From b70d7a99f48d23da62683172b0088e1ffff904ee Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 2 Jun 2009 15:23:55 +1000 Subject: Minor perf tweaks --- src/declarative/canvas/qsimplecanvas.cpp | 48 ++++++++++++++++---------------- src/declarative/canvas/qsimplecanvas_p.h | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp index e582226..59edf74 100644 --- a/src/declarative/canvas/qsimplecanvas.cpp +++ b/src/declarative/canvas/qsimplecanvas.cpp @@ -830,24 +830,25 @@ void QSimpleCanvas::queueUpdate() void QSimpleCanvas::addDirty(QSimpleCanvasItem *c) { + Q_ASSERT(d->isSimpleCanvas()); queueUpdate(); - if (d->isSimpleCanvas()) { - d->oldDirty |= c->d_func()->data()->lastPaintRect; + d->oldDirty |= c->d_func()->data()->lastPaintRect; #if defined(QFX_RENDER_OPENGL) - // Check for filters - QSimpleCanvasItem *fi = c->parent(); - while(fi) { - if (fi->d_func()->data()->dirty) { - break; - } else if (fi->filter()) { - fi->update(); - break; - } - fi = fi->parent(); + // ### Is this parent crawl going to be a problem for scenes with nots + // of things changing? + // Check for filters + QSimpleCanvasItem *fi = c->parent(); + while(fi) { + if (fi->d_func()->data()->dirty) { + break; + } else if (fi->filter()) { + fi->update(); + break; } -#endif - d->dirtyItems.append(c); + fi = fi->parent(); } +#endif + d->dirtyItems.append(c); } QRect QSimpleCanvasPrivate::dirtyItemClip() const @@ -867,7 +868,7 @@ QRect QSimpleCanvasPrivate::dirtyItemClip() const return rv; } -QRegion QSimpleCanvasPrivate::resetDirty() +QRect QSimpleCanvasPrivate::resetDirty() { if (isSimpleCanvas()) { #if defined(QFX_RENDER_OPENGL) @@ -883,11 +884,11 @@ QRegion QSimpleCanvasPrivate::resetDirty() oldDirty = QRect(); if (fullUpdate()) - return QRegion(); + return QRect(); else - return QRegion(r); + return r; } else { - return QRegion(); + return QRect(); } } @@ -914,6 +915,7 @@ QSimpleCanvasItem *QSimpleCanvas::focusItem(QSimpleCanvasItem *item) const bool QSimpleCanvas::event(QEvent *e) { if (e->type() == QEvent::User && d->isSimpleCanvas()) { + int tbf = d->frameTimer.restart(); d->timer = 0; d->isSetup = true; #if defined(QFX_RENDER_OPENGL1) @@ -924,9 +926,7 @@ bool QSimpleCanvas::event(QEvent *e) d->root->d_func()->setupPainting(0, rect()); #endif - QRegion r = d->resetDirty(); - - int tbf = d->frameTimer.restart(); + QRect r = d->resetDirty(); #if defined(QFX_RENDER_QPAINTER) if (r.isEmpty() || fullUpdate()) @@ -935,12 +935,12 @@ bool QSimpleCanvas::event(QEvent *e) repaint(r); emit framePainted(); #else - QRect br = r.boundingRect(); - QRect nr(br.x(), height() - br.y() - br.height(), br.width(), br.height()); + + QRect nr(r.x(), height() - r.y() - r.height(), r.width(), r.height()); if (r.isEmpty() || fullUpdate()) d->egl.updateGL(); - else + else d->egl.updateGL(nr); emit framePainted(); #endif diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h index d9ed4ac..b284c6c 100644 --- a/src/declarative/canvas/qsimplecanvas_p.h +++ b/src/declarative/canvas/qsimplecanvas_p.h @@ -126,7 +126,7 @@ public: #else QRect oldDirty; #endif - QRegion resetDirty(); + QRect resetDirty(); void paint(QPainter &p); -- cgit v0.12 From bc45ef6135b6a01d7fa601765647f2607ee047c8 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 3 Jun 2009 11:56:45 +1000 Subject: OpenGL perf improvements --- src/declarative/canvas/qsimplecanvas.cpp | 3 + src/declarative/canvas/qsimplecanvas_opengl.cpp | 187 +++++++++---- src/declarative/canvas/qsimplecanvasitem.cpp | 4 +- src/declarative/canvas/qsimplecanvasitem.h | 11 +- src/declarative/canvas/qsimplecanvasitem_p.h | 4 +- src/declarative/fx/qfximage.cpp | 348 ++++++++++-------------- src/declarative/fx/qfxrect.cpp | 312 ++++++++------------- src/declarative/fx/qfxtext.cpp | 92 +------ src/declarative/opengl/gltexture.cpp | 65 +++-- src/declarative/opengl/gltexture.h | 5 +- 10 files changed, 473 insertions(+), 558 deletions(-) diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp index 59edf74..f1ff61b 100644 --- a/src/declarative/canvas/qsimplecanvas.cpp +++ b/src/declarative/canvas/qsimplecanvas.cpp @@ -921,6 +921,9 @@ bool QSimpleCanvas::event(QEvent *e) #if defined(QFX_RENDER_OPENGL1) unsigned int zero = 0; d->root->d_func()->setupPainting(0, rect(), &zero); +#elif defined(QFX_RENDER_OPENGL2) + ++d->paintVersion; + d->root->d_func()->setupPainting(0); #else ++d->paintVersion; d->root->d_func()->setupPainting(0, rect()); diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp index ec809ff..dd57c14 100644 --- a/src/declarative/canvas/qsimplecanvas_opengl.cpp +++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE void CanvasEGLWidget::paintGL() { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); _canvas->paintGL(); @@ -112,13 +112,16 @@ void QSimpleCanvasPrivate::paintGL() lrpTimer.start(); QSimpleCanvasItemPrivate::GLPaintParameters p; + QSimpleCanvasItem::GLPainter painter; + p.sceneRect = QRect(0, 0, q->width(), q->height()); p.clipRect = p.sceneRect; p.stencilValue = 0; p.opacity = 1; p.forceParamRefresh = false; - if (!isSetup) - root->d_func()->setupPainting(0, QRect()); + p.painter = &painter; + if (!isSetup) + root->d_func()->setupPainting(0); root->d_func()->paint(p); lrpTime = lrpTimer.elapsed(); @@ -195,7 +198,8 @@ void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters ¶ms, childParams.boundingRect = child->boundingRect(); if (child->filter() && child->filter()->enabled()) { - QSimpleCanvasItem::GLPainter painter(q); + QSimpleCanvasItem::GLPainter &painter = *params.painter; + painter.item = q; painter.activeTransform = child->d_func()->data()->transformActive; painter.activeOpacity = child->d_func()->data()->activeOpacity; painter.sceneClipRect = params.clipRect; @@ -229,34 +233,35 @@ void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child) QSimpleCanvasItemData *const childData = childPrivate->data(); childData->activeOpacity = myData->activeOpacity; - if (childData->visible != 1) + if (childData->visible != 1.) childData->activeOpacity *= childData->visible; - if (childData->activeOpacity != 0) { + if (childData->activeOpacity != 0.) { + QSimpleCanvas::Matrix &am = childData->transformActive; + am = myData->transformActive; + // Calculate child's transform const qreal x = childData->x; const qreal y = childData->y; const qreal scale = childPrivate->scale; QSimpleCanvasItem::Flip flip = childData->flip; - QSimpleCanvas::Matrix &am = childData->transformActive; - am = myData->transformActive; if (x != 0. || y != 0.) am.translate(x, y); if (scale != 1.) { - QPointF to = childPrivate->transformOrigin(); - bool translate = (to.x() != 0. || to.y() != 0.); - if (translate) + if (childPrivate->origin == QSimpleCanvasItem::TopLeft) { + am.scale(scale, scale); + } else { + QPointF to = childPrivate->transformOrigin(); am.translate(to.x(), to.y()); - am.scale(scale, scale); - if (translate) + am.scale(scale, scale); am.translate(-to.x(), -to.y()); + } } if (childData->transformUser) am *= *childData->transformUser; - if (flip) { QRectF br = child->boundingRect(); am.translate(br.width() / 2., br.height() / 2); @@ -268,8 +273,10 @@ void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child) } } -QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding) +//#define QSIMPLECANVAS_DISABLE_TREE_CLIPPING +QRectF QSimpleCanvasItemPrivate::setupPainting(int version) { + static QRectF scene(-1., -1., 2., 2.); Q_Q(QSimpleCanvasItem); bool hasContents = options & QSimpleCanvasItem::HasContents; @@ -285,17 +292,34 @@ QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &boundin rv = active.mapRect(filteredBoundRect); } - - for (int ii = 0; ii < children.count(); ++ii) { - QSimpleCanvasItem *child = children.at(ii); - setupChildState(child); - - QSimpleCanvasItemData *childData = child->d_func()->data(); - if (childData->activeOpacity != 0) - rv |= child->d_func()->setupPainting(version, bounding); - } +#ifdef QSIMPLECANVAS_DISABLE_TREE_CLIPPING + myData->doNotPaint = false; + myData->doNotPaintChildren = false; +#else + myData->doNotPaint = !hasContents || !rv.intersects(scene); + myData->doNotPaintChildren = hasContents && myData->doNotPaint && + (clip != QSimpleCanvasItem::NoClip); +#endif + + if (myData->doNotPaintChildren) { + rv = QRectF(); + } else { + for (int ii = 0; ii < children.count(); ++ii) { + QSimpleCanvasItem *child = children.at(ii); + setupChildState(child); + + QSimpleCanvasItemData *childData = child->d_func()->data(); + if (childData->activeOpacity != 0) + rv |= child->d_func()->setupPainting(version); + } + +#ifndef QSIMPLECANVAS_DISABLE_TREE_CLIPPING + myData->doNotPaintChildren |= !rv.intersects(scene); +#endif + } myData->lastPaintRect = rv; + return rv; } @@ -306,6 +330,10 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas Q_Q(QSimpleCanvasItem); + bool doNotPaintChildren = data()->doNotPaintChildren; + if (doNotPaintChildren) + return; + GLPaintParameters params = oldParams; qreal width = params.boundingRect.width(); @@ -327,12 +355,12 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); ConstantColorShader *shader = basicShaders()->constantColor(); + params.painter->invalidate(); shader->enable(); shader->setTransform(data()->transformActive); shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - shader->disableAttributeArray(ConstantColorShader::Vertices); glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -369,9 +397,11 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas } } - if (layer & QSimpleCanvasFilter::Item && - q->options() & QSimpleCanvasItem::HasContents) { - QSimpleCanvasItem::GLPainter painter(q); + bool doNotPaint = data()->doNotPaint; + + if (!doNotPaint && layer & QSimpleCanvasFilter::Item) { + QSimpleCanvasItem::GLPainter &painter = *params.painter; + painter.item = q; painter.activeTransform = data()->transformActive; painter.activeOpacity = data()->activeOpacity; painter.sceneClipRect = params.clipRect; @@ -390,14 +420,14 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); - + + params.painter->invalidate(); ConstantColorShader *shader = basicShaders()->constantColor(); shader->enable(); shader->setTransform(data()->transformActive); shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - shader->disableAttributeArray(ConstantColorShader::Vertices); glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -405,43 +435,76 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas } } +enum ShaderType { ST_None, ST_SingleTexture, ST_SingleTextureOpacity, ST_Color }; + +QSimpleCanvasItem::GLPainter::GLPainter() +: item(0), activeOpacity(1), flags(0) +{ +} + +QSimpleCanvasItem::GLPainter::GLPainter(QSimpleCanvasItem *i) +: item(i), activeOpacity(1), flags(0) +{ +} + QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader() { if (activeOpacity == 1.) { - item->basicShaders()->singleTexture()->enable(); - item->basicShaders()->singleTexture()->setTransform(activeTransform); - return item->basicShaders()->singleTexture(); + SingleTextureShader *shader = item->basicShaders()->singleTexture(); + if (flags != ST_SingleTexture) { + shader->enable(); + flags = ST_SingleTexture; + } + + shader->setTransform(activeTransform); + return shader; } else { - item->basicShaders()->singleTextureOpacity()->enable(); - item->basicShaders()->singleTextureOpacity()->setTransform(activeTransform); - item->basicShaders()->singleTextureOpacity()->setOpacity(activeOpacity); - return item->basicShaders()->singleTextureOpacity(); + SingleTextureOpacityShader *shader = item->basicShaders()->singleTextureOpacity(); + + if (flags != ST_SingleTextureOpacity) { + shader->enable(); + flags = ST_SingleTextureOpacity; + } + + shader->setTransform(activeTransform); + shader->setOpacity(activeOpacity); + return shader; } +} +void QSimpleCanvasItem::GLPainter::invalidate() +{ + flags = ST_None; } QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color) { - QColor c = color; - item->basicShaders()->constantColor()->enable(); - if (activeOpacity != 1.) { - c.setAlpha(int(c.alpha() * activeOpacity)); + QColor c = color; + + ConstantColorShader *shader = item->basicShaders()->constantColor(); + + if (flags != ST_Color) { + shader->enable(); + flags = ST_Color; } - item->basicShaders()->constantColor()->setColor(c); - item->basicShaders()->constantColor()->setTransform(activeTransform); + if (activeOpacity != 1.) + c.setAlpha(int(c.alpha() * activeOpacity)); + + shader->setColor(c); + shader->setTransform(activeTransform); - return item->basicShaders()->constantColor(); + return shader; } -void QSimpleCanvasItem::GLPainter::drawPixmap(const QPointF &point, - const GLTexture &texture) +void QSimpleCanvasItem::GLPainter::drawPixmap(const QPointF &point, + const GLTexture &texture) { drawPixmap(QRectF(point, QSizeF(texture.width(), texture.height())), texture); } -void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect, - const GLTexture &img) +void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect, + const GLTexture &img) { QGLShaderProgram *shader = useTextureShader(); @@ -466,9 +529,33 @@ void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect, glBindTexture(GL_TEXTURE_2D, img.texture()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +void QSimpleCanvasItem::GLPainter::fillRect(const QRectF &rect, + const QColor &color) +{ + if (color.alpha() == 0xFF) + glDisable(GL_BLEND); + + QGLShaderProgram *shader = useColorShader(color); + float x = rect.x(); + float y = rect.y(); + float width = rect.width(); + float height = rect.height(); + + GLfloat vertices[] = { x, height, + width, height, + x, y, + + width, height, + x, y, + width, y }; + + shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); + glDrawArrays(GL_TRIANGLES, 0, 6); - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); + if (color.alpha() == 0xFF) + glEnable(GL_BLEND); } QT_END_NAMESPACE diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp index f2222a9..7451a5f 100644 --- a/src/declarative/canvas/qsimplecanvasitem.cpp +++ b/src/declarative/canvas/qsimplecanvasitem.cpp @@ -51,8 +51,8 @@ QT_BEGIN_NAMESPACE QSimpleCanvasItemData::QSimpleCanvasItemData() : buttons(Qt::NoButton), flip(QSimpleCanvasItem::NoFlip), dirty(false), transformValid(true), doNotPaint(false), - doNotPaintChildren(false), x(0), y(0), z(0), visible(1), - transformUser(0), transformVersion(0), activeOpacity(1) + doNotPaintChildren(false), x(0), y(0), z(0), + visible(1), transformUser(0), transformVersion(0), activeOpacity(1) { } diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h index f817799..68219de 100644 --- a/src/declarative/canvas/qsimplecanvasitem.h +++ b/src/declarative/canvas/qsimplecanvasitem.h @@ -167,7 +167,8 @@ public: class GLPainter { public: - GLPainter(QSimpleCanvasItem *i) : item(i), activeOpacity(1) {} + GLPainter(); + GLPainter(QSimpleCanvasItem *i); QSimpleCanvasItem *item; QSimpleCanvas::Matrix activeTransform; qreal activeOpacity; @@ -175,9 +176,13 @@ public: QGLShaderProgram *useTextureShader(); QGLShaderProgram *useColorShader(const QColor &); - void drawPixmap(const QPointF &, const GLTexture &); - void drawPixmap(const QRectF &, const GLTexture &); + void drawPixmap(const QPointF &, const GLTexture &); + void drawPixmap(const QRectF &, const GLTexture &); + void fillRect(const QRectF &, const QColor &); + + void invalidate(); private: + int flags; GLPainter(const GLPainter &); GLPainter &operator=(const GLPainter &); }; diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h index e2deab2..27ee0a2 100644 --- a/src/declarative/canvas/qsimplecanvasitem_p.h +++ b/src/declarative/canvas/qsimplecanvasitem_p.h @@ -218,9 +218,11 @@ public: #endif float opacity; bool forceParamRefresh; + + QSimpleCanvasItem::GLPainter *painter; }; #if defined(QFX_RENDER_OPENGL2) - QRectF setupPainting(int version, const QRect &bounding); + QRectF setupPainting(int version); #elif defined(QFX_RENDER_OPENGL1) QRectF setupPainting(int version, const QRect &bounding, unsigned int *zero); #endif diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 22e5d97..1fc84eb 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -448,9 +448,9 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, texVertices[6] = tileWidth; texVertices[7] = tileHeight; } else { texVertices[0] = 0; texVertices[1] = 0; - texVertices[2] = 1; texVertices[3] = 0; - texVertices[4] = 0; texVertices[5] = 1; - texVertices[6] = 1; texVertices[7] = 1; + texVertices[2] = d->_tex.glWidth(); texVertices[3] = 0; + texVertices[4] = 0; texVertices[5] = d->_tex.glHeight(); + texVertices[6] = d->_tex.glWidth(); texVertices[7] = d->_tex.glHeight(); } return 8; @@ -481,25 +481,57 @@ void QFxImage::paintGLContents(GLPainter &p) restoreBlend = true; } + d->checkDirty(); + if (d->_tiled || (!d->_scaleGrid || d->_scaleGrid->isNull())) { - GLfloat vertices[8]; - GLfloat texVertices[8]; - GLTexture *tex = 0; + if (!d->_tiled) { + + float widthV = width(); + float heightV = height(); + float glWidth = d->_tex.glWidth(); + float glHeight = d->_tex.glHeight(); + + float vert[] = { + 0, heightV, + widthV, heightV, + 0, 0, - QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8); + widthV, heightV, + 0, 0, + widthV, 0 }; - shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); + float tex[] = { + 0, 0, + glWidth, 0, + 0, glHeight, + + glWidth, 0, + 0, glHeight, + glWidth, glHeight + }; + + shader->setAttributeArray(SingleTextureShader::Vertices, vert, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, tex, 2); + glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); + glDrawArrays(GL_TRIANGLES, 0, 6); + + } else { - glBindTexture(GL_TEXTURE_2D, tex->texture()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + GLfloat vertices[8]; + GLfloat texVertices[8]; + GLTexture *tex = 0; - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); + QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8); + + shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); + + glBindTexture(GL_TEXTURE_2D, tex->texture()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } } else { - d->checkDirty(); float imgWidth = d->_pix.width(); float imgHeight = d->_pix.height(); @@ -546,235 +578,155 @@ void QFxImage::paintGLContents(GLPainter &p) float vert1[] = { 0, 0, 0, imgtop, imgleft, 0, + + 0, imgtop, + imgleft, 0, + imgleft, imgtop, + + imgleft, 0, imgleft, imgtop, imgright, 0, - imgright, imgtop, - widthV, 0, - widthV, imgtop }; - float tex1[] = { 0, 1, - 0, textop, - texleft, 1, - texleft, textop, - texright, 1, - texright, textop, - 1, 1, - 1, textop }; - float vert2[] = { 0, imgtop, - 0, imgbottom, + imgleft, imgtop, - imgleft, imgbottom, + imgright, 0, imgright, imgtop, - imgright, imgbottom, - widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, - 0, texbottom, - texleft, textop, - texleft, texbottom, - texright, textop, - texright, texbottom, - 1, textop, - 1, texbottom }; - float vert3[] = { 0, imgbottom, - 0, heightV, - imgleft, imgbottom, - imgleft, heightV, - imgright, imgbottom, - imgright, heightV, - widthV, imgbottom, - widthV, heightV }; - float tex3[] = { 0, texbottom, - 0, 0, - texleft, texbottom, - texleft, 0, - texright, texbottom, - texright, 0, - 1, texbottom, - 1, 0 }; - - glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); - shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); - } + imgright, 0, + imgright, imgtop, + widthV, 0, - if (restoreBlend) - glEnable(GL_BLEND); -} -#elif defined(QFX_RENDER_OPENGL1) -void QFxImage::paintGLContents(GLPainter &p) -{ - Q_D(QFxImage); - if (d->_pix.isNull()) - return; + imgright, imgtop, + widthV, 0, + widthV, imgtop, - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(p.activeTransform.data()); + 0, imgtop, + 0, imgbottom, + imgleft, imgtop, - bool restoreBlend = false; - if (isOpaque() && p.activeOpacity == 1) { - glDisable(GL_BLEND); - restoreBlend = true; - } + 0, imgbottom, + imgleft, imgtop, + imgleft, imgbottom, - glEnable(GL_TEXTURE_2D); - if (p.activeOpacity == 1.) { - GLint i = GL_REPLACE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - } else { - GLint i = GL_MODULATE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - glColor4f(1, 1, 1, p.activeOpacity); - } + imgleft, imgtop, + imgleft, imgbottom, + imgright, imgtop, - if (d->_tiled || !d->_scaleGrid || d->_scaleGrid->isNull()) { + imgleft, imgbottom, + imgright, imgtop, + imgright, imgbottom, - GLfloat vertices[8]; - GLfloat texVertices[8]; - GLTexture *tex = 0; + imgright, imgtop, + imgright, imgbottom, + widthV, imgtop, - QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8); + imgright, imgbottom, + widthV, imgtop, + widthV, imgbottom, - glBindTexture(GL_TEXTURE_2D, tex->texture()); + 0, imgbottom, + 0, heightV, + imgleft, imgbottom, - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + 0, heightV, + imgleft, imgbottom, + imgleft, heightV, - glVertexPointer(2, GL_FLOAT, 0, vertices); - glTexCoordPointer(2, GL_FLOAT, 0, texVertices); + imgleft, imgbottom, + imgleft, heightV, + imgright, imgbottom, + imgleft, heightV, + imgright, imgbottom, + imgright, heightV, - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + imgright, imgbottom, + imgright, heightV, + widthV, imgbottom, - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + imgright, heightV, + widthV, imgbottom, + widthV, heightV }; - } else { - d->checkDirty(); + float tex1[] = { 0, 1, + 0, textop, + texleft, 1, - float imgWidth = d->_pix.width(); - float imgHeight = d->_pix.height(); - if (!imgWidth || !imgHeight) { - if (restoreBlend) - glEnable(GL_BLEND); - return; - } + 0, textop, + texleft, 1, + texleft, textop, - float widthV = width(); - float heightV = height(); + texleft, 1, + texleft, textop, + texright, 1, - float texleft = 0; - float texright = 1; - float textop = 1; - float texbottom = 0; - float imgleft = 0; - float imgright = widthV; - float imgtop = 0; - float imgbottom = heightV; + texleft, textop, + texright, 1, + texright, textop, - const int sgl = d->_scaleGrid->left(); - const int sgr = d->_scaleGrid->right(); - const int sgt = d->_scaleGrid->top(); - const int sgb = d->_scaleGrid->bottom(); + texright, 1, + texright, textop, + 1, 1, - if (sgl) { - texleft = float(sgl) / imgWidth; - imgleft = sgl; - } - if (sgr) { - texright = 1. - float(sgr) / imgWidth; - imgright = widthV - sgr; - } - if (sgt) { - textop = 1. - float(sgb) / imgHeight; - imgtop = sgt; - } - if (sgb) { - texbottom = float(sgt) / imgHeight; - imgbottom = heightV - sgb; - } + texright, textop, + 1, 1, + 1, textop, - float vert1[] = { 0, 0, - 0, imgtop, - imgleft, 0, - imgleft, imgtop, - imgright, 0, - imgright, imgtop, - widthV, 0, - widthV, imgtop }; - float tex1[] = { 0, 1, 0, textop, - texleft, 1, + 0, texbottom, texleft, textop, - texright, 1, - texright, textop, - 1, 1, - 1, textop }; - float vert2[] = { 0, imgtop, - 0, imgbottom, - imgleft, imgtop, - imgleft, imgbottom, - imgright, imgtop, - imgright, imgbottom, - widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, + 0, texbottom, texleft, textop, texleft, texbottom, + + texleft, textop, + texleft, texbottom, + texright, textop, + + texleft, texbottom, + texright, textop, + texright, texbottom, + texright, textop, texright, texbottom, 1, textop, - 1, texbottom }; - float vert3[] = { 0, imgbottom, - 0, heightV, - imgleft, imgbottom, - imgleft, heightV, - imgright, imgbottom, - imgright, heightV, - widthV, imgbottom, - widthV, heightV }; - float tex3[] = { 0, texbottom, + + texright, texbottom, + 1, textop, + 1, texbottom, + + 0, texbottom, + 0, 0, + texleft, texbottom, + 0, 0, texleft, texbottom, texleft, 0, + + texleft, texbottom, + texleft, 0, + texright, texbottom, + + texleft, 0, + texright, texbottom, + texright, 0, + texright, texbottom, texright, 0, 1, texbottom, + + texright, 0, + 1, texbottom, 1, 0 }; glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - glVertexPointer(2, GL_FLOAT, 0, vert1); - glTexCoordPointer(2, GL_FLOAT, 0, tex1); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert2); - glTexCoordPointer(2, GL_FLOAT, 0, tex2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert3); - glTexCoordPointer(2, GL_FLOAT, 0, tex3); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); + glDrawArrays(GL_TRIANGLES, 0, 54); } - if (restoreBlend) + if (restoreBlend) glEnable(GL_BLEND); } #endif diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index c156753..3d6897e 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -692,6 +692,7 @@ void QFxRect::paintGLContents(GLPainter &p) colors[i+3] = c.alphaF() * p.activeOpacity; colors[i+7] = colors[i+3]; } + p.invalidate(); ColorShader *shader = basicShaders()->color(); shader->enable(); shader->setTransform(p.activeTransform); @@ -702,19 +703,9 @@ void QFxRect::paintGLContents(GLPainter &p) shader->disableAttributeArray(ColorShader::Vertices); shader->disableAttributeArray(ColorShader::Colors); } else { - QGLShaderProgram *shader = p.useColorShader(d->getColor()); - float widthV = width(); - float heightV = height(); - - GLfloat vertices[] = { 0, heightV, - widthV, heightV, - 0, 0, - widthV, 0 }; + p.fillRect(QRectF(0, 0, width(), height()), d->getColor()); - shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - shader->disableAttributeArray(ConstantColorShader::Vertices); } } else { qreal offset = 0; @@ -768,236 +759,155 @@ void QFxRect::paintGLContents(GLPainter &p) float vert1[] = { -pw/2, -pw/2, -pw/2, imgtop, imgleft, -pw/2, + + -pw/2, imgtop, + imgleft, -pw/2, + imgleft, imgtop, + + imgleft, -pw/2, + imgleft, imgtop, + imgright, -pw/2, + imgleft, imgtop, imgright, -pw/2, imgright, imgtop, + + imgright, -pw/2, + imgright, imgtop, widthV, -pw/2, - widthV, imgtop }; - float tex1[] = { 0, 0, - 0, textop, - texleft, 0, - texleft, textop, - texright, 0, - texright, textop, - 1, 0, - 1, textop }; - float vert2[] = { -pw/2, imgtop, - -pw/2, imgbottom, - imgleft, imgtop, - imgleft, imgbottom, + imgright, imgtop, - imgright, imgbottom, + widthV, -pw/2, widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, - 0, texbottom, - texleft, textop, - texleft, texbottom, - texright, textop, - texright, texbottom, - 1, textop, - 1, texbottom }; - float vert3[] = { -pw/2, heightV, + + -pw/2, heightV, -pw/2, imgbottom, imgleft, heightV, + + -pw/2, imgbottom, + imgleft, heightV, + imgleft, imgbottom, + + imgleft, heightV, imgleft, imgbottom, imgright, heightV, + + imgleft, imgbottom, + imgright, heightV, + imgright, imgbottom, + + imgright, heightV, imgright, imgbottom, widthV, heightV, - widthV, imgbottom }; - float tex3[] = { 0, 1, - 0, texbottom, - texleft, 1, - texleft, texbottom, - texright, 1, - texright, texbottom, - 1, 1, - 1, texbottom }; - glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); + imgright, imgbottom, + widthV, heightV, + widthV, imgbottom, - shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - if (yMiddles) { - shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - } - shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); + -pw/2, imgtop, + -pw/2, imgbottom, + imgleft, imgtop, - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); - } -} -#elif defined(QFX_RENDER_OPENGL1) -void QFxRect::paintGLContents(GLPainter &p) -{ - Q_D(QFxRect); + -pw/2, imgbottom, + imgleft, imgtop, + imgleft, imgbottom, - float widthV = width(); - float heightV = height(); - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(p.activeTransform.data()); - - if (d->_radius == 0 && (!d->_pen || !d->_pen->isValid())) { - GLfloat vertices[] = { 0, heightV, - widthV, heightV, - 0, 0, - widthV, 0 }; + imgleft, imgtop, + imgleft, imgbottom, + imgright, imgtop, - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2,GL_FLOAT,0,vertices); + imgleft, imgbottom, + imgright, imgtop, + imgright, imgbottom, - QColor c; - if (d->_gradcolor.isValid()) - c = d->_color; - else - c = d->getColor(); - float r = c.redF(); - float g = c.greenF(); - float b = c.blueF(); - float a = c.alphaF() * p.activeOpacity; - - float r2 = r; float g2 = g; float b2 = b; float a2 = a; - - if (d->_gradcolor.isValid()) { - r2 = d->_gradcolor.redF(); - g2 = d->_gradcolor.greenF(); - b2 = d->_gradcolor.blueF(); - a2 = d->_gradcolor.alphaF() * p.activeOpacity; - } + imgright, imgtop, + imgright, imgbottom, + widthV, imgtop, + + imgright, imgbottom, + widthV, imgtop, + widthV, imgbottom }; - GLfloat colors[] = { r2, g2, b2, a2, - r2, g2, b2, a2, - r, g, b, a, - r, g, b, a }; - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4,GL_FLOAT,0,colors); + float tex1[] = { 0, 0, + 0, textop, + texleft, 0, - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + 0, textop, + texleft, 0, + texleft, textop, - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - } else { - qreal offset = 0; - if (d->_radius > 0) { - generateRoundedRect(); - offset = d->_radius; - } else { - generateBorderedRect(); - offset = d->pen()->width(); - } + texleft, 0, + texleft, textop, + texright, 0, - if (p.activeOpacity == 1.) { - GLint i = GL_REPLACE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - } else { - GLint i = GL_MODULATE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - glColor4f(1, 1, 1, p.activeOpacity); - } + texleft, textop, + texright, 0, + texright, textop, - float texWidth = d->_rectTexture.width(); - float texHeight = d->_rectTexture.height(); - if (!texWidth || !texHeight) - return; + texright, 0, + texright, textop, + 1, 0, - float widthV = width(); - float heightV = height(); - - float texleft = 0; - float texright = 1; - float textop = 1; - float texbottom = 0; - float imgleft = 0; - float imgright = widthV; - float imgtop = 0; - float imgbottom = heightV; - - texleft = float(offset) / texWidth; - imgleft = offset; - texright = 1. - float(offset) / texWidth; - imgright = widthV - offset; - textop = 1. - float(offset) / texHeight; - imgtop = offset; - texbottom = float(offset) / texHeight; - imgbottom = heightV - offset; - - float vert1[] = { 0, 0, - 0, imgtop, - imgleft, 0, - imgleft, imgtop, - imgright, 0, - imgright, imgtop, - widthV, 0, - widthV, imgtop }; - float tex1[] = { 0, 1, - 0, textop, + texright, textop, + 1, 0, + 1, textop, + + 0, 1, + 0, texbottom, texleft, 1, - texleft, textop, + + 0, texbottom, + texleft, 1, + texleft, texbottom, + + texleft, 1, + texleft, texbottom, texright, 1, - texright, textop, + + texleft, texbottom, + texright, 1, + texright, texbottom, + + texright, 1, + texright, texbottom, 1, 1, - 1, textop }; - float vert2[] = { 0, imgtop, - 0, imgbottom, - imgleft, imgtop, - imgleft, imgbottom, - imgright, imgtop, - imgright, imgbottom, - widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, + + texright, texbottom, + 1, 1, + 1, texbottom, + + 0, textop, 0, texbottom, texleft, textop, + + 0, texbottom, + texleft, textop, + texleft, texbottom, + + texleft, textop, texleft, texbottom, texright, textop, - texright, texbottom, - 1, textop, - 1, texbottom }; - float vert3[] = { 0, imgbottom, - 0, heightV, - imgleft, imgbottom, - imgleft, heightV, - imgright, imgbottom, - imgright, heightV, - widthV, imgbottom, - widthV, heightV }; - float tex3[] = { 0, texbottom, - 0, 0, + texleft, texbottom, - texleft, 0, + texright, textop, texright, texbottom, - texright, 0, - 1, texbottom, - 1, 0 }; - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); + texright, textop, + texright, texbottom, + 1, textop, - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + texright, texbottom, + 1, textop, + 1, texbottom }; - glVertexPointer(2, GL_FLOAT, 0, vert1); - glTexCoordPointer(2, GL_FLOAT, 0, tex1); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert2); - glTexCoordPointer(2, GL_FLOAT, 0, tex2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert3); - glTexCoordPointer(2, GL_FLOAT, 0, tex3); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); + glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); + glDrawArrays(GL_TRIANGLES, 0, 36 + (yMiddles?18:0)); } } #endif diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index 702ec81..1b5c080 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -796,103 +796,31 @@ void QFxText::paintGLContents(GLPainter &p) QGLShaderProgram *shader = p.useTextureShader(); GLfloat vertices[] = { x, y + heightV, - x + widthV, y + heightV, - x, y, - x + widthV, y }; + x + widthV, y + heightV, + x, y, + + x + widthV, y + heightV, + x, y, + x + widthV, y }; GLfloat texVertices[] = { 0, 0, 1, 0, 0, 1, + + 1, 0, + 0, 1, 1, 1 }; shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); glBindTexture(GL_TEXTURE_2D, d->tex.texture()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDrawArrays(GL_TRIANGLES, 0, 6); shader->disableAttributeArray(SingleTextureShader::Vertices); shader->disableAttributeArray(SingleTextureShader::TextureCoords); } -#elif defined(QFX_RENDER_OPENGL) -void QFxText::paintGLContents(GLPainter &p) -{ - Q_D(QFxText); - d->checkImgCache(); - if (d->imgCache.isNull()) - return; - - int w = width(); - int h = height(); - - float x = 0; - float y = 0; - - switch (d->hAlign) { - case AlignLeft: - x = 0; - break; - case AlignRight: - x = w - d->imgCache.width(); - break; - case AlignHCenter: - x = (w - d->imgCache.width()) / 2; - break; - } - - switch (d->vAlign) { - case AlignTop: - y = 0; - break; - case AlignBottom: - y = h - d->imgCache.height(); - break; - case AlignVCenter: - y = (h - d->imgCache.height()) / 2; - break; - } - - float widthV = d->imgCache.width(); - float heightV = d->imgCache.height(); - - GLfloat vertices[] = { x, y + heightV, - x + widthV, y + heightV, - x, y, - x + widthV, y }; - - GLfloat texVertices[] = { 0, 0, - 1, 0, - 0, 1, - 1, 1 }; - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(p.activeTransform.data()); - glEnable(GL_TEXTURE_2D); - if (p.activeOpacity == 1.) { - GLint i = GL_REPLACE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - } else { - GLint i = GL_MODULATE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - glColor4f(1, 1, 1, p.activeOpacity); - } - - glBindTexture(GL_TEXTURE_2D, d->tex.texture()); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - glVertexPointer(2, GL_FLOAT, 0, vertices); - glTexCoordPointer(2, GL_FLOAT, 0, texVertices); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); -} - #endif void QFxText::componentComplete() diff --git a/src/declarative/opengl/gltexture.cpp b/src/declarative/opengl/gltexture.cpp index 199b362..bebee08 100644 --- a/src/declarative/opengl/gltexture.cpp +++ b/src/declarative/opengl/gltexture.cpp @@ -79,7 +79,8 @@ public: GLTexturePrivate(GLTexture *_q) : q(_q), texture(0), width(0), height(0), horizWrap(GLTexture::Repeat), vertWrap(GLTexture::Repeat), - minFilter(GLTexture::Linear), magFilter(GLTexture::Linear) + minFilter(GLTexture::Linear), magFilter(GLTexture::Linear), + glWidth(1.), glHeight(1.) { } @@ -92,6 +93,9 @@ public: GLTexture::FilterMode minFilter; GLTexture::FilterMode magFilter; + qreal glWidth; + qreal glHeight; + void genTexture(); }; @@ -167,32 +171,43 @@ static inline int npot(int size) by explicitly setting the size, or by previously setting an image), it will be destroyed and a new texture created with \a img's contents and size. */ -void GLTexture::setImage(const QImage &img) +void GLTexture::setImage(const QImage &img, ImageMode mode) { if (img.isNull()) return; d->genTexture(); - //QImage dataImage = img.scaled(npot(img.width()), npot(img.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - QImage dataImage = QGLWidget_convertToGLFormat(img); - glBindTexture(GL_TEXTURE_2D, d->texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(), - dataImage.height(), 0, - (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, - GL_UNSIGNED_BYTE, dataImage.bits()); - d->width = dataImage.width(); - d->height = dataImage.height(); - -#if 0 - glGenerateMipmap(GL_TEXTURE_2D); - int e = glGetError(); - if (d->magFilter == Linear) - setMagFilter(MipmapLinear); - if (d->minFilter == Linear) - setMinFilter((GLTexture::FilterMode)GL_LINEAR_MIPMAP_LINEAR); -#endif + + // ### Need to respect mode + if (img.format() == QImage::Format_RGB16) { + QImage dataImage = img.mirrored(); + int max = (img.width() > img.height())?img.width():img.height(); + max = npot(max); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, max, + max, 0, + GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, 0); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dataImage.width(), + dataImage.height(), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + dataImage.bits()); + + d->glWidth = qreal(dataImage.width()) / qreal(max); + d->glHeight = qreal(dataImage.height()) / qreal(max); + } else { + QImage dataImage = QGLWidget_convertToGLFormat(img); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(), + dataImage.height(), 0, + (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, + GL_UNSIGNED_BYTE, dataImage.bits()); + } + + d->width = img.width(); + d->height = img.height(); } void GLTexture::copyImage(const QImage &img, const QPoint &point, @@ -219,6 +234,16 @@ int GLTexture::height() const return d->height; } +qreal GLTexture::glWidth() const +{ + return d->glWidth; +} + +qreal GLTexture::glHeight() const +{ + return d->glHeight; +} + /*! Sets the \a size of the texture. This will destroy the current contents of the texture. If an image has been assigned, it will need to be reassigned diff --git a/src/declarative/opengl/gltexture.h b/src/declarative/opengl/gltexture.h index 787c9a5..d301d8a 100644 --- a/src/declarative/opengl/gltexture.h +++ b/src/declarative/opengl/gltexture.h @@ -69,11 +69,14 @@ public: bool isNull() const; void clear(); - void setImage(const QImage &); + enum ImageMode { NonPowerOfTwo, PowerOfTwo }; + void setImage(const QImage &, ImageMode = NonPowerOfTwo); void copyImage(const QImage &, const QPoint & = QPoint(0, 0), const QRect & = QRect()); int width() const; int height() const; + qreal glWidth() const; + qreal glHeight() const; QSize size() const; void setSize(const QSize &); -- cgit v0.12 From 694b270d78d99e94c8ab7543b7371edbe16ecaab Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 3 Jun 2009 16:09:39 +1000 Subject: Render items with z-order, and render opaque objects first. --- src/declarative/canvas/qsimplecanvas.cpp | 4 +- src/declarative/canvas/qsimplecanvas_opengl.cpp | 55 +++++++++++++++++++++---- src/declarative/canvas/qsimplecanvas_p.h | 1 + src/declarative/canvas/qsimplecanvasitem.h | 6 ++- src/declarative/canvas/qsimplecanvasitem_p.h | 6 ++- src/declarative/fx/qfximage.cpp | 5 ++- 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp index f1ff61b..cb46f94 100644 --- a/src/declarative/canvas/qsimplecanvas.cpp +++ b/src/declarative/canvas/qsimplecanvas.cpp @@ -923,7 +923,9 @@ bool QSimpleCanvas::event(QEvent *e) d->root->d_func()->setupPainting(0, rect(), &zero); #elif defined(QFX_RENDER_OPENGL2) ++d->paintVersion; - d->root->d_func()->setupPainting(0); + d->opaqueList = 0; + int z = 0; + d->root->d_func()->setupPainting(0, z, &d->opaqueList); #else ++d->paintVersion; d->root->d_func()->setupPainting(0, rect()); diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp index dd57c14..659104d 100644 --- a/src/declarative/canvas/qsimplecanvas_opengl.cpp +++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE void CanvasEGLWidget::paintGL() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _canvas->paintGL(); } @@ -120,8 +120,29 @@ void QSimpleCanvasPrivate::paintGL() p.opacity = 1; p.forceParamRefresh = false; p.painter = &painter; - if (!isSetup) - root->d_func()->setupPainting(0); + if (!isSetup) { + opaqueList = 0; + int z = 0; + root->d_func()->setupPainting(0, z, &opaqueList); + } + + glEnable(GL_DEPTH_TEST); + + glDisable(GL_BLEND); + painter.blendEnabled = false; + painter.activeOpacity = 1; + while (opaqueList) { + painter.item = opaqueList; + painter.activeTransform = opaqueList->d_func()->data()->transformActive; + // ### - I don't think this is right + painter.sceneClipRect = p.clipRect; + + opaqueList->paintGLContents(painter); + opaqueList = opaqueList->d_func()->nextOpaque; + } + glEnable(GL_BLEND); + painter.blendEnabled = true; + root->d_func()->paint(p); lrpTime = lrpTimer.elapsed(); @@ -274,7 +295,7 @@ void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child) } //#define QSIMPLECANVAS_DISABLE_TREE_CLIPPING -QRectF QSimpleCanvasItemPrivate::setupPainting(int version) +QRectF QSimpleCanvasItemPrivate::setupPainting(int version, int &z, QSimpleCanvasItem **opaqueList) { static QRectF scene(-1., -1., 2., 2.); Q_Q(QSimpleCanvasItem); @@ -301,16 +322,31 @@ QRectF QSimpleCanvasItemPrivate::setupPainting(int version) (clip != QSimpleCanvasItem::NoClip); #endif + if (!myData->doNotPaint && + (options & QSimpleCanvasItem::IsOpaque) && + (myData->activeOpacity == 1.) && + (clip == 0)) { + + nextOpaque = *opaqueList; + *opaqueList = q; + myData->doNotPaint = true; + + } + + int myZ = z++; + if (myData->doNotPaintChildren) { rv = QRectF(); } else { + zOrderChildren(); + for (int ii = 0; ii < children.count(); ++ii) { QSimpleCanvasItem *child = children.at(ii); setupChildState(child); QSimpleCanvasItemData *childData = child->d_func()->data(); if (childData->activeOpacity != 0) - rv |= child->d_func()->setupPainting(version); + rv |= child->d_func()->setupPainting(version, z, opaqueList); } #ifndef QSIMPLECANVAS_DISABLE_TREE_CLIPPING @@ -318,11 +354,14 @@ QRectF QSimpleCanvasItemPrivate::setupPainting(int version) #endif } + myData->transformActive.translate(0, 0, myZ); + myData->lastPaintRect = rv; return rv; } + void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvasFilter::Layer layer) { if (!layer) @@ -384,8 +423,6 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas params.clipRect = sr; } - zOrderChildren(); - int upto = 0; for (upto = 0; upto < children.count(); ++upto) { QSimpleCanvasItem *c = children.at(upto); @@ -438,12 +475,12 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas enum ShaderType { ST_None, ST_SingleTexture, ST_SingleTextureOpacity, ST_Color }; QSimpleCanvasItem::GLPainter::GLPainter() -: item(0), activeOpacity(1), flags(0) +: item(0), activeOpacity(1), blendEnabled(true), flags(0) { } QSimpleCanvasItem::GLPainter::GLPainter(QSimpleCanvasItem *i) -: item(i), activeOpacity(1), flags(0) +: item(i), activeOpacity(1), blendEnabled(true), flags(0) { } diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h index b284c6c..5fc0c48 100644 --- a/src/declarative/canvas/qsimplecanvas_p.h +++ b/src/declarative/canvas/qsimplecanvas_p.h @@ -129,6 +129,7 @@ public: QRect resetDirty(); void paint(QPainter &p); + QSimpleCanvasItem *opaqueList; int timer; diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h index 68219de..ee07a21 100644 --- a/src/declarative/canvas/qsimplecanvasitem.h +++ b/src/declarative/canvas/qsimplecanvasitem.h @@ -90,7 +90,8 @@ public: SimpleItem = 0x00000020, IsFocusPanel = 0x00000040, IsFocusRealm = 0x00000080, - AcceptsInputMethods = 0x00000100}; + AcceptsInputMethods = 0x00000100, + IsOpaque = 0x00000200 }; Q_DECLARE_FLAGS(Options, Option) QSimpleCanvasItem(QSimpleCanvasItem *parent=0); @@ -181,6 +182,9 @@ public: void fillRect(const QRectF &, const QColor &); void invalidate(); + + bool blendEnabled; + private: int flags; GLPainter(const GLPainter &); diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h index 27ee0a2..6c21d9f 100644 --- a/src/declarative/canvas/qsimplecanvasitem_p.h +++ b/src/declarative/canvas/qsimplecanvasitem_p.h @@ -161,7 +161,7 @@ public: QSimpleCanvasItem::ClipType clip:3; QSimpleCanvasItem::TransformOrigin origin:4; - int options:9; + int options:10; bool focusable:1; bool wantsActiveFocusPanelPendingCanvas:1; bool hasBeenActiveFocusPanel:1; @@ -222,7 +222,7 @@ public: QSimpleCanvasItem::GLPainter *painter; }; #if defined(QFX_RENDER_OPENGL2) - QRectF setupPainting(int version); + QRectF setupPainting(int version, int &z, QSimpleCanvasItem **); #elif defined(QFX_RENDER_OPENGL1) QRectF setupPainting(int version, const QRect &bounding, unsigned int *zero); #endif @@ -241,6 +241,8 @@ public: #endif + QSimpleCanvasItem *nextOpaque; + void zOrderChildren(); bool freshenNeeded() const; void doFreshenTransforms() const; diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 1fc84eb..d28cf7d 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -254,6 +254,9 @@ void QFxImage::setOpaque(bool o) if (o == d->_opaque) return; d->_opaque = o; + + setOptions(IsOpaque, o); + update(); } @@ -476,7 +479,7 @@ void QFxImage::paintGLContents(GLPainter &p) QGLShaderProgram *shader = p.useTextureShader(); bool restoreBlend = false; - if (isOpaque() && p.activeOpacity == 1) { + if (p.blendEnabled && isOpaque() && p.activeOpacity == 1) { glDisable(GL_BLEND); restoreBlend = true; } -- cgit v0.12 From e91dff94de4851b4b8ac48cadccd516893fe4661 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 3 Jun 2009 19:07:45 +1000 Subject: Use POT textures only --- src/declarative/fx/qfximage.cpp | 14 ++++---- src/declarative/fx/qfxrect.cpp | 41 +++++++++++---------- src/declarative/fx/qfxtext.cpp | 13 +++---- src/declarative/opengl/gltexture.cpp | 69 +++++++++++++++++++++++++----------- 4 files changed, 86 insertions(+), 51 deletions(-) diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index d28cf7d..d3ac38f 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -462,7 +462,7 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, void QFxImagePrivate::checkDirty() { if (_texDirty && !_pix.isNull()) { - _tex.setImage(_pix.toImage()); + _tex.setImage(_pix.toImage(), GLTexture::PowerOfTwo); _tex.setHorizontalWrap(GLTexture::Repeat); _tex.setVerticalWrap(GLTexture::Repeat); } @@ -548,8 +548,8 @@ void QFxImage::paintGLContents(GLPainter &p) float heightV = height(); float texleft = 0; - float texright = 1; - float textop = 1; + float texright = d->_tex.glWidth(); + float textop = d->_tex.glHeight(); float texbottom = 0; float imgleft = 0; float imgright = widthV; @@ -562,19 +562,19 @@ void QFxImage::paintGLContents(GLPainter &p) const int sgb = d->_scaleGrid->bottom(); if (sgl) { - texleft = float(sgl) / imgWidth; + texleft = d->_tex.glWidth() * float(sgl) / imgWidth; imgleft = sgl; } if (sgr) { - texright = 1. - float(sgr) / imgWidth; + texright = d->_tex.glWidth() - float(sgr) / imgWidth; imgright = widthV - sgr; } if (sgt) { - textop = 1. - float(sgb) / imgHeight; + textop = d->_tex.glHeight() - float(sgb) / imgHeight; imgtop = sgt; } if (sgb) { - texbottom = float(sgt) / imgHeight; + texbottom = d->_tex.glHeight() * float(sgt) / imgHeight; imgbottom = heightV - sgb; } diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index 3d6897e..c053001 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -535,7 +535,7 @@ void QFxRect::generateRoundedRect() } p.setBrush(d->_color); p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->_radius, d->_radius); - d->_rectTexture.setImage(roundRect); + d->_rectTexture.setImage(roundRect, GLTexture::PowerOfTwo); } } @@ -556,7 +556,7 @@ void QFxRect::generateBorderedRect() } p.setBrush(d->_color); p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2); - d->_rectTexture.setImage(borderedRect); + d->_rectTexture.setImage(borderedRect, GLTexture::PowerOfTwo); } } #endif @@ -756,6 +756,11 @@ void QFxRect::paintGLContents(GLPainter &p) if (offset==1) texleft=texright=textop=texbottom=0.5; + texleft *= d->_rectTexture.glWidth(); + texright *= d->_rectTexture.glWidth(); + textop *= d->_rectTexture.glHeight(); + texbottom *= d->_rectTexture.glHeight(); + float vert1[] = { -pw/2, -pw/2, -pw/2, imgtop, imgleft, -pw/2, @@ -847,35 +852,35 @@ void QFxRect::paintGLContents(GLPainter &p) texright, 0, texright, textop, - 1, 0, + d->_rectTexture.glWidth(), 0, texright, textop, - 1, 0, - 1, textop, + d->_rectTexture.glWidth(), 0, + d->_rectTexture.glWidth(), textop, - 0, 1, + 0, d->_rectTexture.glHeight(), 0, texbottom, - texleft, 1, + texleft, d->_rectTexture.glHeight(), 0, texbottom, - texleft, 1, + texleft, d->_rectTexture.glHeight(), texleft, texbottom, - texleft, 1, + texleft, d->_rectTexture.glHeight(), texleft, texbottom, - texright, 1, + texright, d->_rectTexture.glHeight(), texleft, texbottom, - texright, 1, + texright, d->_rectTexture.glHeight(), texright, texbottom, - texright, 1, + texright, d->_rectTexture.glHeight(), texright, texbottom, - 1, 1, + d->_rectTexture.glWidth(), d->_rectTexture.glHeight(), texright, texbottom, - 1, 1, - 1, texbottom, + d->_rectTexture.glWidth(), d->_rectTexture.glHeight(), + d->_rectTexture.glWidth(), texbottom, 0, textop, 0, texbottom, @@ -895,11 +900,11 @@ void QFxRect::paintGLContents(GLPainter &p) texright, textop, texright, texbottom, - 1, textop, + d->_rectTexture.glWidth(), textop, texright, texbottom, - 1, textop, - 1, texbottom }; + d->_rectTexture.glWidth(), textop, + d->_rectTexture.glWidth(), texbottom }; diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index 1b5c080..7a2dd8d 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -696,7 +696,7 @@ void QFxTextPrivate::checkImgCache() } #if defined(QFX_RENDER_OPENGL) - tex.setImage(imgCache.toImage()); + tex.setImage(imgCache.toImage(), GLTexture::PowerOfTwo); #endif imgDirty = false; @@ -755,6 +755,7 @@ void QFxText::paintContents(QPainter &p) #elif defined(QFX_RENDER_OPENGL2) void QFxText::paintGLContents(GLPainter &p) { + //return; Q_D(QFxText); d->checkImgCache(); if (d->imgCache.isNull()) @@ -804,12 +805,12 @@ void QFxText::paintGLContents(GLPainter &p) x + widthV, y }; GLfloat texVertices[] = { 0, 0, - 1, 0, - 0, 1, + d->tex.glWidth(), 0, + 0, d->tex.glHeight(), - 1, 0, - 0, 1, - 1, 1 }; + d->tex.glWidth(), 0, + 0, d->tex.glHeight(), + d->tex.glWidth(), d->tex.glHeight() }; shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); diff --git a/src/declarative/opengl/gltexture.cpp b/src/declarative/opengl/gltexture.cpp index bebee08..cd9c406 100644 --- a/src/declarative/opengl/gltexture.cpp +++ b/src/declarative/opengl/gltexture.cpp @@ -180,30 +180,59 @@ void GLTexture::setImage(const QImage &img, ImageMode mode) glBindTexture(GL_TEXTURE_2D, d->texture); - // ### Need to respect mode - if (img.format() == QImage::Format_RGB16) { - QImage dataImage = img.mirrored(); + if (mode == NonPowerOfTwo) { + + if (img.format() == QImage::Format_RGB16) { + QImage dataImage = img.mirrored(); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dataImage.width(), + dataImage.height(), 0, + GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, dataImage.bits()); + } else { + QImage dataImage = QGLWidget_convertToGLFormat(img); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(), + dataImage.height(), 0, + (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, + GL_UNSIGNED_BYTE, dataImage.bits()); + } + d->glWidth = 1.; + d->glHeight = 1.; + + } else { + // mode == PowerOfTwo int max = (img.width() > img.height())?img.width():img.height(); max = npot(max); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, max, - max, 0, - GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, 0); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dataImage.width(), - dataImage.height(), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - dataImage.bits()); - - d->glWidth = qreal(dataImage.width()) / qreal(max); - d->glHeight = qreal(dataImage.height()) / qreal(max); - } else { - QImage dataImage = QGLWidget_convertToGLFormat(img); + if (img.format() == QImage::Format_RGB16) { + QImage dataImage = img.mirrored(); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, max, + max, 0, + GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, 0); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dataImage.width(), + dataImage.height(), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + dataImage.bits()); + + } else { + QImage dataImage = QGLWidget_convertToGLFormat(img); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, max, + max, 0, + (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, + GL_UNSIGNED_BYTE, 0); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dataImage.width(), + dataImage.height(), + (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, + GL_UNSIGNED_BYTE, dataImage.bits()); + } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(), - dataImage.height(), 0, - (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, - GL_UNSIGNED_BYTE, dataImage.bits()); + d->glWidth = qreal(img.width()) / qreal(max); + d->glHeight = qreal(img.height()) / qreal(max); } d->width = img.width(); -- cgit v0.12 From bf50ad866fc787b7787fd102566993c284622112 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 4 Jun 2009 11:12:02 +1000 Subject: Cleanup private class member names --- src/declarative/fx/qfximage.cpp | 134 ++++++++++++++++++++-------------------- src/declarative/fx/qfximage_p.h | 28 ++++----- 2 files changed, 81 insertions(+), 81 deletions(-) diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index d3ac38f..509323a 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -141,22 +141,22 @@ QFxImage::~QFxImage() QPixmap QFxImage::pixmap() const { Q_D(const QFxImage); - return d->_pix; + return d->pix; } void QFxImage::setPixmap(const QPixmap &pix) { Q_D(QFxImage); d->url = QUrl(); - d->_pix = pix; - d->_opaque=false; + d->pix = pix; + d->opaque=false; - setImplicitWidth(d->_pix.width()); - setImplicitHeight(d->_pix.height()); + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); #if defined(QFX_RENDER_OPENGL) - d->_texDirty = true; - d->_tex.clear(); + d->texDirty = true; + d->tex.clear(); #endif update(); } @@ -189,7 +189,7 @@ void QFxImage::setPixmap(const QPixmap &pix) QFxScaleGrid *QFxImage::scaleGrid() { Q_D(QFxImage); - return d->scaleGrid(); + return d->getScaleGrid(); } /*! @@ -213,13 +213,13 @@ QFxScaleGrid *QFxImage::scaleGrid() bool QFxImage::isTiled() const { Q_D(const QFxImage); - return d->_tiled; + return d->tiled; } void QFxImage::setTiled(bool tile) { Q_D(QFxImage); - d->_tiled = tile; + d->tiled = tile; } /*! @@ -245,15 +245,15 @@ void QFxImage::setTiled(bool tile) bool QFxImage::isOpaque() const { Q_D(const QFxImage); - return d->_opaque; + return d->opaque; } void QFxImage::setOpaque(bool o) { Q_D(QFxImage); - if (o == d->_opaque) + if (o == d->opaque) return; - d->_opaque = o; + d->opaque = o; setOptions(IsOpaque, o); @@ -296,15 +296,15 @@ void QFxImage::componentComplete() bool QFxImage::smoothTransform() const { Q_D(const QFxImage); - return d->_smooth; + return d->smooth; } void QFxImage::setSmoothTransform(bool s) { Q_D(QFxImage); - if (d->_smooth == s) + if (d->smooth == s) return; - d->_smooth = s; + d->smooth = s; update(); } @@ -320,16 +320,16 @@ void QFxImage::dump(int depth) void QFxImage::paintContents(QPainter &p) { Q_D(QFxImage); - if (d->_pix.isNull()) + if (d->pix.isNull()) return; QPainter::RenderHints oldHints = p.renderHints(); - if (d->_smooth) - p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->_smooth); + if (d->smooth) + p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); - QPixmap pix = d->_pix; + QPixmap pix = d->pix; - if (d->_tiled) { + if (d->tiled) { p.save(); p.setClipRect(0, 0, width(), height(), Qt::IntersectClip); QRect me = QRect(0, 0, width(), height()); @@ -348,7 +348,7 @@ void QFxImage::paintContents(QPainter &p) } p.restore(); - } else if (!d->_scaleGrid || d->_scaleGrid->isNull()) { + } else if (!d->scaleGrid || d->scaleGrid->isNull()) { if (width() != pix.width() || height() != pix.height()) { QTransform scale; scale.scale(width() / qreal(pix.width()), @@ -361,10 +361,10 @@ void QFxImage::paintContents(QPainter &p) p.drawPixmap(0, 0, pix); } } else { - int sgl = d->_scaleGrid->left(); - int sgr = d->_scaleGrid->right(); - int sgt = d->_scaleGrid->top(); - int sgb = d->_scaleGrid->bottom(); + int sgl = d->scaleGrid->left(); + int sgr = d->scaleGrid->right(); + int sgt = d->scaleGrid->top(); + int sgb = d->scaleGrid->bottom(); int w = width(); int h = height(); @@ -415,7 +415,7 @@ void QFxImage::paintContents(QPainter &p) QRect(pix.width()-sgr, pix.height() - sgb, sgr, sgb)); } - if (d->_smooth) + if (d->smooth) p.setRenderHints(oldHints); } #elif defined(QFX_RENDER_OPENGL) @@ -424,7 +424,7 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, { Q_D(QFxImage); - if (d->_pix.isNull() || (d->_scaleGrid && !d->_scaleGrid->isNull())) + if (d->pix.isNull() || (d->scaleGrid && !d->scaleGrid->isNull())) return 0; if (count < 8) @@ -440,20 +440,20 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, vertices[4] = 0; vertices[5] = 0; vertices[6] = widthV; vertices[7] = 0; - *texture = &d->_tex; + *texture = &d->tex; - if (d->_tiled) { - float tileWidth = widthV / d->_pix.width(); - float tileHeight = heightV / d->_pix.height(); + if (d->tiled) { + float tileWidth = widthV / d->pix.width(); + float tileHeight = heightV / d->pix.height(); texVertices[0] = 0; texVertices[1] = 0; texVertices[2] = tileWidth; texVertices[3] = 0; texVertices[4] = 0; texVertices[5] = tileHeight; texVertices[6] = tileWidth; texVertices[7] = tileHeight; } else { texVertices[0] = 0; texVertices[1] = 0; - texVertices[2] = d->_tex.glWidth(); texVertices[3] = 0; - texVertices[4] = 0; texVertices[5] = d->_tex.glHeight(); - texVertices[6] = d->_tex.glWidth(); texVertices[7] = d->_tex.glHeight(); + texVertices[2] = d->tex.glWidth(); texVertices[3] = 0; + texVertices[4] = 0; texVertices[5] = d->tex.glHeight(); + texVertices[6] = d->tex.glWidth(); texVertices[7] = d->tex.glHeight(); } return 8; @@ -461,19 +461,19 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, void QFxImagePrivate::checkDirty() { - if (_texDirty && !_pix.isNull()) { - _tex.setImage(_pix.toImage(), GLTexture::PowerOfTwo); - _tex.setHorizontalWrap(GLTexture::Repeat); - _tex.setVerticalWrap(GLTexture::Repeat); + if (texDirty && !pix.isNull()) { + tex.setImage(pix.toImage(), GLTexture::PowerOfTwo); + tex.setHorizontalWrap(GLTexture::Repeat); + tex.setVerticalWrap(GLTexture::Repeat); } - _texDirty = false; + texDirty = false; } #if defined(QFX_RENDER_OPENGL2) void QFxImage::paintGLContents(GLPainter &p) { Q_D(QFxImage); - if (d->_pix.isNull()) + if (d->pix.isNull()) return; QGLShaderProgram *shader = p.useTextureShader(); @@ -486,14 +486,14 @@ void QFxImage::paintGLContents(GLPainter &p) d->checkDirty(); - if (d->_tiled || (!d->_scaleGrid || d->_scaleGrid->isNull())) { + if (d->tiled || (!d->scaleGrid || d->scaleGrid->isNull())) { - if (!d->_tiled) { + if (!d->tiled) { float widthV = width(); float heightV = height(); - float glWidth = d->_tex.glWidth(); - float glHeight = d->_tex.glHeight(); + float glWidth = d->tex.glWidth(); + float glHeight = d->tex.glHeight(); float vert[] = { 0, heightV, @@ -516,7 +516,7 @@ void QFxImage::paintGLContents(GLPainter &p) shader->setAttributeArray(SingleTextureShader::Vertices, vert, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex, 2); - glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); + glBindTexture(GL_TEXTURE_2D, d->tex.texture()); glDrawArrays(GL_TRIANGLES, 0, 6); } else { @@ -536,8 +536,8 @@ void QFxImage::paintGLContents(GLPainter &p) } else { - float imgWidth = d->_pix.width(); - float imgHeight = d->_pix.height(); + float imgWidth = d->pix.width(); + float imgHeight = d->pix.height(); if (!imgWidth || !imgHeight) { if (restoreBlend) glEnable(GL_BLEND); @@ -548,33 +548,33 @@ void QFxImage::paintGLContents(GLPainter &p) float heightV = height(); float texleft = 0; - float texright = d->_tex.glWidth(); - float textop = d->_tex.glHeight(); + float texright = d->tex.glWidth(); + float textop = d->tex.glHeight(); float texbottom = 0; float imgleft = 0; float imgright = widthV; float imgtop = 0; float imgbottom = heightV; - const int sgl = d->_scaleGrid->left(); - const int sgr = d->_scaleGrid->right(); - const int sgt = d->_scaleGrid->top(); - const int sgb = d->_scaleGrid->bottom(); + const int sgl = d->scaleGrid->left(); + const int sgr = d->scaleGrid->right(); + const int sgt = d->scaleGrid->top(); + const int sgb = d->scaleGrid->bottom(); if (sgl) { - texleft = d->_tex.glWidth() * float(sgl) / imgWidth; + texleft = d->tex.glWidth() * float(sgl) / imgWidth; imgleft = sgl; } if (sgr) { - texright = d->_tex.glWidth() - float(sgr) / imgWidth; + texright = d->tex.glWidth() - float(sgr) / imgWidth; imgright = widthV - sgr; } if (sgt) { - textop = d->_tex.glHeight() - float(sgb) / imgHeight; + textop = d->tex.glHeight() - float(sgb) / imgHeight; imgtop = sgt; } if (sgb) { - texbottom = d->_tex.glHeight() * float(sgt) / imgHeight; + texbottom = d->tex.glHeight() * float(sgt) / imgHeight; imgbottom = heightV - sgb; } @@ -722,7 +722,7 @@ void QFxImage::paintGLContents(GLPainter &p) 1, texbottom, 1, 0 }; - glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); + glBindTexture(GL_TEXTURE_2D, d->tex.texture()); shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); @@ -846,8 +846,8 @@ void QFxImage::setSource(const QString &url) setImplicitWidth(0); setImplicitHeight(0); #if defined(QFX_RENDER_OPENGL) - d->_texDirty = true; - d->_tex.clear(); + d->texDirty = true; + d->tex.clear(); #endif emit statusChanged(d->status); emit sourceChanged(d->source); @@ -889,7 +889,7 @@ void QFxImage::requestFinished() { Q_D(QFxImage); if (d->url.path().endsWith(QLatin1String(".sci"))) { - d->_pix = QFxPixmap(d->sciurl); + d->pix = QFxPixmap(d->sciurl); } else { if (d->reply) { disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), @@ -897,18 +897,18 @@ void QFxImage::requestFinished() if (d->reply->error() != QNetworkReply::NoError) d->status = Error; } - d->_pix = QFxPixmap(d->url); + d->pix = QFxPixmap(d->url); setOptions(QFxImage::SimpleItem, true); } - setImplicitWidth(d->_pix.width()); - setImplicitHeight(d->_pix.height()); + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); if (d->status == Loading) d->status = Idle; d->progress = 1.0; #if defined(QFX_RENDER_OPENGL) - d->_texDirty = true; - d->_tex.clear(); + d->texDirty = true; + d->tex.clear(); #endif emit statusChanged(d->status); emit sourceChanged(d->source); diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index b3cccf9..b5c6055 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -72,9 +72,9 @@ class QFxImagePrivate : public QFxItemPrivate public: QFxImagePrivate() - : _scaleGrid(0), _tiled(false), _smooth(false), _opaque(false), + : scaleGrid(0), tiled(false), smooth(false), opaque(false), #if defined(QFX_RENDER_OPENGL) - _texDirty(true), + texDirty(true), #endif status(QFxImage::Idle), sciReply(0), progress(0.0) { @@ -82,27 +82,27 @@ public: ~QFxImagePrivate() { - delete _scaleGrid; + delete scaleGrid; } void setContent(QIODevice* dev, const QString &url); - QFxScaleGrid *scaleGrid() + QFxScaleGrid *getScaleGrid() { - if (!_scaleGrid) - _scaleGrid = new QFxScaleGrid; - return _scaleGrid; + if (!scaleGrid) + scaleGrid = new QFxScaleGrid; + return scaleGrid; } - QFxScaleGrid *_scaleGrid; - QPixmap _pix; - bool _tiled : 1; - bool _smooth : 1; - bool _opaque : 1; + QFxScaleGrid *scaleGrid; + QPixmap pix; + bool tiled : 1; + bool smooth : 1; + bool opaque : 1; #if defined(QFX_RENDER_OPENGL) + bool texDirty : 1; void checkDirty(); - bool _texDirty; - GLTexture _tex; + GLTexture tex; #endif QFxImage::Status status; -- cgit v0.12 From f7cf2cdc0b6c83a639d155987f871f7932c1d845 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 4 Jun 2009 12:32:47 +1000 Subject: Cleanup private class member names --- src/declarative/fx/qfxrect.cpp | 212 ++++++++++++++++++++--------------------- src/declarative/fx/qfxrect_p.h | 26 ++--- 2 files changed, 119 insertions(+), 119 deletions(-) diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index c053001..d52e31c 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -253,13 +253,13 @@ void QFxRect::doUpdate() { #if defined(QFX_RENDER_QPAINTER) Q_D(QFxRect); - d->_rectImage = QPixmap(); + d->rectImage = QPixmap(); #endif #if defined(QFX_RENDER_OPENGL) Q_D(QFxRect); - d->_rectTexture.clear(); + d->rectTexture.clear(); #endif - const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; + const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; setPaintMargin((pw+1)/2); update(); } @@ -277,7 +277,7 @@ void QFxRect::doUpdate() QFxPen *QFxRect::pen() { Q_D(QFxRect); - return d->pen(); + return d->getPen(); } /*! @@ -348,20 +348,20 @@ void QFxRect::setGradient(QFxGradient *gradient) qreal QFxRect::radius() const { Q_D(const QFxRect); - return d->_radius; + return d->radius; } void QFxRect::setRadius(qreal radius) { Q_D(QFxRect); - if (d->_radius == radius) + if (d->radius == radius) return; - d->_radius = radius; + d->radius = radius; #if defined(QFX_RENDER_QPAINTER) - d->_rectImage = QPixmap(); + d->rectImage = QPixmap(); #elif defined(QFX_RENDER_OPENGL) - d->_rectTexture.clear(); + d->rectTexture.clear(); #endif update(); } @@ -370,7 +370,7 @@ void QFxRect::dump(int depth) { Q_D(QFxRect); QByteArray ba(depth * 4, ' '); - qWarning() << ba.constData() << "QFxRect:" << d->_color; + qWarning() << ba.constData() << "QFxRect:" << d->color; QFxItem::dump(depth); } @@ -394,21 +394,21 @@ void QFxRect::dump(int depth) QColor QFxRect::color() const { Q_D(const QFxRect); - return d->_color; + return d->color; } void QFxRect::setColor(const QColor &c) { Q_D(QFxRect); - if (d->_color == c) + if (d->color == c) return; - d->_color = c; + d->color = c; #if defined(QFX_RENDER_QPAINTER) - d->_rectImage = QPixmap(); + d->rectImage = QPixmap(); #endif #if defined(QFX_RENDER_OPENGL) - d->_rectTexture.clear(); + d->rectTexture.clear(); #endif update(); } @@ -437,30 +437,30 @@ void QFxRect::setColor(const QColor &c) QColor QFxRect::tintColor() const { Q_D(const QFxRect); - return d->_tintColor; + return d->tintColor; } void QFxRect::setTintColor(const QColor &c) { Q_D(QFxRect); - if (d->_tintColor == c) + if (d->tintColor == c) return; - d->_tintColor = c; + d->tintColor = c; update(); } QColor QFxRectPrivate::getColor() { - if (_tintColor.isValid()) { - int a = _tintColor.alpha(); + if (tintColor.isValid()) { + int a = tintColor.alpha(); if (a == 0xFF) - return _tintColor; + return tintColor; else if (a == 0x00) - return _color; + return color; else { - uint src = _tintColor.rgba(); - uint dest = _color.rgba(); + uint src = tintColor.rgba(); + uint dest = color.rgba(); uint res = (((a * (src & 0xFF00FF)) + ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF; @@ -472,7 +472,7 @@ QColor QFxRectPrivate::getColor() return QColor::fromRgba(res); } } else { - return _color; + return color; } } @@ -481,82 +481,82 @@ QColor QFxRectPrivate::getColor() void QFxRect::generateRoundedRect() { Q_D(QFxRect); - if (d->_rectImage.isNull()) { - const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; - d->_rectImage = QPixmap(d->_radius*2 + 3 + pw*2, d->_radius*2 + 3 + pw*2); - d->_rectImage.fill(Qt::transparent); - QPainter p(&(d->_rectImage)); + if (d->rectImage.isNull()) { + const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; + d->rectImage = QPixmap(d->radius*2 + 3 + pw*2, d->radius*2 + 3 + pw*2); + d->rectImage.fill(Qt::transparent); + QPainter p(&(d->rectImage)); p.setRenderHint(QPainter::Antialiasing); - if (d->_pen && d->_pen->isValid()) { - QPen pn(QColor(pen()->color()), pen()->width()); + if (d->pen && d->pen->isValid()) { + QPen pn(QColor(getPen()->color()), getPen()->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); } - p.setBrush(d->_color); - p.drawRoundedRect((pw+1)/2, (pw+1)/2, d->_rectImage.width()-(pw+1)/2*2, d->_rectImage.height()-(pw+1)/2*2, d->_radius, d->_radius); + p.setBrush(d->color); + p.drawRoundedRect((pw+1)/2, (pw+1)/2, d->rectImage.width()-(pw+1)/2*2, d->rectImage.height()-(pw+1)/2*2, d->radius, d->radius); } } void QFxRect::generateBorderedRect() { Q_D(QFxRect); - if (d->_rectImage.isNull()) { - const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; - d->_rectImage = QPixmap(d->pen()->width()*2 + 3 + pw*2, d->pen()->width()*2 + 3 + pw*2); - d->_rectImage.fill(Qt::transparent); - QPainter p(&(d->_rectImage)); + if (d->rectImage.isNull()) { + const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; + d->rectImage = QPixmap(d->getPen()->width()*2 + 3 + pw*2, d->getPen()->width()*2 + 3 + pw*2); + d->rectImage.fill(Qt::transparent); + QPainter p(&(d->rectImage)); p.setRenderHint(QPainter::Antialiasing); - if (d->_pen && d->_pen->isValid()) { - QPen pn(QColor(pen()->color()), pen()->width()); + if (d->pen && d->pen->isValid()) { + QPen pn(QColor(getPen()->color()), getPen()->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); } - p.setBrush(d->_color); - p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, d->_rectImage.width()-(pw+1)/2*2, d->_rectImage.height()-(pw+1)/2*2); + p.setBrush(d->color); + p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, d->rectImage.width()-(pw+1)/2*2, d->rectImage.height()-(pw+1)/2*2); } } #elif defined(QFX_RENDER_OPENGL) void QFxRect::generateRoundedRect() { Q_D(QFxRect); - if (d->_rectTexture.isNull()) { - const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; - QImage roundRect(d->_radius*2 + 4 + pw*2, d->_radius*2 + 4 + pw*2, QImage::Format_ARGB32_Premultiplied); + if (d->rectTexture.isNull()) { + const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; + QImage roundRect(d->radius*2 + 4 + pw*2, d->radius*2 + 4 + pw*2, QImage::Format_ARGB32_Premultiplied); roundRect.fill(0); QPainter p(&roundRect); p.setRenderHint(QPainter::Antialiasing); - if (d->_pen && d->_pen->isValid()) { + if (d->pen && d->pen->isValid()) { QPen pn(QColor(pen()->color()), pen()->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); } - p.setBrush(d->_color); - p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->_radius, d->_radius); - d->_rectTexture.setImage(roundRect, GLTexture::PowerOfTwo); + p.setBrush(d->color); + p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->radius, d->radius); + d->rectTexture.setImage(roundRect, GLTexture::PowerOfTwo); } } void QFxRect::generateBorderedRect() { Q_D(QFxRect); - if (d->_rectTexture.isNull()) { - const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; + if (d->rectTexture.isNull()) { + const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; QImage borderedRect(pw*2 + 4, pw*2 + 4, QImage::Format_ARGB32_Premultiplied); borderedRect.fill(0); QPainter p(&(borderedRect)); p.setRenderHint(QPainter::Antialiasing); - if (d->_pen && d->_pen->isValid()) { + if (d->pen && d->pen->isValid()) { QPen pn(QColor(pen()->color()), pen()->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); } - p.setBrush(d->_color); + p.setBrush(d->color); p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2); - d->_rectTexture.setImage(borderedRect, GLTexture::PowerOfTwo); + d->rectTexture.setImage(borderedRect, GLTexture::PowerOfTwo); } } #endif @@ -566,7 +566,7 @@ void QFxRect::generateBorderedRect() void QFxRect::paintContents(QPainter &p) { Q_D(QFxRect); - if (d->_radius > 0 || (d->_pen && d->_pen->isValid()) + if (d->radius > 0 || (d->pen && d->pen->isValid()) || (d->gradient && d->gradient->gradient()) ) drawRect(p); else @@ -581,26 +581,26 @@ void QFxRect::drawRect(QPainter &p) // Image path won't work for gradients though QPainter::RenderHints oldHints = p.renderHints(); p.setRenderHint(QPainter::Antialiasing); - if (d->_pen && d->_pen->isValid()) { - QPen pn(QColor(pen()->color()), pen()->width()); + if (d->pen && d->pen->isValid()) { + QPen pn(QColor(getPen()->color()), getPen()->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); } p.setBrush(*d->gradient->gradient()); - if (d->_radius > 0.) - p.drawRoundedRect(0, 0, width(), height(), d->_radius, d->_radius); + if (d->radius > 0.) + p.drawRoundedRect(0, 0, width(), height(), d->radius, d->radius); else p.drawRect(0, 0, width(), height()); p.setRenderHints(oldHints); } else { int offset = 0; - const int pw = d->_pen && d->_pen->isValid() ? (d->_pen->width()+1)/2*2 : 0; + const int pw = d->pen && d->pen->isValid() ? (d->pen->width()+1)/2*2 : 0; - if (d->_radius > 0) { + if (d->radius > 0) { generateRoundedRect(); //### implicit conversion to int - offset = int(d->_radius+1.5+pw); + offset = int(d->radius+1.5+pw); } else { generateBorderedRect(); offset = pw+1; @@ -627,40 +627,40 @@ void QFxRect::drawRect(QPainter &p) } // Upper left - p.drawPixmap(QRect(-pw/2, -pw/2, xOffset, yOffset), d->_rectImage, QRect(0, 0, xOffset, yOffset)); + p.drawPixmap(QRect(-pw/2, -pw/2, xOffset, yOffset), d->rectImage, QRect(0, 0, xOffset, yOffset)); // Upper middle if (xMiddles) - p.drawPixmap(QRect(xOffset-pw/2, -pw/2, width() - xSide + pw, yOffset), d->_rectImage, - QRect(d->_rectImage.width()/2, 0, 1, yOffset)); + p.drawPixmap(QRect(xOffset-pw/2, -pw/2, width() - xSide + pw, yOffset), d->rectImage, + QRect(d->rectImage.width()/2, 0, 1, yOffset)); // Upper right - p.drawPixmap(QPoint(width()-xOffset+pw/2, -pw/2), d->_rectImage, - QRect(d->_rectImage.width()-xOffset, 0, xOffset, yOffset)); + p.drawPixmap(QPoint(width()-xOffset+pw/2, -pw/2), d->rectImage, + QRect(d->rectImage.width()-xOffset, 0, xOffset, yOffset)); // Middle left if (yMiddles) - p.drawPixmap(QRect(-pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->_rectImage, - QRect(0, d->_rectImage.height()/2, xOffset, 1)); + p.drawPixmap(QRect(-pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->rectImage, + QRect(0, d->rectImage.height()/2, xOffset, 1)); // Middle if (xMiddles && yMiddles) // XXX paint errors in animation example //p.fillRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw, d->getColor()); - p.drawPixmap(QRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw), d->_rectImage, - QRect(d->_rectImage.width()/2, d->_rectImage.height()/2, 1, 1)); + p.drawPixmap(QRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw), d->rectImage, + QRect(d->rectImage.width()/2, d->rectImage.height()/2, 1, 1)); // Middle right if (yMiddles) - p.drawPixmap(QRect(width()-xOffset+pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->_rectImage, - QRect(d->_rectImage.width()-xOffset, d->_rectImage.height()/2, xOffset, 1)); + p.drawPixmap(QRect(width()-xOffset+pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->rectImage, + QRect(d->rectImage.width()-xOffset, d->rectImage.height()/2, xOffset, 1)); // Lower left - p.drawPixmap(QPoint(-pw/2, height() - yOffset + pw/2), d->_rectImage, QRect(0, d->_rectImage.height() - yOffset, xOffset, yOffset)); + p.drawPixmap(QPoint(-pw/2, height() - yOffset + pw/2), d->rectImage, QRect(0, d->rectImage.height() - yOffset, xOffset, yOffset)); // Lower Middle if (xMiddles) - p.drawPixmap(QRect(xOffset-pw/2, height() - yOffset +pw/2, width() - xSide + pw, yOffset), d->_rectImage, - QRect(d->_rectImage.width()/2, d->_rectImage.height() - yOffset, 1, yOffset)); + p.drawPixmap(QRect(xOffset-pw/2, height() - yOffset +pw/2, width() - xSide + pw, yOffset), d->rectImage, + QRect(d->rectImage.width()/2, d->rectImage.height() - yOffset, 1, yOffset)); // Lower Right - p.drawPixmap(QPoint(width()-xOffset+pw/2, height() - yOffset+pw/2), d->_rectImage, - QRect(d->_rectImage.width()-xOffset, d->_rectImage.height() - yOffset, xOffset, yOffset)); + p.drawPixmap(QPoint(width()-xOffset+pw/2, height() - yOffset+pw/2), d->rectImage, + QRect(d->rectImage.width()-xOffset, d->rectImage.height() - yOffset, xOffset, yOffset)); } } #endif @@ -671,7 +671,7 @@ void QFxRect::drawRect(QPainter &p) void QFxRect::paintGLContents(GLPainter &p) { Q_D(QFxRect); - if (d->_radius == 0 && (!d->_pen || !d->_pen->isValid())) { + if (d->radius == 0 && (!d->pen || !d->pen->isValid())) { if (d->gradient) { float widthV = width(); float heightV = height(); @@ -709,11 +709,11 @@ void QFxRect::paintGLContents(GLPainter &p) } } else { qreal offset = 0; - qreal pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0.0; + qreal pw = d->pen && d->pen->isValid() ? d->pen->width() : 0.0; - if (d->_radius > 0) { + if (d->radius > 0) { generateRoundedRect(); - offset = d->_radius + pw+1.5; + offset = d->radius + pw+1.5; } else { generateBorderedRect(); offset = pw+1.5; @@ -721,8 +721,8 @@ void QFxRect::paintGLContents(GLPainter &p) QGLShaderProgram *shader = p.useTextureShader(); - float texWidth = d->_rectTexture.width(); - float texHeight = d->_rectTexture.height(); + float texWidth = d->rectTexture.width(); + float texHeight = d->rectTexture.height(); if (!texWidth || !texHeight) return; @@ -756,10 +756,10 @@ void QFxRect::paintGLContents(GLPainter &p) if (offset==1) texleft=texright=textop=texbottom=0.5; - texleft *= d->_rectTexture.glWidth(); - texright *= d->_rectTexture.glWidth(); - textop *= d->_rectTexture.glHeight(); - texbottom *= d->_rectTexture.glHeight(); + texleft *= d->rectTexture.glWidth(); + texright *= d->rectTexture.glWidth(); + textop *= d->rectTexture.glHeight(); + texbottom *= d->rectTexture.glHeight(); float vert1[] = { -pw/2, -pw/2, -pw/2, imgtop, @@ -852,35 +852,35 @@ void QFxRect::paintGLContents(GLPainter &p) texright, 0, texright, textop, - d->_rectTexture.glWidth(), 0, + d->rectTexture.glWidth(), 0, texright, textop, - d->_rectTexture.glWidth(), 0, - d->_rectTexture.glWidth(), textop, + d->rectTexture.glWidth(), 0, + d->rectTexture.glWidth(), textop, - 0, d->_rectTexture.glHeight(), + 0, d->rectTexture.glHeight(), 0, texbottom, - texleft, d->_rectTexture.glHeight(), + texleft, d->rectTexture.glHeight(), 0, texbottom, - texleft, d->_rectTexture.glHeight(), + texleft, d->rectTexture.glHeight(), texleft, texbottom, - texleft, d->_rectTexture.glHeight(), + texleft, d->rectTexture.glHeight(), texleft, texbottom, - texright, d->_rectTexture.glHeight(), + texright, d->rectTexture.glHeight(), texleft, texbottom, - texright, d->_rectTexture.glHeight(), + texright, d->rectTexture.glHeight(), texright, texbottom, - texright, d->_rectTexture.glHeight(), + texright, d->rectTexture.glHeight(), texright, texbottom, - d->_rectTexture.glWidth(), d->_rectTexture.glHeight(), + d->rectTexture.glWidth(), d->rectTexture.glHeight(), texright, texbottom, - d->_rectTexture.glWidth(), d->_rectTexture.glHeight(), - d->_rectTexture.glWidth(), texbottom, + d->rectTexture.glWidth(), d->rectTexture.glHeight(), + d->rectTexture.glWidth(), texbottom, 0, textop, 0, texbottom, @@ -900,15 +900,15 @@ void QFxRect::paintGLContents(GLPainter &p) texright, textop, texright, texbottom, - d->_rectTexture.glWidth(), textop, + d->rectTexture.glWidth(), textop, texright, texbottom, - d->_rectTexture.glWidth(), textop, - d->_rectTexture.glWidth(), texbottom }; + d->rectTexture.glWidth(), textop, + d->rectTexture.glWidth(), texbottom }; - glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); + glBindTexture(GL_TEXTURE_2D, d->rectTexture.texture()); shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h index 8cafcbb..6d11917 100644 --- a/src/declarative/fx/qfxrect_p.h +++ b/src/declarative/fx/qfxrect_p.h @@ -69,13 +69,13 @@ class QFxRectPrivate : public QFxItemPrivate public: QFxRectPrivate() - : gradient(0), _pen(0), _radius(0) + : gradient(0), pen(0), radius(0) { } ~QFxRectPrivate() { - delete _pen; + delete pen; } void init() @@ -83,24 +83,24 @@ public: } #if defined(QFX_RENDER_OPENGL) - GLTexture _rectTexture; + GLTexture rectTexture; #endif QColor getColor(); - QColor _color; + QColor color; QFxGradient *gradient; - QColor _tintColor; - QFxPen *pen() { - if (!_pen) { + QColor tintColor; + QFxPen *getPen() { + if (!pen) { Q_Q(QFxRect); - _pen = new QFxPen; - QObject::connect(_pen, SIGNAL(updated()), q, SLOT(doUpdate())); + pen = new QFxPen; + QObject::connect(pen, SIGNAL(updated()), q, SLOT(doUpdate())); } - return _pen; + return pen; } - QFxPen *_pen; - qreal _radius; + QFxPen *pen; + qreal radius; #if defined(QFX_RENDER_QPAINTER) - QPixmap _rectImage; + QPixmap rectImage; #endif }; -- cgit v0.12 From a276e872e83e0c2f04a367299580ef787b6efc51 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 4 Jun 2009 13:35:15 +1000 Subject: Share GL textures where possible --- src/declarative/canvas/qsimplecanvas_opengl.cpp | 84 +++++++++++++++- src/declarative/canvas/qsimplecanvas_p.h | 3 + src/declarative/canvas/qsimplecanvasitem.h | 23 +++++ src/declarative/fx/qfximage.cpp | 57 ++++++----- src/declarative/fx/qfximage_p.h | 4 +- src/declarative/fx/qfxrect.cpp | 126 ++++++++++++++---------- src/declarative/fx/qfxrect_p.h | 4 +- 7 files changed, 221 insertions(+), 80 deletions(-) diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp index 659104d..7969a2a 100644 --- a/src/declarative/canvas/qsimplecanvas_opengl.cpp +++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp @@ -294,7 +294,7 @@ void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child) } } -//#define QSIMPLECANVAS_DISABLE_TREE_CLIPPING +#define QSIMPLECANVAS_DISABLE_TREE_CLIPPING QRectF QSimpleCanvasItemPrivate::setupPainting(int version, int &z, QSimpleCanvasItem **opaqueList) { static QRectF scene(-1., -1., 2., 2.); @@ -595,4 +595,86 @@ void QSimpleCanvasItem::GLPainter::fillRect(const QRectF &rect, glEnable(GL_BLEND); } +void QSimpleCanvasItem::CachedTexture::addRef() +{ + ++r; +} + +void QSimpleCanvasItem::CachedTexture::release() +{ + Q_ASSERT(r > 0); + --r; + + if (r == 0) { + if (!s.isEmpty()) + d->cachedTextures.remove(s); + delete this; + } +} + +int QSimpleCanvasItem::CachedTexture::pixmapWidth() const +{ + return w; +} + +int QSimpleCanvasItem::CachedTexture::pixmapHeight() const +{ + return h; +} + +QSimpleCanvasItem::CachedTexture::CachedTexture() +: r(0), w(0), h(0) +{ +} + +QSimpleCanvasItem::CachedTexture * +QSimpleCanvasItem::cachedTexture(const QString &key) +{ + Q_D(QSimpleCanvasItem); + if (!d->canvas || key.isEmpty()) + return 0; + + QSimpleCanvasPrivate *canvas = d->canvas->d; + QHash::ConstIterator iter = + canvas->cachedTextures.find(key); + if (iter != canvas->cachedTextures.end()) { + (*iter)->addRef(); + return (*iter); + } else { + return 0; + } +} + +QSimpleCanvasItem::CachedTexture * +QSimpleCanvasItem::cachedTexture(const QString &key, const QPixmap &pix) +{ + Q_D(QSimpleCanvasItem); + if (!d->canvas) + return 0; + + QSimpleCanvasPrivate *canvas = d->canvas->d; + QHash::ConstIterator iter = + canvas->cachedTextures.end(); + if (!key.isEmpty()) + iter = canvas->cachedTextures.find(key); + + if (iter != canvas->cachedTextures.end()) { + (*iter)->addRef(); + return (*iter); + } else { + CachedTexture *rv = new CachedTexture; + rv->s = key; + rv->d = canvas; + rv->w = pix.width(); + rv->h = pix.height(); + rv->setImage(pix.toImage(), GLTexture::PowerOfTwo); + rv->setHorizontalWrap(GLTexture::Repeat); + rv->setVerticalWrap(GLTexture::Repeat); + rv->addRef(); + if (!key.isEmpty()) + canvas->cachedTextures.insert(key, rv); + return rv; + } +} + QT_END_NAMESPACE diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h index 5fc0c48..3a0186e 100644 --- a/src/declarative/canvas/qsimplecanvas_p.h +++ b/src/declarative/canvas/qsimplecanvas_p.h @@ -43,6 +43,7 @@ #define QSIMPLECANVAS_P_H #include "qsimplecanvas.h" +#include "qsimplecanvasitem.h" #include #include @@ -187,6 +188,8 @@ public: } mutable GLBasicShaders *basicShadersInstance; + QHash cachedTextures; + QList frameBuffers; QGLFramebufferObject *acquire(int, int); void release(QGLFramebufferObject *); diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h index ee07a21..e62c56d 100644 --- a/src/declarative/canvas/qsimplecanvasitem.h +++ b/src/declarative/canvas/qsimplecanvasitem.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -236,6 +237,28 @@ public: static QSimpleCanvasItem *findNextFocus(QSimpleCanvasItem *item); GLBasicShaders *basicShaders() const; + +#if defined(QFX_RENDER_OPENGL) + class CachedTexture : public GLTexture + { + public: + void addRef(); + void release(); + + int pixmapWidth() const; + int pixmapHeight() const; + + private: + CachedTexture(); + friend class QSimpleCanvasItem; + QSimpleCanvasPrivate *d; + QString s; + int r, w, h; + }; + + CachedTexture *cachedTexture(const QString &); + CachedTexture *cachedTexture(const QString &, const QPixmap &); +#endif static QPixmap string(const QString &, const QColor & = Qt::black, const QFont & = QFont()); diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 509323a..03a674d 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -124,9 +124,13 @@ QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent) QFxImage::~QFxImage() { - Q_D(const QFxImage); + Q_D(QFxImage); if (d->sciReply) d->sciReply->deleteLater(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } } /*! @@ -156,7 +160,10 @@ void QFxImage::setPixmap(const QPixmap &pix) #if defined(QFX_RENDER_OPENGL) d->texDirty = true; - d->tex.clear(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } #endif update(); } @@ -440,7 +447,7 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, vertices[4] = 0; vertices[5] = 0; vertices[6] = widthV; vertices[7] = 0; - *texture = &d->tex; + *texture = d->tex; if (d->tiled) { float tileWidth = widthV / d->pix.width(); @@ -451,9 +458,9 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, texVertices[6] = tileWidth; texVertices[7] = tileHeight; } else { texVertices[0] = 0; texVertices[1] = 0; - texVertices[2] = d->tex.glWidth(); texVertices[3] = 0; - texVertices[4] = 0; texVertices[5] = d->tex.glHeight(); - texVertices[6] = d->tex.glWidth(); texVertices[7] = d->tex.glHeight(); + texVertices[2] = d->tex->glWidth(); texVertices[3] = 0; + texVertices[4] = 0; texVertices[5] = d->tex->glHeight(); + texVertices[6] = d->tex->glWidth(); texVertices[7] = d->tex->glHeight(); } return 8; @@ -461,11 +468,9 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, void QFxImagePrivate::checkDirty() { - if (texDirty && !pix.isNull()) { - tex.setImage(pix.toImage(), GLTexture::PowerOfTwo); - tex.setHorizontalWrap(GLTexture::Repeat); - tex.setVerticalWrap(GLTexture::Repeat); - } + Q_Q(QFxImage); + if (texDirty && !pix.isNull()) + tex = q->cachedTexture(url.toString(), pix); texDirty = false; } @@ -492,8 +497,8 @@ void QFxImage::paintGLContents(GLPainter &p) float widthV = width(); float heightV = height(); - float glWidth = d->tex.glWidth(); - float glHeight = d->tex.glHeight(); + float glWidth = d->tex->glWidth(); + float glHeight = d->tex->glHeight(); float vert[] = { 0, heightV, @@ -516,7 +521,7 @@ void QFxImage::paintGLContents(GLPainter &p) shader->setAttributeArray(SingleTextureShader::Vertices, vert, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex, 2); - glBindTexture(GL_TEXTURE_2D, d->tex.texture()); + glBindTexture(GL_TEXTURE_2D, d->tex->texture()); glDrawArrays(GL_TRIANGLES, 0, 6); } else { @@ -548,8 +553,8 @@ void QFxImage::paintGLContents(GLPainter &p) float heightV = height(); float texleft = 0; - float texright = d->tex.glWidth(); - float textop = d->tex.glHeight(); + float texright = d->tex->glWidth(); + float textop = d->tex->glHeight(); float texbottom = 0; float imgleft = 0; float imgright = widthV; @@ -562,19 +567,19 @@ void QFxImage::paintGLContents(GLPainter &p) const int sgb = d->scaleGrid->bottom(); if (sgl) { - texleft = d->tex.glWidth() * float(sgl) / imgWidth; + texleft = d->tex->glWidth() * float(sgl) / imgWidth; imgleft = sgl; } if (sgr) { - texright = d->tex.glWidth() - float(sgr) / imgWidth; + texright = d->tex->glWidth() - float(sgr) / imgWidth; imgright = widthV - sgr; } if (sgt) { - textop = d->tex.glHeight() - float(sgb) / imgHeight; + textop = d->tex->glHeight() - float(sgb) / imgHeight; imgtop = sgt; } if (sgb) { - texbottom = d->tex.glHeight() * float(sgt) / imgHeight; + texbottom = d->tex->glHeight() * float(sgt) / imgHeight; imgbottom = heightV - sgb; } @@ -722,7 +727,7 @@ void QFxImage::paintGLContents(GLPainter &p) 1, texbottom, 1, 0 }; - glBindTexture(GL_TEXTURE_2D, d->tex.texture()); + glBindTexture(GL_TEXTURE_2D, d->tex->texture()); shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); @@ -847,7 +852,10 @@ void QFxImage::setSource(const QString &url) setImplicitHeight(0); #if defined(QFX_RENDER_OPENGL) d->texDirty = true; - d->tex.clear(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } #endif emit statusChanged(d->status); emit sourceChanged(d->source); @@ -908,7 +916,10 @@ void QFxImage::requestFinished() d->progress = 1.0; #if defined(QFX_RENDER_OPENGL) d->texDirty = true; - d->tex.clear(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } #endif emit statusChanged(d->status); emit sourceChanged(d->source); diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index b5c6055..cd07a37 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -74,7 +74,7 @@ public: QFxImagePrivate() : scaleGrid(0), tiled(false), smooth(false), opaque(false), #if defined(QFX_RENDER_OPENGL) - texDirty(true), + texDirty(true), tex(0), #endif status(QFxImage::Idle), sciReply(0), progress(0.0) { @@ -102,7 +102,7 @@ public: #if defined(QFX_RENDER_OPENGL) bool texDirty : 1; void checkDirty(); - GLTexture tex; + QSimpleCanvasItem::CachedTexture *tex; #endif QFxImage::Status status; diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index d52e31c..eacc85e 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -257,7 +257,10 @@ void QFxRect::doUpdate() #endif #if defined(QFX_RENDER_OPENGL) Q_D(QFxRect); - d->rectTexture.clear(); + if (d->rectTexture) { + d->rectTexture->release(); + d->rectTexture = 0; + } #endif const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; setPaintMargin((pw+1)/2); @@ -361,7 +364,10 @@ void QFxRect::setRadius(qreal radius) #if defined(QFX_RENDER_QPAINTER) d->rectImage = QPixmap(); #elif defined(QFX_RENDER_OPENGL) - d->rectTexture.clear(); + if (d->rectTexture) { + d->rectTexture->release(); + d->rectTexture = 0; + } #endif update(); } @@ -408,7 +414,10 @@ void QFxRect::setColor(const QColor &c) d->rectImage = QPixmap(); #endif #if defined(QFX_RENDER_OPENGL) - d->rectTexture.clear(); + if (d->rectTexture) { + d->rectTexture->release(); + d->rectTexture = 0; + } #endif update(); } @@ -521,42 +530,55 @@ void QFxRect::generateBorderedRect() void QFxRect::generateRoundedRect() { Q_D(QFxRect); - if (d->rectTexture.isNull()) { + if (!d->rectTexture) { const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; - QImage roundRect(d->radius*2 + 4 + pw*2, d->radius*2 + 4 + pw*2, QImage::Format_ARGB32_Premultiplied); - roundRect.fill(0); - QPainter p(&roundRect); - p.setRenderHint(QPainter::Antialiasing); - if (d->pen && d->pen->isValid()) { - QPen pn(QColor(pen()->color()), pen()->width()); - p.setPen(pn); - } else { - p.setPen(Qt::NoPen); + QString key = QString("QFxRect://r_%1_%2_%3_%4").arg(pw).arg(d->radius).arg((d->pen && d->pen->isValid())?d->pen->color().name():QString()).arg(d->color.name()); + + d->rectTexture = cachedTexture(key); + + if (!d->rectTexture) { + QPixmap roundRect(d->radius*2 + 4 + pw*2, d->radius*2 + 4 + pw*2); + roundRect.fill(Qt::transparent); + QPainter p(&roundRect); + p.setRenderHint(QPainter::Antialiasing); + if (d->pen && d->pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } + p.setBrush(d->color); + p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->radius, d->radius); + + d->rectTexture = cachedTexture(key, roundRect); } - p.setBrush(d->color); - p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->radius, d->radius); - d->rectTexture.setImage(roundRect, GLTexture::PowerOfTwo); } } void QFxRect::generateBorderedRect() { Q_D(QFxRect); - if (d->rectTexture.isNull()) { + if (!d->rectTexture) { const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; - QImage borderedRect(pw*2 + 4, pw*2 + 4, QImage::Format_ARGB32_Premultiplied); - borderedRect.fill(0); - QPainter p(&(borderedRect)); - p.setRenderHint(QPainter::Antialiasing); - if (d->pen && d->pen->isValid()) { - QPen pn(QColor(pen()->color()), pen()->width()); - p.setPen(pn); - } else { - p.setPen(Qt::NoPen); + QString key = QString("QFxRect://b_%1_%2_%3_%4").arg(pw).arg(d->radius).arg((d->pen && d->pen->isValid())?d->pen->color().name():QString()).arg(d->color.name()); + + d->rectTexture = cachedTexture(key); + + if (!d->rectTexture) { + QPixmap borderedRect(pw*2 + 4, pw*2 + 4); + borderedRect.fill(Qt::transparent); + QPainter p(&(borderedRect)); + p.setRenderHint(QPainter::Antialiasing); + if (d->pen && d->pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } + p.setBrush(d->color); + p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2); + d->rectTexture = cachedTexture(key, borderedRect); } - p.setBrush(d->color); - p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2); - d->rectTexture.setImage(borderedRect, GLTexture::PowerOfTwo); } } #endif @@ -721,8 +743,8 @@ void QFxRect::paintGLContents(GLPainter &p) QGLShaderProgram *shader = p.useTextureShader(); - float texWidth = d->rectTexture.width(); - float texHeight = d->rectTexture.height(); + float texWidth = d->rectTexture->width(); + float texHeight = d->rectTexture->height(); if (!texWidth || !texHeight) return; @@ -756,10 +778,10 @@ void QFxRect::paintGLContents(GLPainter &p) if (offset==1) texleft=texright=textop=texbottom=0.5; - texleft *= d->rectTexture.glWidth(); - texright *= d->rectTexture.glWidth(); - textop *= d->rectTexture.glHeight(); - texbottom *= d->rectTexture.glHeight(); + texleft *= d->rectTexture->glWidth(); + texright *= d->rectTexture->glWidth(); + textop *= d->rectTexture->glHeight(); + texbottom *= d->rectTexture->glHeight(); float vert1[] = { -pw/2, -pw/2, -pw/2, imgtop, @@ -852,35 +874,35 @@ void QFxRect::paintGLContents(GLPainter &p) texright, 0, texright, textop, - d->rectTexture.glWidth(), 0, + d->rectTexture->glWidth(), 0, texright, textop, - d->rectTexture.glWidth(), 0, - d->rectTexture.glWidth(), textop, + d->rectTexture->glWidth(), 0, + d->rectTexture->glWidth(), textop, - 0, d->rectTexture.glHeight(), + 0, d->rectTexture->glHeight(), 0, texbottom, - texleft, d->rectTexture.glHeight(), + texleft, d->rectTexture->glHeight(), 0, texbottom, - texleft, d->rectTexture.glHeight(), + texleft, d->rectTexture->glHeight(), texleft, texbottom, - texleft, d->rectTexture.glHeight(), + texleft, d->rectTexture->glHeight(), texleft, texbottom, - texright, d->rectTexture.glHeight(), + texright, d->rectTexture->glHeight(), texleft, texbottom, - texright, d->rectTexture.glHeight(), + texright, d->rectTexture->glHeight(), texright, texbottom, - texright, d->rectTexture.glHeight(), + texright, d->rectTexture->glHeight(), texright, texbottom, - d->rectTexture.glWidth(), d->rectTexture.glHeight(), + d->rectTexture->glWidth(), d->rectTexture->glHeight(), texright, texbottom, - d->rectTexture.glWidth(), d->rectTexture.glHeight(), - d->rectTexture.glWidth(), texbottom, + d->rectTexture->glWidth(), d->rectTexture->glHeight(), + d->rectTexture->glWidth(), texbottom, 0, textop, 0, texbottom, @@ -900,15 +922,15 @@ void QFxRect::paintGLContents(GLPainter &p) texright, textop, texright, texbottom, - d->rectTexture.glWidth(), textop, + d->rectTexture->glWidth(), textop, texright, texbottom, - d->rectTexture.glWidth(), textop, - d->rectTexture.glWidth(), texbottom }; + d->rectTexture->glWidth(), textop, + d->rectTexture->glWidth(), texbottom }; - glBindTexture(GL_TEXTURE_2D, d->rectTexture.texture()); + glBindTexture(GL_TEXTURE_2D, d->rectTexture->texture()); shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h index 6d11917..d68eb4e 100644 --- a/src/declarative/fx/qfxrect_p.h +++ b/src/declarative/fx/qfxrect_p.h @@ -69,7 +69,7 @@ class QFxRectPrivate : public QFxItemPrivate public: QFxRectPrivate() - : gradient(0), pen(0), radius(0) + : rectTexture(0), gradient(0), pen(0), radius(0) { } @@ -83,7 +83,7 @@ public: } #if defined(QFX_RENDER_OPENGL) - GLTexture rectTexture; + QSimpleCanvasItem::CachedTexture *rectTexture; #endif QColor getColor(); QColor color; -- cgit v0.12 From 3ac9b6bdeb9f7522fa857fbc25a9da48e6d82186 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 9 Jun 2009 10:50:10 +1000 Subject: Fixed compile with MinGW 3.4. This compiler doesn't seem to follow the same rule as others for implicit conversions to/from wchar_t. Add the necessary casts, keeping in mind that sizeof(wchar_t) == 2 on Windows. --- src/gui/util/qdesktopservices_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp index 8d2701c..9f8efb4 100644 --- a/src/gui/util/qdesktopservices_win.cpp +++ b/src/gui/util/qdesktopservices_win.cpp @@ -115,11 +115,11 @@ static bool launchWebBrowser(const QUrl &url) if (res == ERROR_SUCCESS) { returnValue = RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast(keyValue), &bufferSize); if (!returnValue) - keyName = QString::fromUtf16(keyValue); + keyName = QString::fromUtf16((const ushort*)keyValue); RegCloseKey(handle); } keyName += QLatin1String("\\Shell\\Open\\Command"); - res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName.utf16(), 0, KEY_READ, &handle); + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle); if (res != ERROR_SUCCESS) return false; -- cgit v0.12 From a359abb4ccf5a2dc3bd1fac9836231677b3dc14f Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 9 Jun 2009 10:53:25 +1000 Subject: Protect EGL property names that only exist in some versions with #ifdefs Reviewed-by: trustme --- src/opengl/qegl.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/opengl/qegl.cpp b/src/opengl/qegl.cpp index f1ae4ed..290f77c 100644 --- a/src/opengl/qegl.cpp +++ b/src/opengl/qegl.cpp @@ -413,12 +413,18 @@ int QEglProperties::value(int name) const case EGL_RED_SIZE: return 0; case EGL_GREEN_SIZE: return 0; case EGL_BLUE_SIZE: return 0; - case EGL_LUMINANCE_SIZE: return 0; case EGL_ALPHA_SIZE: return 0; +#if defined(EGL_LUMINANCE_SIZE) + case EGL_LUMINANCE_SIZE: return 0; +#endif +#if defined(EGL_ALPHA_MASK_SIZE) case EGL_ALPHA_MASK_SIZE: return 0; +#endif case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE; case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE; +#if defined(EGL_COLOR_BUFFER_TYPE) case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER; +#endif case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE; case EGL_CONFIG_ID: return EGL_DONT_CARE; case EGL_DEPTH_SIZE: return 0; @@ -427,7 +433,9 @@ int QEglProperties::value(int name) const case EGL_NATIVE_VISUAL_TYPE: return EGL_DONT_CARE; case EGL_MAX_SWAP_INTERVAL: return EGL_DONT_CARE; case EGL_MIN_SWAP_INTERVAL: return EGL_DONT_CARE; +#if defined(EGL_RENDERABLE_TYPE) case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT; +#endif case EGL_SAMPLE_BUFFERS: return 0; case EGL_SAMPLES: return 0; case EGL_STENCIL_SIZE: return 0; -- cgit v0.12 From 1bbe23c5814dfda4cc6154c49e5bbf7c6ead7eba Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 9 Jun 2009 10:54:37 +1000 Subject: Make OpenGL/ES 1.1 work again for Qt/Embedded Reviewed-by: trustme --- src/opengl/qgl.cpp | 15 +++++++++++++++ src/opengl/qgl_p.h | 3 +-- src/opengl/qglframebufferobject.cpp | 2 ++ src/opengl/qglpixelbuffer.cpp | 5 +++-- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 2e72851..37a9916 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -65,12 +65,19 @@ #include "qimage.h" #include "qgl_p.h" +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) #include "gl2paintengineex/qpaintengineex_opengl2_p.h" +#endif #ifndef QT_OPENGL_ES_2 #include #endif +#ifdef Q_WS_QWS +#include +#include +#endif + #include #include @@ -4428,7 +4435,11 @@ void QGLDrawable::swapBuffers() void QGLDrawable::makeCurrent() { previous_fbo = 0; +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) if (!pixmapData && !fbo) { +#else +#endif + if (!fbo) { QGLContext *ctx = context(); previous_fbo = ctx->d_ptr->current_fbo; ctx->d_ptr->current_fbo = 0; @@ -4561,8 +4572,10 @@ QColor QGLDrawable::backgroundColor() const { if (widget) return widget->palette().brush(widget->backgroundRole()).color(); +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) else if (pixmapData) return pixmapData->fillColor(); +#endif return QApplication::palette().brush(QPalette::Background).color(); } @@ -4590,8 +4603,10 @@ bool QGLDrawable::autoFillBackground() const { if (widget) return widget->autoFillBackground(); +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) else if (pixmapData) return pixmapData->needsFill(); +#endif else return false; } diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index b3523d4..4af8598 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -428,8 +428,7 @@ private: extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg(); #ifdef Q_WS_QWS -class QOpenGLPaintEngine; -extern QOpenGLPaintEngine* qt_qgl_paint_engine(); +extern QPaintEngine* qt_qgl_paint_engine(); extern EGLDisplay qt_qgl_egl_display(); #endif diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 3e7ca0a..fb16107 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -43,7 +43,9 @@ #include #include +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) #include +#endif #ifndef QT_OPENGL_ES_2 #include diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 483856a..0af97e3 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -76,12 +76,13 @@ \sa {opengl/pbuffers}{Pbuffers Example} */ -#include - #include #include #include +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) +#include +#endif #ifndef QT_OPENGL_ES_2 #include #endif -- cgit v0.12 From 6d4fe549e7a258913b19f52e29bcfb84cc8a97ad Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 9 Jun 2009 12:58:10 +1000 Subject: Fix build breakage from 1bbe23c5 - endif in the wrong place Reviewed-by: trustme --- src/opengl/qgl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 37a9916..146d088 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4438,8 +4438,8 @@ void QGLDrawable::makeCurrent() #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) if (!pixmapData && !fbo) { #else -#endif if (!fbo) { +#endif QGLContext *ctx = context(); previous_fbo = ctx->d_ptr->current_fbo; ctx->d_ptr->current_fbo = 0; -- cgit v0.12 From cea87b08520888feff2f10d1bbf71bc8c2f1d780 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 9 Jun 2009 13:20:51 +1000 Subject: Another breakage in 1bbe23c5 - move qpaintengineex_opengl2_p.h include up Moving qpaintengineex_opengl2_p.h down caused it to come after an include of , which causes problems on some platforms. Move it back up again. Reviewed-by: trustme --- src/opengl/qglpixelbuffer.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 0af97e3..9b7a506 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -76,13 +76,16 @@ \sa {opengl/pbuffers}{Pbuffers Example} */ -#include -#include -#include +#include #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) #include #endif + +#include +#include +#include + #ifndef QT_OPENGL_ES_2 #include #endif -- cgit v0.12 From edd535defde42cf4b57c6144b6ba8a0607363d5e Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 9 Jun 2009 14:59:16 +1000 Subject: Fix OpenGL texture access issues --- src/declarative/fx/qfximage.cpp | 100 ++++++++++++++++++++--------------- src/declarative/fx/qfxtext.cpp | 19 ++++--- src/declarative/opengl/gltexture.cpp | 8 +++ src/declarative/opengl/gltexture.h | 1 + 4 files changed, 78 insertions(+), 50 deletions(-) diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 03a674d..c5e7e89 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -500,6 +500,12 @@ void QFxImage::paintGLContents(GLPainter &p) float glWidth = d->tex->glWidth(); float glHeight = d->tex->glHeight(); + float deltaX = 0.5 / qreal(d->tex->glSize().width()); + float deltaY = 0.5 / qreal(d->tex->glSize().height()); + glWidth -= deltaX; + glHeight -= deltaY; + + float vert[] = { 0, heightV, widthV, heightV, @@ -510,12 +516,12 @@ void QFxImage::paintGLContents(GLPainter &p) widthV, 0 }; float tex[] = { - 0, 0, - glWidth, 0, - 0, glHeight, + deltaX, deltaY, + glWidth, deltaY, + deltaX, glHeight, - glWidth, 0, - 0, glHeight, + glWidth, deltaY, + deltaX, glHeight, glWidth, glHeight }; @@ -551,11 +557,17 @@ void QFxImage::paintGLContents(GLPainter &p) float widthV = width(); float heightV = height(); - - float texleft = 0; - float texright = d->tex->glWidth(); - float textop = d->tex->glHeight(); - float texbottom = 0; + float glWidth = d->tex->glWidth(); + float glHeight = d->tex->glHeight(); + float deltaX = 0.5 / qreal(d->tex->glSize().width()); + float deltaY = 0.5 / qreal(d->tex->glSize().height()); + glHeight -= deltaY; + glWidth -= deltaX; + + float texleft = deltaX; + float texright = glWidth; + float textop = glHeight; + float texbottom = deltaY; float imgleft = 0; float imgright = widthV; float imgtop = 0; @@ -567,19 +579,19 @@ void QFxImage::paintGLContents(GLPainter &p) const int sgb = d->scaleGrid->bottom(); if (sgl) { - texleft = d->tex->glWidth() * float(sgl) / imgWidth; + texleft = deltaX + d->tex->glWidth() * float(sgl) / imgWidth; imgleft = sgl; } if (sgr) { - texright = d->tex->glWidth() - float(sgr) / imgWidth; + texright = d->tex->glWidth() - float(sgr) / imgWidth - deltaX; imgright = widthV - sgr; } if (sgt) { - textop = d->tex->glHeight() - float(sgb) / imgHeight; + textop = d->tex->glHeight() - float(sgb) / imgHeight - deltaY; imgtop = sgt; } if (sgb) { - texbottom = d->tex->glHeight() * float(sgt) / imgHeight; + texbottom = deltaY + d->tex->glHeight() * float(sgt) / imgHeight; imgbottom = heightV - sgb; } @@ -655,35 +667,35 @@ void QFxImage::paintGLContents(GLPainter &p) widthV, imgbottom, widthV, heightV }; - float tex1[] = { 0, 1, - 0, textop, - texleft, 1, + float tex1[] = { deltaX, glHeight, + deltaX, textop, + texleft, glHeight, - 0, textop, - texleft, 1, + deltaX, textop, + texleft, glHeight, texleft, textop, - texleft, 1, + texleft, glHeight, texleft, textop, - texright, 1, + texright, glHeight, texleft, textop, - texright, 1, + texright, glHeight, texright, textop, - texright, 1, + texright, glHeight, texright, textop, - 1, 1, + glWidth, glHeight, texright, textop, - 1, 1, - 1, textop, + glWidth, glHeight, + glWidth, textop, - 0, textop, - 0, texbottom, + deltaX, textop, + deltaX, texbottom, texleft, textop, - 0, texbottom, + deltaX, texbottom, texleft, textop, texleft, texbottom, @@ -697,35 +709,35 @@ void QFxImage::paintGLContents(GLPainter &p) texright, textop, texright, texbottom, - 1, textop, + glWidth, textop, texright, texbottom, - 1, textop, - 1, texbottom, + glWidth, textop, + glWidth, texbottom, - 0, texbottom, - 0, 0, + deltaX, texbottom, + deltaX, deltaY, texleft, texbottom, - 0, 0, + deltaX, deltaY, texleft, texbottom, - texleft, 0, + texleft, deltaY, texleft, texbottom, - texleft, 0, + texleft, deltaY, texright, texbottom, - texleft, 0, + texleft, deltaY, texright, texbottom, - texright, 0, + texright, deltaY, texright, texbottom, - texright, 0, - 1, texbottom, + texright, deltaY, + glWidth, texbottom, - texright, 0, - 1, texbottom, - 1, 0 }; + texright, deltaY, + glWidth, texbottom, + glWidth, deltaY }; glBindTexture(GL_TEXTURE_2D, d->tex->texture()); diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index 7a2dd8d..031c0f8 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -793,9 +793,16 @@ void QFxText::paintGLContents(GLPainter &p) float widthV = d->imgCache.width(); float heightV = d->imgCache.height(); + float glWidth = d->tex.glWidth(); + float glHeight = d->tex.glHeight(); QGLShaderProgram *shader = p.useTextureShader(); + float deltaX = 0.5 / qreal(d->tex.glSize().width()); + float deltaY = 0.5 / qreal(d->tex.glSize().height()); + glWidth -= deltaX; + glHeight -= deltaY; + GLfloat vertices[] = { x, y + heightV, x + widthV, y + heightV, x, y, @@ -804,13 +811,13 @@ void QFxText::paintGLContents(GLPainter &p) x, y, x + widthV, y }; - GLfloat texVertices[] = { 0, 0, - d->tex.glWidth(), 0, - 0, d->tex.glHeight(), + GLfloat texVertices[] = { deltaX, deltaY, + glWidth, deltaY, + deltaX, glHeight, - d->tex.glWidth(), 0, - 0, d->tex.glHeight(), - d->tex.glWidth(), d->tex.glHeight() }; + glWidth, deltaY, + deltaX, glHeight, + glWidth, glHeight }; shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); diff --git a/src/declarative/opengl/gltexture.cpp b/src/declarative/opengl/gltexture.cpp index cd9c406..c2a02df 100644 --- a/src/declarative/opengl/gltexture.cpp +++ b/src/declarative/opengl/gltexture.cpp @@ -95,6 +95,7 @@ public: qreal glWidth; qreal glHeight; + QSize glSize; void genTexture(); }; @@ -199,6 +200,7 @@ void GLTexture::setImage(const QImage &img, ImageMode mode) } d->glWidth = 1.; d->glHeight = 1.; + d->glSize = img.size(); } else { // mode == PowerOfTwo @@ -233,6 +235,7 @@ void GLTexture::setImage(const QImage &img, ImageMode mode) d->glWidth = qreal(img.width()) / qreal(max); d->glHeight = qreal(img.height()) / qreal(max); + d->glSize = QSize(max, max); } d->width = img.width(); @@ -273,6 +276,11 @@ qreal GLTexture::glHeight() const return d->glHeight; } +QSize GLTexture::glSize() const +{ + return d->glSize; +} + /*! Sets the \a size of the texture. This will destroy the current contents of the texture. If an image has been assigned, it will need to be reassigned diff --git a/src/declarative/opengl/gltexture.h b/src/declarative/opengl/gltexture.h index d301d8a..c08d68f 100644 --- a/src/declarative/opengl/gltexture.h +++ b/src/declarative/opengl/gltexture.h @@ -77,6 +77,7 @@ public: int height() const; qreal glWidth() const; qreal glHeight() const; + QSize glSize() const; QSize size() const; void setSize(const QSize &); -- cgit v0.12 From 45ad5f8e643f8a1bd52143ad628e5418f5ae8fa3 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 9 Jun 2009 15:16:16 +1000 Subject: Can now dynamically delete objects as well. The QtScript object wrapper now has a destroy function. This should work for all QML objects. This commit also has some clean up in the dynamic creation code, which still has a bug regarding path resolution. --- src/declarative/qml/qmlcomponent.cpp | 1 + src/declarative/qml/qmlcomponent.h | 1 + src/declarative/qml/qmlengine.cpp | 74 +++++++++++++++++++++++++++--------- src/declarative/qml/qmlengine.h | 1 - src/declarative/qml/qmlengine_p.h | 3 ++ 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 267fba8..f90af4a 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE class QByteArray; +int statusId = qRegisterMetaType("QmlComponent::Status"); /*! \class QmlComponent diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h index bb76c8b..fe0c422 100644 --- a/src/declarative/qml/qmlcomponent.h +++ b/src/declarative/qml/qmlcomponent.h @@ -104,6 +104,7 @@ private: friend class QmlVME; friend struct QmlCompositeTypeData; }; +Q_DECLARE_METATYPE(QmlComponent::Status); QML_DECLARE_TYPE(QmlComponent) QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index d8ca809..73b9245 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -842,27 +842,48 @@ QScriptValue QmlEngine::qmlScriptObject(QObject* object, QmlEngine* engine) This function takes the URL of a QML file as its only argument. It returns a component object which can be used to create and load that QML file. - Example JavaScript: + Example JavaScript is below, remember that QML files that might be loaded + over the network cannot be expected to be ready immediately. \code - component = createComponent("Sprite.qml"); - if(component.isReady()){ - sprite = component.create(); - if(sprite == 0){ + var component; + var sprite; + function finishCreation(){ + if(component.isReady()){ + sprite = component.createObject(); + if(sprite == 0){ + // Error Handling + }else{ + sprite.parent = page; + sprite.x = 200; + //... + } + }else if(component.isError()){ // Error Handling - }else{ - sprite.parent = page; - sprite.x = 200; - //... } + } + + component = createComponent("Sprite.qml"); + if(component.isReady()){ + finishCreation(); }else{ - // The finishCreation function does the same thing as the above - // if(component.isReady()) branch component.statusChanged.connect(finishCreation); } \endcode - Remember that QML files that might be loaded over the network cannot be - expected to be ready immediately. + If you are certain the files will be local, you could simplify to + + \code + component = createComponent("Sprite.qml"); + sprite = component.createObject(); + if(sprite == 0){ + // Error Handling + }else{ + sprite.parent = page; + sprite.x = 200; + //... + } + \endcode + */ QScriptValue QmlEngine::createComponent(QScriptContext *ctxt, QScriptEngine *engine) { @@ -872,8 +893,8 @@ QScriptValue QmlEngine::createComponent(QScriptContext *ctxt, QScriptEngine *eng if(ctxt->argumentCount() != 1 || !activeEngine){ c = new QmlComponent(activeEngine); }else{ - c = new QmlComponent(activeEngine, QUrl(ctxt->argument(0).toString()), - activeEngine); + QUrl url = QUrl(ctxt->argument(0).toString()); + c = new QmlComponent(activeEngine, url, activeEngine); } return engine->newQObject(c); } @@ -897,7 +918,7 @@ QScriptValue QmlEngine::createQMLObject(QScriptContext *ctxt, QScriptEngine *eng if(ctxt->argumentCount() < 1){ qWarning() << "createQMLObject requires a string argument."; }else{ - qWarning() << "createQMLObject failed inexplicably."; + qWarning() << "createQMLObject cannot find engine."; } return engine->nullValue(); } @@ -1518,18 +1539,37 @@ void QmlContextScriptClass::setProperty(QScriptValue &object, ///////////////////////////////////////////////////////////// /* The QmlObjectScriptClass handles property access for QObjects - via QtScript. + via QtScript. It is also used to provide a more useful API in + QtScript for QML. */ + +QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine) +{ + QObject* obj = context->thisObject().data().toQObject(); + if(obj) + delete obj; + context->thisObject().setData(QScriptValue(engine, 0)); + return engine->nullValue(); +} + QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) : QmlScriptClass(bindEngine) { engine = bindEngine; + prototypeObject = engine->scriptEngine()->newObject(); + prototypeObject.setProperty("destroy", + engine->scriptEngine()->newFunction(QmlObjectDestroy)); } QmlObjectScriptClass::~QmlObjectScriptClass() { } +QScriptValue QmlObjectScriptClass::prototype() const +{ + return prototypeObject; +} + QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id) diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h index ca66097..f114379 100644 --- a/src/declarative/qml/qmlengine.h +++ b/src/declarative/qml/qmlengine.h @@ -90,7 +90,6 @@ public: static QScriptValue qmlScriptObject(QObject*, QmlEngine*); - // Below two functions provide a way to dynamically create objects from JS static QScriptValue createComponent(QScriptContext*, QScriptEngine*); static QScriptValue createQMLObject(QScriptContext*, QScriptEngine*); diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 89b0a4a..d7249e4 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -221,6 +221,9 @@ public: QmlObjectScriptClass(QmlEngine *); ~QmlObjectScriptClass(); + virtual QScriptValue prototype () const; + QScriptValue prototypeObject; + virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id); -- cgit v0.12 From ebcf875d90d940103e409de9127bb592d7336afe Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 9 Jun 2009 09:10:53 +0200 Subject: qdoc: Inserted
between summary sections. Also added the left and right borders to the function headers in the detail sections. --- tools/qdoc3/htmlgenerator.cpp | 3 ++- tools/qdoc3/test/classic.css | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 90d3b04..0c21534 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -1073,6 +1073,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, if (!s->inherited.isEmpty()) needOtherSection = true; } else { + out() << "
\n"; out() << "\n"; @@ -2335,7 +2336,7 @@ void HtmlGenerator::generateSynopsis(const Node *node, QString HtmlGenerator::highlightedCode(const QString& markedCode, CodeMarker *marker, const Node *relative, - CodeMarker::SynopsisStyle style, + CodeMarker::SynopsisStyle , bool nameAlignment) { QString src = markedCode; diff --git a/tools/qdoc3/test/classic.css b/tools/qdoc3/test/classic.css index 3e2370d..85bb348 100644 --- a/tools/qdoc3/test/classic.css +++ b/tools/qdoc3/test/classic.css @@ -17,7 +17,7 @@ h3.fn,span.fn background-color: #e0eff6; border-width: 1px; border-style: solid; - border-color: #3388be #e0eff6 #e9f8ff #e0eff6; + border-color: #3388be #3388be #e9f8ff #3388be; font-weight: bold; padding: 6px 0px 6px 10px; } -- cgit v0.12 From b5c401b9aa3481886ad9e2d7816680c97839004e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 25 May 2009 11:59:10 +0200 Subject: Add recursive drawing method to QGraphicsScene. For now it's opt-in, but the important thing is by effectively implementing Simple Canvas' approach to drawing, we're in theory (and in practise measured on the desktop) as fast as Simple Canvas when rendering. --- src/gui/graphicsview/qgraphicsscene.cpp | 82 +++++++++++++++++++++++++++++++++ src/gui/graphicsview/qgraphicsscene_p.h | 3 ++ src/gui/graphicsview/qgraphicsview.cpp | 34 ++++++++------ src/gui/graphicsview/qgraphicsview.h | 3 +- 4 files changed, 107 insertions(+), 15 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 49c2329..362d66d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1870,6 +1870,11 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex; } +static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return qt_closestLeaf(item2, item1); +} + /*! \internal @@ -5013,6 +5018,83 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } } +void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, + const QRegion &exposedRegion, QWidget *widget) +{ + if (item && (!item->isVisible() || qFuzzyIsNull(item->opacity()))) + return; + + painter->save(); + + // Set transform + if (item) { + if (item->d_ptr->itemIsUntransformable()) { + painter->setWorldTransform(item->deviceTransform(viewTransform), false); + } else { + const QPointF &pos = item->d_ptr->pos; + bool posNull = pos.isNull(); + if (!posNull || item->d_ptr->hasTransform) { + if (item->d_ptr->hasTransform) { + QTransform x = item->transform(); + if (!posNull) + x *= QTransform::fromTranslate(pos.x(), pos.y()); + painter->setWorldTransform(x, true); + } else { + painter->setWorldTransform(QTransform::fromTranslate(pos.x(), pos.y()), true); + } + } + } + } + + // Setup recursive clipping. + if (item && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) + painter->setClipPath(item->shape(), Qt::IntersectClip); + +#if 0 + const QList &children = item ? item->d_ptr->children : topLevelItems; +#else + // ### if we ensure all children are sorted by Z by default, we don't have + // to sort this list for each paint. + QList children = item ? item->d_ptr->children : topLevelItems; + qSort(children.begin(), children.end(), qt_notclosestLeaf); +#endif + + // Draw children behind + int i; + for (i = 0; i < children.size(); ++i) { + QGraphicsItem *child = children.at(i); + if (!(child->flags() & QGraphicsItem::ItemStacksBehindParent)) + break; + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget); + } + + // Draw item + if (item) { + QRect itemViewRect = painter->worldTransform().mapRect(item->boundingRect()).toRect().adjusted(-1, -1, 1, 1); + if (itemViewRect.intersects(exposedRegion.boundingRect())) { + QStyleOptionGraphicsItem option; + item->d_ptr->initStyleOption(&option, painter->worldTransform(), exposedRegion); + + bool clipsToShape = (item->flags() & QGraphicsItem::ItemClipsToShape); + if (clipsToShape) { + painter->save(); + painter->setClipPath(item->shape(), Qt::IntersectClip); + } + + drawItemHelper(item, painter, &option, widget, false); + + if (clipsToShape) + painter->restore(); + } + } + + // Draw children in front + for (; i < children.size(); ++i) + drawSubtreeRecursive(children.at(i), painter, viewTransform, exposedRegion, widget); + + painter->restore(); +} + /*! Paints the given \a items using the provided \a painter, after the background has been drawn, and before the foreground has been diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 9ace725..369b0ef 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -253,6 +253,9 @@ public: const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); + void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, + const QRegion &exposedRegion, QWidget *widget); + QStyle *style; QFont font; void setFont_helper(const QFont &font); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 10b837a..2459c49 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3387,10 +3387,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event) bool allItems = false; QList itemList = d->findItems(exposedRegion, &allItems); -#ifdef QGRAPHICSVIEW_DEBUG - int exposedTime = stopWatch.elapsed(); -#endif - if ((d->cacheMode & CacheBackground) #ifdef Q_WS_X11 && X11->use_xrender @@ -3436,16 +3432,26 @@ void QGraphicsView::paintEvent(QPaintEvent *event) int backgroundTime = stopWatch.elapsed() - exposedTime; #endif - if (!itemList.isEmpty()) { - // Generate the style options. - const int numItems = itemList.size(); - QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. - QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); - for (int i = 0; i < numItems; ++i) - itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, exposedRegion, allItems); - // Draw the items. - drawItems(&painter, numItems, itemArray, styleOptionArray); - d->freeStyleOptionsArray(styleOptionArray); + const char *directEnv = getenv("QGRAPHICSVIEW_DIRECT"); + bool overrideDirectPaint = directEnv && atoi(directEnv) != 0; + if (overrideDirectPaint || (d->optimizationFlags & BypassDrawItems)) { + d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, exposedRegion, viewport()); + } else { + // Find all exposed items + bool allItems = false; + QList itemList = d->findItems(exposedRegion, &allItems); + + if (!itemList.isEmpty()) { + // Generate the style options. + const int numItems = itemList.size(); + QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. + QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); + for (int i = 0; i < numItems; ++i) + itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, exposedRegion, allItems); + // Draw the items. + drawItems(&painter, numItems, itemArray, styleOptionArray); + d->freeStyleOptionsArray(styleOptionArray); + } } #ifdef QGRAPHICSVIEW_DEBUG diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h index c3ea6e5..7692e16 100644 --- a/src/gui/graphicsview/qgraphicsview.h +++ b/src/gui/graphicsview/qgraphicsview.h @@ -112,7 +112,8 @@ public: enum OptimizationFlag { DontClipPainter = 0x1, // obsolete DontSavePainterState = 0x2, - DontAdjustForAntialiasing = 0x4 + DontAdjustForAntialiasing = 0x4, + BypassDrawItems = 0x8 }; Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag) -- cgit v0.12 From 1873203f3a3c64a2eb59bbc555eb8edf6b30315a Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 25 May 2009 16:41:31 +0200 Subject: Fix optimization flags and opacity. --- src/gui/graphicsview/qgraphicsscene.cpp | 44 +++++++++++++++++++++++---------- src/gui/graphicsview/qgraphicsscene_p.h | 3 ++- src/gui/graphicsview/qgraphicsview.cpp | 3 ++- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 362d66d..e360a07 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5019,12 +5019,22 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, - const QRegion &exposedRegion, QWidget *widget) + const QRegion &exposedRegion, QWidget *widget, + QGraphicsView::OptimizationFlags optimizationFlags) { - if (item && (!item->isVisible() || qFuzzyIsNull(item->opacity()))) + if (item && (!item->isVisible())) return; - painter->save(); + bool hasOpacity = item && item->d_ptr->hasEffectiveOpacity; + bool childClip = (item && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)); + bool savePainter = !(optimizationFlags & QGraphicsView::DontSavePainterState); + + QTransform restoreTransform; + if (childClip || hasOpacity) { + painter->save(); + } else { + restoreTransform = painter->worldTransform(); + } // Set transform if (item) { @@ -5047,8 +5057,10 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } // Setup recursive clipping. - if (item && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) + if (childClip) painter->setClipPath(item->shape(), Qt::IntersectClip); + if (hasOpacity) + painter->setOpacity(item->effectiveOpacity()); #if 0 const QList &children = item ? item->d_ptr->children : topLevelItems; @@ -5065,34 +5077,40 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QGraphicsItem *child = children.at(i); if (!(child->flags() & QGraphicsItem::ItemStacksBehindParent)) break; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, optimizationFlags); } // Draw item - if (item) { - QRect itemViewRect = painter->worldTransform().mapRect(item->boundingRect()).toRect().adjusted(-1, -1, 1, 1); + if (item && !item->d_ptr->isFullyTransparent()) { + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + QRect itemViewRect = painter->worldTransform().mapRect(brect).toRect().adjusted(-1, -1, 1, 1); if (itemViewRect.intersects(exposedRegion.boundingRect())) { QStyleOptionGraphicsItem option; item->d_ptr->initStyleOption(&option, painter->worldTransform(), exposedRegion); bool clipsToShape = (item->flags() & QGraphicsItem::ItemClipsToShape); - if (clipsToShape) { + if (savePainter || clipsToShape) painter->save(); + if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); - } drawItemHelper(item, painter, &option, widget, false); - - if (clipsToShape) + + if (savePainter || clipsToShape) painter->restore(); } } // Draw children in front for (; i < children.size(); ++i) - drawSubtreeRecursive(children.at(i), painter, viewTransform, exposedRegion, widget); + drawSubtreeRecursive(children.at(i), painter, viewTransform, exposedRegion, widget, optimizationFlags); - painter->restore(); + if (childClip || hasOpacity) { + painter->restore(); + } else { + painter->setWorldTransform(restoreTransform, /* combine = */ false); + } } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 369b0ef..0ac1765 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -57,6 +57,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +#include "qgraphicsview.h" #include "qgraphicsscene_bsp_p.h" #include "qgraphicsitem_p.h" @@ -254,7 +255,7 @@ public: bool painterStateProtection); void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, - const QRegion &exposedRegion, QWidget *widget); + const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags); QStyle *style; QFont font; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2459c49..40c84db 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3435,7 +3435,8 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const char *directEnv = getenv("QGRAPHICSVIEW_DIRECT"); bool overrideDirectPaint = directEnv && atoi(directEnv) != 0; if (overrideDirectPaint || (d->optimizationFlags & BypassDrawItems)) { - d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, exposedRegion, viewport()); + d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, exposedRegion, + viewport(), d->optimizationFlags); } else { // Find all exposed items bool allItems = false; -- cgit v0.12 From 6cbc582c9699498e7f1762121bb2cff04d2596ce Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 25 May 2009 17:15:03 +0200 Subject: Minor optimizations. --- src/gui/graphicsview/qgraphicsscene.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e360a07..45108ca 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5022,15 +5022,14 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags) { - if (item && (!item->isVisible())) + if (item && !item->d_ptr->visible) return; - bool hasOpacity = item && item->d_ptr->hasEffectiveOpacity; - bool childClip = (item && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)); + bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); bool savePainter = !(optimizationFlags & QGraphicsView::DontSavePainterState); QTransform restoreTransform; - if (childClip || hasOpacity) { + if (childClip) { painter->save(); } else { restoreTransform = painter->worldTransform(); @@ -5059,7 +5058,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Setup recursive clipping. if (childClip) painter->setClipPath(item->shape(), Qt::IntersectClip); - if (hasOpacity) + if (item) painter->setOpacity(item->effectiveOpacity()); #if 0 @@ -5075,7 +5074,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * int i; for (i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); - if (!(child->flags() & QGraphicsItem::ItemStacksBehindParent)) + if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, optimizationFlags); } @@ -5089,7 +5088,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QStyleOptionGraphicsItem option; item->d_ptr->initStyleOption(&option, painter->worldTransform(), exposedRegion); - bool clipsToShape = (item->flags() & QGraphicsItem::ItemClipsToShape); + bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); if (savePainter || clipsToShape) painter->save(); if (clipsToShape) @@ -5106,7 +5105,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * for (; i < children.size(); ++i) drawSubtreeRecursive(children.at(i), painter, viewTransform, exposedRegion, widget, optimizationFlags); - if (childClip || hasOpacity) { + if (childClip) { painter->restore(); } else { painter->setWorldTransform(restoreTransform, /* combine = */ false); -- cgit v0.12 From 6f1cca3661b794f170ed00fdc84e8ad31789aa9f Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 26 May 2009 09:07:44 +0200 Subject: Further optimizations, from the simple canvas rendering logics. --- src/gui/graphicsview/qgraphicsscene.cpp | 115 +++++++++++++++++--------------- src/gui/graphicsview/qgraphicsscene_p.h | 3 +- src/gui/graphicsview/qgraphicsview.cpp | 2 +- 3 files changed, 63 insertions(+), 57 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 45108ca..7eb49e9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5018,27 +5018,20 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } } -void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, +void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, + const QTransform &viewTransform, const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags) { - if (item && !item->d_ptr->visible) + if (item && item->d_ptr->isInvisible()) return; - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); - bool savePainter = !(optimizationFlags & QGraphicsView::DontSavePainterState); - - QTransform restoreTransform; - if (childClip) { - painter->save(); - } else { - restoreTransform = painter->worldTransform(); - } - - // Set transform + // Calculate the full transform for this item. + QTransform transform; + QRect viewBoundingRect; if (item) { if (item->d_ptr->itemIsUntransformable()) { - painter->setWorldTransform(item->deviceTransform(viewTransform), false); + transform = item->deviceTransform(viewTransform); } else { const QPointF &pos = item->d_ptr->pos; bool posNull = pos.isNull(); @@ -5047,69 +5040,81 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QTransform x = item->transform(); if (!posNull) x *= QTransform::fromTranslate(pos.x(), pos.y()); - painter->setWorldTransform(x, true); + transform = x * parentTransform; } else { - painter->setWorldTransform(QTransform::fromTranslate(pos.x(), pos.y()), true); + transform = QTransform::fromTranslate(pos.x(), pos.y()) * parentTransform; } + } else { + transform = parentTransform; } } + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + viewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1) & exposedRegion.boundingRect(); + } else { + transform = parentTransform; } - // Setup recursive clipping. - if (childClip) - painter->setClipPath(item->shape(), Qt::IntersectClip); - if (item) - painter->setOpacity(item->effectiveOpacity()); - -#if 0 - const QList &children = item ? item->d_ptr->children : topLevelItems; -#else - // ### if we ensure all children are sorted by Z by default, we don't have - // to sort this list for each paint. + // Find and sort children. QList children = item ? item->d_ptr->children : topLevelItems; qSort(children.begin(), children.end(), qt_notclosestLeaf); -#endif + + bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); + bool dontDrawItem = !item || viewBoundingRect.isEmpty(); + bool dontDrawChildren = item && dontDrawItem && childClip; + childClip &= !dontDrawChildren & !children.isEmpty(); + + // Clip children. + if (childClip) { + painter->save(); + painter->setWorldTransform(transform); + painter->setClipPath(item->shape(), Qt::IntersectClip); + } // Draw children behind int i; - for (i = 0; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); - if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) - break; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, optimizationFlags); + if (!dontDrawChildren) { + for (i = 0; i < children.size(); ++i) { + QGraphicsItem *child = children.at(i); + if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) + break; + drawSubtreeRecursive(child, painter, transform, viewTransform, + exposedRegion, widget, optimizationFlags); + } } // Draw item - if (item && !item->d_ptr->isFullyTransparent()) { - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - QRect itemViewRect = painter->worldTransform().mapRect(brect).toRect().adjusted(-1, -1, 1, 1); - if (itemViewRect.intersects(exposedRegion.boundingRect())) { - QStyleOptionGraphicsItem option; - item->d_ptr->initStyleOption(&option, painter->worldTransform(), exposedRegion); + if (!dontDrawItem) { + QStyleOptionGraphicsItem option; + item->d_ptr->initStyleOption(&option, transform, exposedRegion); - bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); - if (savePainter || clipsToShape) - painter->save(); - if (clipsToShape) - painter->setClipPath(item->shape(), Qt::IntersectClip); + bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); + bool savePainter = clipsToShape || !(optimizationFlags & QGraphicsView::DontSavePainterState); + if (savePainter) + painter->save(); + if (!childClip) + painter->setWorldTransform(transform); + if (clipsToShape) + painter->setClipPath(item->shape(), Qt::IntersectClip); + painter->setOpacity(item->effectiveOpacity()); - drawItemHelper(item, painter, &option, widget, false); + drawItemHelper(item, painter, &option, widget, false); - if (savePainter || clipsToShape) - painter->restore(); - } + if (savePainter) + painter->restore(); } // Draw children in front - for (; i < children.size(); ++i) - drawSubtreeRecursive(children.at(i), painter, viewTransform, exposedRegion, widget, optimizationFlags); + if (!dontDrawChildren) { + for (; i < children.size(); ++i) { + drawSubtreeRecursive(children.at(i), painter, transform, viewTransform, + exposedRegion, widget, optimizationFlags); + } + } - if (childClip) { + // Restore child clip + if (childClip) painter->restore(); - } else { - painter->setWorldTransform(restoreTransform, /* combine = */ false); - } } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 0ac1765..bb99908 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -254,7 +254,8 @@ public: const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); - void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, + void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, + const QTransform &viewTransform, const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags); QStyle *style; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 40c84db..1994675 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3435,7 +3435,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const char *directEnv = getenv("QGRAPHICSVIEW_DIRECT"); bool overrideDirectPaint = directEnv && atoi(directEnv) != 0; if (overrideDirectPaint || (d->optimizationFlags & BypassDrawItems)) { - d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, exposedRegion, + d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, exposedRegion, viewport(), d->optimizationFlags); } else { // Find all exposed items -- cgit v0.12 From e7c7e4f57530d7b3571bf11dbe555c52f6dc3f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 26 May 2009 20:23:54 +0200 Subject: Cache QGraphicsItem::childrenBoundingRect. We'll need this later when making a smarter update mechanism. --- src/gui/graphicsview/qgraphicsitem.cpp | 15 +++++++++++++++ src/gui/graphicsview/qgraphicsitem_p.h | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b9e462b..e09d3f0 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -925,6 +925,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de */ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect) { + if (!dirtyChildrenBoundingRect) { + *rect |= x->mapRect(childrenBoundingRect); + return; + } + for (int i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); QGraphicsItemPrivate *childd = child->d_ptr; @@ -948,6 +953,9 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec childd->childrenBoundingRectHelper(x, rect); } } + + childrenBoundingRect = *rect; + dirtyChildrenBoundingRect = 0; } void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, @@ -3567,6 +3575,9 @@ void QGraphicsItem::setZValue(qreal z) */ QRectF QGraphicsItem::childrenBoundingRect() const { + if (!d_ptr->dirtyChildrenBoundingRect) + return d_ptr->childrenBoundingRect; + QRectF childRect; QTransform x; d_ptr->childrenBoundingRectHelper(&x, &childRect); @@ -6400,6 +6411,10 @@ void QGraphicsItem::prepareGeometryChange() scenePrivate->removeFromIndex(this); } + QGraphicsItem *parent = this; + while (parent = parent->d_ptr->parent) + parent->d_ptr->dirtyChildrenBoundingRect = 1; + if (d_ptr->inSetPosHelper) return; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index bd81fe5..200d177 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -160,6 +160,7 @@ public: hasDecomposedTransform(0), dirtyTransform(0), dirtyTransformComponents(0), + dirtyChildrenBoundingRect(1), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -308,6 +309,7 @@ public: } QPainterPath cachedClipPath; + QRectF childrenBoundingRect; QPointF pos; qreal z; QGraphicsScene *scene; @@ -350,7 +352,8 @@ public: quint32 hasDecomposedTransform : 1; quint32 dirtyTransform : 1; quint32 dirtyTransformComponents : 1; - quint32 padding : 18; // feel free to use + quint32 dirtyChildrenBoundingRect : 1; + quint32 padding : 17; // feel free to use // Optional stacking order int globalStackingOrder; -- cgit v0.12 From 63a3c0ad549b57d0896f267383cf671d6212a70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 27 May 2009 21:31:44 +0200 Subject: Massive re-factoring of Graphics View's update mechanism. This is work-in-progress, so don't expect everything to work perfectly. Most of the auto-test pass and examples and demos seem to run fine. Unfortunately I'm too tired to write about the actual update mehanism now, but it's faster than the old approach (if that helps:)). There's more to optimize, but I'll come back to that later. I need some sleep now :) To be continued. --- src/gui/graphicsview/qgraphicsitem.cpp | 156 ++++++----------- src/gui/graphicsview/qgraphicsitem_p.h | 22 ++- src/gui/graphicsview/qgraphicsscene.cpp | 212 ++++++++++++----------- src/gui/graphicsview/qgraphicsscene.h | 4 +- src/gui/graphicsview/qgraphicsscene_p.h | 30 +++- src/gui/graphicsview/qgraphicsview.cpp | 194 ++++----------------- src/gui/graphicsview/qgraphicsview.h | 1 - src/gui/graphicsview/qgraphicsview_p.h | 9 +- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 5 +- 9 files changed, 253 insertions(+), 380 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index e09d3f0..ec6b35b 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -863,8 +863,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de parent->d_ptr->addChild(q); parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant); - if (!implicitUpdate) - updateHelper(QRectF(), false, true); + if (!implicitUpdate && scene) { + scene->d_func()->markDirty(q_ptr, QRect(), + /*invalidateChildren=*/false, + /*maybeDirtyClipPath=*/true); + } // Inherit ancestor flags from the new parent. updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); @@ -895,7 +898,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de setEnabledHelper(true, /* explicit = */ false); // If the item is being deleted, the whole scene will be updated. - updateHelper(QRectF(), false, true); + if (scene) { + scene->d_func()->markDirty(q_ptr, QRect(), + /*invalidateChildren=*/false, + /*maybeDirtyClipPath=*/true); + } } } @@ -1358,7 +1365,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask); if (fullUpdate) - d_ptr->fullUpdateHelper(false, true); + d_ptr->paintedViewBoundingRectsNeedRepaint = 1; // Keep the old flags to compare the diff. GraphicsItemFlags oldFlags = this->flags(); @@ -1398,8 +1405,11 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->updateAncestorFlag(ItemIgnoresTransformations); } - // ### Why updateHelper? - d_ptr->updateHelper(QRectF(), false, true); + if (d_ptr->scene) { + d_ptr->scene->d_func()->markDirty(this, QRectF(), + /*invalidateChildren=*/true, + /*maybeDirtyClipPath*/true); + } // Notify change. itemChange(ItemFlagsHaveChanged, quint32(flags)); @@ -1665,7 +1675,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue(extra(ExtraCacheData)); if (c) c->purge(); - updateHelper(QRectF(), /* force = */ true); + if (scene) { + scene->d_func()->markDirty(q_ptr, QRectF(), + /*invalidateChildren=*/false, + /*maybeDirtyClipPath=*/false, + /*force=*/true); + } } // Certain properties are dropped as an item becomes invisible. @@ -1828,8 +1843,8 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo enabled = newEnabledVariant.toBool(); // Schedule redraw. - if (update) - updateHelper(); + if (update && scene) + scene->d_func()->markDirty(q_ptr); foreach (QGraphicsItem *child, children) { if (!newEnabled || !child->d_ptr->explicitlyDisabled) @@ -1930,9 +1945,8 @@ void QGraphicsItem::setSelected(bool selected) return; d_ptr->selected = newSelected; - d_ptr->updateHelper(); - if (d_ptr->scene) { + d_ptr->scene->d_func()->markDirty(this); QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func(); if (selected) { sceneD->selectedItems << this; @@ -2051,7 +2065,12 @@ void QGraphicsItem::setOpacity(qreal opacity) itemChange(ItemOpacityHasChanged, newOpacity); // Update. - d_ptr->fullUpdateHelper(/*childrenOnly=*/false, /*maybeDirtyClipPath=*/false, /*ignoreOpacity=*/true); + if (d_ptr->scene) + d_ptr->scene->d_func()->markDirty(this, QRectF(), + /*invalidateChildren=*/true, + /*maybeDirtyClipPath=*/false, + /*force=*/false, + /*ignoreOpacity=*/true); } /*! @@ -2501,10 +2520,8 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) // Update and repositition. inSetPosHelper = 1; updateCachedClipPathFromSetPosHelper(newPos); - if (scene) { - fullUpdateHelper(true); + if (scene) q->prepareGeometryChange(); - } this->pos = newPos; invalidateSceneTransformCache(); @@ -3305,7 +3322,6 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) return; // Update and set the new transformation. - d_ptr->fullUpdateHelper(true, true); prepareGeometryChange(); d_ptr->hasTransform = !newTransform.isIdentity(); d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); @@ -3358,7 +3374,6 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) return; // Update and set the new transformation. - d_ptr->fullUpdateHelper(true, true); prepareGeometryChange(); d_ptr->hasTransform = !newTransform.isIdentity(); d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); @@ -3545,9 +3560,9 @@ void QGraphicsItem::setZValue(qreal z) if (newZ == d_ptr->z) return; d_ptr->z = newZ; - d_ptr->fullUpdateHelper(); if (d_ptr->scene) { + d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); // Invalidate any sort caching; arrival of a new item means we need to // resort. d_ptr->scene->d_func()->invalidateSortCache(); @@ -4208,84 +4223,13 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. return (!visible && !ignoreVisibleBit) - || (dirty && !ignoreDirtyBit) + || (!ignoreDirtyBit && (dirty || hasDirtyAncestor())) || !scene || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect) || (!ignoreClipping && (childrenClippedToShape() && isClippedAway())) || (!ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); } -/*! - \internal - - Asks the scene to mark this item's scene rect as dirty, requesting a - redraw. This does not invalidate any cache. - - The \a force argument is for the update call in setVisible(), which is the - only case where the item's background should be marked as dirty even when - the item isn't visible. -*/ -void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool maybeDirtyClipPath) -{ - // No scene, or if the scene is updating everything, means we have nothing - // to do. The only exception is if the scene tracks the growing scene rect. - if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force)) - return; - - if (rect.isNull()) - dirty = 1; - scene->itemUpdated(q_ptr, rect); -} - -/*! - \internal - - Propagates updates to \a item and all its children. -*/ -void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath, bool ignoreOpacity) -{ - if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/false, - /*ignoreDirtyBit=*/true, ignoreOpacity)) { - return; - } - - if (!childrenOnly && !dirty) { - // Effectively the same as updateHelper(QRectF(), false, maybeDirtyClipPath). - dirty = 1; - scene->itemUpdated(q_ptr, QRectF()); - } - - if (dirtyChildren || childrenClippedToShape()) { - // Unnecessary to update children as well. - return; - } - - if (ancestorFlags & AncestorClipsChildren) { - Q_Q(QGraphicsItem); - // Check if we can avoid updating all children. - QGraphicsItem *p = parent; - QRectF br = q->boundingRect(); - while (p) { - if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) { - bool ok; - QTransform x = q->itemTransform(p, &ok); - if (!ok) - break; - if (x.mapRect(br).contains(p->boundingRect())) - return; - } - p = p->d_ptr->parent; - if (!p || !(p->d_ptr->ancestorFlags & AncestorClipsChildren)) - break; - // ### check one level only - break; - } - } - foreach (QGraphicsItem *child, children) - child->d_ptr->fullUpdateHelper(false, maybeDirtyClipPath); - dirtyChildren = 1; -} - static inline bool allChildrenCombineOpacityHelper(QGraphicsItem *parent) { Q_ASSERT(parent); @@ -4590,14 +4534,10 @@ void QGraphicsItem::update(const QRectF &rect) // Only invalidate cache; item is already dirty. if (d_ptr->dirty) return; - } else if (d_ptr->discardUpdateRequest()) { - return; } - // Effectively the same as updateHelper(rect); - if (rect.isNull()) - d_ptr->dirty = 1; - d_ptr->scene->itemUpdated(this, rect); + if (d_ptr->scene) + d_ptr->scene->d_func()->markDirty(this); } /*! @@ -4695,7 +4635,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) exposed -= r.translated(dx, dy); foreach (QRect rect, exposed.rects()) update(rect); - d_ptr->updateHelper(); + d->scene->d_func()->markDirty(this); } else { update(rect); } @@ -5911,7 +5851,8 @@ void QGraphicsItem::focusOutEvent(QFocusEvent *event) void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event); - d_ptr->updateHelper(); + if (d_ptr->scene) + d_ptr->scene->d_func()->markDirty(this); } /*! @@ -5939,7 +5880,8 @@ void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event); - d_ptr->updateHelper(); + if (d_ptr->scene) + d_ptr->scene->d_func()->markDirty(this); } /*! @@ -6367,9 +6309,10 @@ void QGraphicsItem::addToIndex() // ### add to child index only if applicable return; } - if (d_ptr->scene) + if (d_ptr->scene) { d_ptr->scene->d_func()->addToIndex(this); - d_ptr->updateHelper(); + d_ptr->scene->d_func()->markDirty(this); + } } /*! @@ -6385,9 +6328,10 @@ void QGraphicsItem::removeFromIndex() // ### remove from child index only if applicable return; } - d_ptr->updateHelper(); - if (d_ptr->scene) + if (d_ptr->scene) { + d_ptr->scene->d_func()->markDirty(this); d_ptr->scene->d_func()->removeFromIndex(this); + } } /*! @@ -6406,7 +6350,10 @@ void QGraphicsItem::removeFromIndex() void QGraphicsItem::prepareGeometryChange() { if (d_ptr->scene) { - d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); + d_ptr->paintedViewBoundingRectsNeedRepaint = 1; + d_ptr->scene->d_func()->markDirty(this, QRectF(), + /*invalidateChildren=*/true, + /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); scenePrivate->removeFromIndex(this); } @@ -8075,7 +8022,6 @@ void QGraphicsPixmapItem::setTransformationMode(Qt::TransformationMode mode) { Q_D(QGraphicsPixmapItem); if (mode != d->transformationMode) { - d_ptr->updateHelper(); d->transformationMode = mode; update(); } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 200d177..1d4b37a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -161,6 +161,8 @@ public: dirtyTransform(0), dirtyTransformComponents(0), dirtyChildrenBoundingRect(1), + inDirtyList(0), + paintedViewBoundingRectsNeedRepaint(0), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -186,8 +188,6 @@ public: void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; - void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false); - void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false, bool ignoreOpacity = false); void updateEffectiveOpacity(); void resolveEffectiveOpacity(qreal effectiveParentOpacity); void resolveDepth(int parentDepth); @@ -308,8 +308,22 @@ public: || (childrenCombineOpacity() && isFullyTransparent()); } + inline bool hasDirtyAncestor() const + { + QGraphicsItem *p = parent; + while (p) { + if (p->d_ptr->dirtyChildren || (p->d_ptr->dirty && p->d_ptr->childrenClippedToShape())) + return true; + p = p->d_ptr->parent; + } + return false; + } + + QPainterPath cachedClipPath; QRectF childrenBoundingRect; + QRectF needsRepaint; + QMap paintedViewBoundingRects; QPointF pos; qreal z; QGraphicsScene *scene; @@ -353,7 +367,9 @@ public: quint32 dirtyTransform : 1; quint32 dirtyTransformComponents : 1; quint32 dirtyChildrenBoundingRect : 1; - quint32 padding : 17; // feel free to use + quint32 inDirtyList : 1; + quint32 paintedViewBoundingRectsNeedRepaint : 1; + quint32 padding : 15; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7eb49e9..d004ed2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -334,7 +334,6 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() updateAll(false), calledEmitUpdated(false), selectionChanging(0), - dirtyItemResetPending(false), regenerateIndex(true), purgePending(false), indexTimerId(0), @@ -678,31 +677,81 @@ void QGraphicsScenePrivate::_q_polishItems() unpolishedItems.clear(); } -/*! - \internal -*/ -void QGraphicsScenePrivate::_q_resetDirtyItems() +void QGraphicsScenePrivate::_q_processDirtyItems() { + Q_Q(QGraphicsScene); + if (dirtyItems.isEmpty()) + return; + + if (updateAll) { + for (int i = 0; i < dirtyItems.size(); ++i) + resetDirtyItem(dirtyItems.at(i)); + dirtyItems.clear(); + return; + } + + const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); for (int i = 0; i < dirtyItems.size(); ++i) { QGraphicsItem *item = dirtyItems.at(i); - item->d_ptr->dirty = 0; - item->d_ptr->dirtyChildren = 0; + if (useCompatUpdate && !item->d_ptr->itemIsUntransformable() + && qFuzzyIsNull(item->boundingRegionGranularity())) { + // This block of code is kept for compatibility. Since 4.5, by default + // QGraphicsView does not connect the signal and we use the below + // method of delivering updates. + q->update(item->sceneBoundingRect()); + resetDirtyItem(item); + continue; + } + + QRectF dirtyRect; + bool uninitializedDirtyRect = true; + + for (int j = 0; j < views.size(); ++j) { + QGraphicsView *view = views.at(j); + QGraphicsViewPrivate *viewPrivate = view->d_func(); + if (viewPrivate->fullUpdatePending) + continue; + switch (viewPrivate->viewportUpdateMode) { + case QGraphicsView::NoViewportUpdate: + continue; + case QGraphicsView::FullViewportUpdate: + view->viewport()->update(); + viewPrivate->fullUpdatePending = 1; + continue; + default: + break; + } + + if (uninitializedDirtyRect) { + dirtyRect = adjustedItemBoundingRect(item); + if (!item->d_ptr->dirty) { + _q_adjustRect(&item->d_ptr->needsRepaint); + dirtyRect &= item->d_ptr->needsRepaint; + } + + if (item->d_ptr->dirtyChildren && !item->d_ptr->children.isEmpty() + && !item->d_ptr->childrenClippedToShape()) { + QRectF childrenBounds = item->childrenBoundingRect(); + _q_adjustRect(&childrenBounds); + dirtyRect |= childrenBounds; + } + uninitializedDirtyRect = false; + } + + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) + viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + + if (!item->d_ptr->hasBoundingRegionGranularity) + viewPrivate->updateRect(viewPrivate->mapToViewRect(item, dirtyRect)); + else + viewPrivate->updateRegion(viewPrivate->mapToViewRegion(item, dirtyRect)); + } + resetDirtyItem(item); } - dirtyItems.clear(); - dirtyItemResetPending = false; -} -/*! - \internal -*/ -void QGraphicsScenePrivate::resetDirtyItemsLater() -{ - Q_Q(QGraphicsScene); - if (dirtyItemResetPending) - return; - // dirtyItems.reserve(indexedItems.size() + unindexedItems.size()); - dirtyItemResetPending = true; - QMetaObject::invokeMethod(q, "_q_resetDirtyItems", Qt::QueuedConnection); + dirtyItems.clear(); + for (int i = 0; i < views.size(); ++i) + views.at(i)->d_func()->processPendingUpdates(); } /*! @@ -761,10 +810,9 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) // Update selected & hovered item bookkeeping selectedItems.remove(item); hoverItems.removeAll(item); - pendingUpdateItems.removeAll(item); cachedItemsUnderMouse.removeAll(item); unpolishedItems.removeAll(item); - dirtyItems.removeAll(item); + removeFromDirtyItems(item); //We remove all references of item from the sceneEventFilter arrays QMultiMap::iterator iterator = sceneEventFilters.begin(); @@ -3319,7 +3367,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->pendingUpdateItems.removeAll(item); d->cachedItemsUnderMouse.removeAll(item); d->unpolishedItems.removeAll(item); - d->dirtyItems.removeAll(item); + d->removeFromDirtyItems(item); //We remove all references of item from the sceneEventFilter arrays QMultiMap::iterator iterator = d->sceneEventFilters.begin(); @@ -3330,11 +3378,6 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) ++iterator; } - - //Ensure dirty flag have the correct default value so the next time it will be added it will receive updates - item->d_func()->dirty = 0; - item->d_func()->dirtyChildren = 0; - // Remove all children recursively foreach (QGraphicsItem *child, item->children()) removeItem(child); @@ -5050,7 +5093,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } QRectF brect = item->boundingRect(); _q_adjustRect(&brect); - viewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1) & exposedRegion.boundingRect(); + const QRect paintedViewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); + item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); + viewBoundingRect = paintedViewBoundingRect & exposedRegion.boundingRect(); } else { transform = parentTransform; } @@ -5117,6 +5162,44 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->restore(); } +void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, + bool maybeDirtyClipPath, bool force, bool ignoreOpacity) +{ + Q_ASSERT(item); + if (updateAll) + return; + + if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, + /*ignoreVisibleBit=*/force, + /*ignoreDirtyBit=*/false, ignoreOpacity)) { + return; + } + + const bool fullItemUpdate = rect.isNull(); + if (!fullItemUpdate && rect.isEmpty()) + return; + + if (dirtyItems.isEmpty()) + QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection); + + if (item->d_ptr->inDirtyList) { + if (fullItemUpdate) + item->d_ptr->dirty = 1; + else if (!item->d_ptr->dirty) + item->d_ptr->needsRepaint |= rect; + } else { + dirtyItems.append(item); + item->d_ptr->inDirtyList = 1; + if (fullItemUpdate) + item->d_ptr->dirty = 1; + else if (!item->d_ptr->dirty) + item->d_ptr->needsRepaint = rect; + } + + if (invalidateChildren) + item->d_ptr->dirtyChildren = 1; +} + /*! Paints the given \a items using the provided \a painter, after the background has been drawn, and before the foreground has been @@ -5238,6 +5321,8 @@ void QGraphicsScene::drawItems(QPainter *painter, // Draw the item d->drawItemHelper(item, painter, &options[i], widget, d->painterStateProtection); + const QRect paintedViewBoundingRect = painter->worldTransform().mapRect(options[i].rect).adjusted(-1, -1, 1, 1); + item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); if (saveState) painter->restore(); @@ -5364,73 +5449,6 @@ bool QGraphicsScene::focusNextPrevChild(bool next) */ /*! - \internal - - This private function is called by QGraphicsItem, which is a friend of - QGraphicsScene. It is used by QGraphicsScene to record the rectangles that - need updating. It also launches a single-shot timer to ensure that - updated() will be emitted later. - - The \a item parameter is the item that changed, and \a rect is the - area of the item that changed given in item coordinates. -*/ -void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect) -{ - Q_D(QGraphicsScene); - // Deliver the actual update. - if (!d->updateAll) { - if (d->views.isEmpty() || ((d->connectedSignals & d->changedSignalMask) && !item->d_ptr->itemIsUntransformable() - && qFuzzyIsNull(item->boundingRegionGranularity()))) { - // This block of code is kept for compatibility. Since 4.5, by default - // QGraphicsView does not connect the signal and we use the below - // method of delivering updates. - update(item->sceneBoundingRect()); - } else { - // ### Remove _q_adjustedRects(). - QRectF boundingRect(adjustedItemBoundingRect(item)); - if (!rect.isNull()) { - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - boundingRect &= adjustedRect; - } - - // Update each view directly. - for (int i = 0; i < d->views.size(); ++i) - d->views.at(i)->d_func()->itemUpdated(item, boundingRect); - } - } - if (item->d_ptr->dirty) { - d->dirtyItems << item; - d->resetDirtyItemsLater(); - } - - if (!item->isVisible()) - return; // Hiding an item won't effect the largestUntransformableItem/sceneRect. - - // Update d->largestUntransformableItem by mapping this item's bounding - // rect back to the topmost untransformable item's untransformed - // coordinate system (which sort of equals the 1:1 coordinate system of an - // untransformed view). - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *parent = item; - while (parent && (parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations)) - parent = parent->parentItem(); - d->largestUntransformableItem |= item->mapToItem(parent, item->boundingRect()).boundingRect(); - } - - // Only track the automatically growing scene rect if the scene has no - // defined scene rect. - if (!d->hasSceneRect) { - QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect; - QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect()); - _q_adjustRect(&adjustedItemSceneBoundingRect); - d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect; - if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit sceneRectChanged(d->growingItemsBoundingRect); - } -} - -/*! \since 4.4 Returns the scene's style, or the same as QApplication::style() if the diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 9802f87..4c0f2ec 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -271,8 +271,6 @@ Q_SIGNALS: void selectionChanged(); private: - void itemUpdated(QGraphicsItem *item, const QRectF &rect); - Q_DECLARE_PRIVATE(QGraphicsScene) Q_DISABLE_COPY(QGraphicsScene) Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) @@ -281,7 +279,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) - Q_PRIVATE_SLOT(d_func(), void _q_resetDirtyItems()) + Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems()) friend class QGraphicsItem; friend class QGraphicsItemPrivate; friend class QGraphicsView; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index bb99908..f2226bf 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -111,7 +111,7 @@ public: QSet selectedItems; QList unindexedItems; QList indexedItems; - QList dirtyItems; + QVector dirtyItems; QList pendingUpdateItems; QList unpolishedItems; QList topLevelItems; @@ -121,9 +121,7 @@ public: void _q_updateLater(); void _q_polishItems(); - void _q_resetDirtyItems(); - void resetDirtyItemsLater(); - bool dirtyItemResetPending; + void _q_processDirtyItems(); QList freeItemIndexes; bool regenerateIndex; @@ -257,6 +255,30 @@ public: void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, const QTransform &viewTransform, const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags); + void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, + bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); + + inline void resetDirtyItem(QGraphicsItem *item) + { + Q_ASSERT(item); + item->d_ptr->dirty = 0; + item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; + item->d_ptr->dirtyChildren = 0; + item->d_ptr->inDirtyList = 0; + item->d_ptr->needsRepaint = QRectF(); + } + + inline void removeFromDirtyItems(QGraphicsItem *item) + { + int i = 0; + while (i < dirtyItems.size()) { + if (dirtyItems.at(i) == item) + dirtyItems.remove(i); + else + ++i; + } + resetDirtyItem(item); + } QStyle *style; QFont font; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 1994675..acf26e1 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -329,8 +329,6 @@ QGraphicsViewPrivate::QGraphicsViewPrivate() #endif lastDragDropEvent(0), fullUpdatePending(true), - dirtyRectCount(0), - updatingLater(false), updateSceneSlotReimplementedChecked(false) { styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS); @@ -804,125 +802,28 @@ static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) return boundingRect; } -/*! - \internal -*/ -void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) +void QGraphicsViewPrivate::processPendingUpdates() { - if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate) - return; - if (item->d_ptr->dirty) - updateLater(); - - QRectF updateRect = rect; - if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) { - updateRect &= adjustedItemBoundingRect(item); - if (updateRect.isEmpty()) - return; - } - - QGraphicsItem *clipItem = item; - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // Minimize unnecessary redraw. - QGraphicsItem *parent = item; - while ((parent = parent->d_ptr->parent)) { - if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) { - // Map update rect to the current parent and itersect with its bounding rect. - updateRect = clipItem->itemTransform(parent).mapRect(updateRect) - & adjustedItemBoundingRect(parent); - if (updateRect.isEmpty()) - return; - clipItem = parent; - } - - if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) - break; - } - } - - // Map update rect from clipItem coordinates to view coordinates. - Q_ASSERT(clipItem); - if (!item->d_ptr->hasBoundingRegionGranularity) - this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect()); - else - updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect()); -} - -void QGraphicsViewPrivate::updateLater() -{ - Q_Q(QGraphicsView); - if (updatingLater) - return; - updatingLater = true; - QMetaObject::invokeMethod(q, "_q_updateLaterSlot", Qt::QueuedConnection); -} - -void QGraphicsViewPrivate::_q_updateLaterSlot() -{ - Q_Q(QGraphicsView); if (!scene) return; - QRect vr = viewport->rect(); - QTransform viewTransform = q->viewportTransform(); - const QList &dirtyItems = scene->d_func()->dirtyItems; - for (int i = 0; i < dirtyItems.size(); ++i) { - const QGraphicsItem *item = dirtyItems.at(i); - if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false, - /*ignoreVisibleBit=*/false, - /*ignoreDirtyBit=*/true)) { - continue; - } - QTransform x = item->sceneTransform() * viewTransform; - updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr); + if (fullUpdatePending) { // We have already called viewport->update() + dirtyBoundingRect = QRect(); + dirtyRegion = QRegion(); + return; } - dirtyRectCount += dirtyRects.size(); - - bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate; - if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) { - if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate - || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate - && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) { - if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) { - viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); - } else { - viewport->update(dirtyBoundingRect); - } - } else { - // ### Improve this block, which is very slow for complex regions. We - // need to strike the balance between having an accurate update - // region, and running fast. The below approach is the simplest way to - // create a region from a bunch of rects, but we might want to use - // other approaches; e.g., a grid of a fixed size representing - // quadrants of the viewport, which we mark as dirty depending on the - // rectangles in the list. Perhaps this should go into a - // QRegion::fromRects(rects, how) function. - QRegion region; - if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) { - for (int i = 0; i < dirtyRegions.size(); ++i) { - QVector rects = dirtyRegions.at(i).rects(); - for (int j = 0; j < rects.size(); ++j) - region += rects.at(j).adjusted(-2, -2, 2, 2); - } - for (int i = 0; i < dirtyRects.size(); ++i) - region += dirtyRects.at(i).adjusted(-2, -2, 2, 2); - } else { - for (int i = 0; i < dirtyRegions.size(); ++i) - region += dirtyRegions.at(i); - for (int i = 0; i < dirtyRects.size(); ++i) - region += dirtyRects.at(i); - } - - viewport->update(region); - } + if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { + if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) + viewport->update(dirtyBoundingRect); + else + viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); + } else { + viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. } - dirtyRegions.clear(); - dirtyRects.clear(); - dirtyRectCount = 0; dirtyBoundingRect = QRect(); - updatingLater = false; + dirtyRegion = QRegion(); } void QGraphicsViewPrivate::updateAll() @@ -930,14 +831,13 @@ void QGraphicsViewPrivate::updateAll() Q_Q(QGraphicsView); q->viewport()->update(); fullUpdatePending = true; - dirtyRectCount = 0; dirtyBoundingRect = QRect(); - updatingLater = false; + dirtyRegion = QRegion(); } void QGraphicsViewPrivate::updateRegion(const QRegion &r) { - if (r.isEmpty()) + if (r.isEmpty() || fullUpdatePending) return; Q_Q(QGraphicsView); @@ -950,45 +850,30 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r) break; case QGraphicsView::BoundingRectViewportUpdate: dirtyBoundingRect |= r.boundingRect(); - if (dirtyBoundingRect == q->viewport()->rect()) { + if (dirtyBoundingRect.contains(q->viewport()->rect())) { fullUpdatePending = true; q->viewport()->update(); - } else { - updateLater(); } break; - case QGraphicsView::SmartViewportUpdate: - dirtyBoundingRect |= r.boundingRect(); - if ((dirtyRectCount + r.numRects()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD) - dirtyRegions << r; - dirtyRectCount += r.numRects(); - updateLater(); - break; + case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE case QGraphicsView::MinimalViewportUpdate: - dirtyRegions << r; - dirtyRectCount += r.numRects(); - updateLater(); + if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) { + dirtyRegion += r; + } else { + const QVector &rects = r.rects(); + for (int i = 0; i < rects.size(); ++i) + dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2); + } break; case QGraphicsView::NoViewportUpdate: // Unreachable break; } - - // Compress the regions... - if (dirtyRectCount > QGRAPHICSVIEW_REGION_RECT_THRESHOLD && dirtyRegions.size() > 1) { - QRegion masterRegion; - for (int i=0; iviewport()->rect()) { + if (dirtyBoundingRect.contains(q->viewport()->rect())) { fullUpdatePending = true; q->viewport()->update(); - } else { - updateLater(); } break; - case QGraphicsView::SmartViewportUpdate: - dirtyBoundingRect |= r; - if ((dirtyRectCount + dirtyRects.size()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD) - dirtyRects << r; - updateLater(); - break; + case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE case QGraphicsView::MinimalViewportUpdate: - dirtyRects << r; - updateLater(); + if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) + dirtyRegion += r; + else + dirtyRegion += r.adjusted(-2, -2, 2, 2); break; case QGraphicsView::NoViewportUpdate: // Unreachable @@ -2613,9 +2493,10 @@ void QGraphicsView::updateScene(const QList &rects) // Extract and reset dirty scene rect info. QVector dirtyViewportRects; - for (int i = 0; i < d->dirtyRegions.size(); ++i) - dirtyViewportRects += d->dirtyRegions.at(i).rects(); - d->dirtyRegions.clear(); + const QVector &dirtyRects = d->dirtyRegion.rects(); + for (int i = 0; i < dirtyRects.size(); ++i) + dirtyViewportRects += dirtyRects.at(i); + d->dirtyRegion = QRegion(); bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate; bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) @@ -3544,10 +3425,7 @@ void QGraphicsView::scrollContentsBy(int dx, int dy) if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) { if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) { - for (int i = 0; i < d->dirtyRects.size(); ++i) - d->dirtyRects[i].translate(dx, dy); - for (int i = 0; i < d->dirtyRegions.size(); ++i) - d->dirtyRegions[i].translate(dx, dy); + d->dirtyRegion.translate(dx, dy); if (d->accelerateScrolling) { #ifndef QT_NO_RUBBERBAND // Update new and old rubberband regions diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h index 7692e16..deed1d0 100644 --- a/src/gui/graphicsview/qgraphicsview.h +++ b/src/gui/graphicsview/qgraphicsview.h @@ -274,7 +274,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_setViewportCursor(const QCursor &)) Q_PRIVATE_SLOT(d_func(), void _q_unsetViewportCursor()) #endif - Q_PRIVATE_SLOT(d_func(), void _q_updateLaterSlot()) friend class QGraphicsSceneWidget; friend class QGraphicsScene; friend class QGraphicsScenePrivate; diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index c18f85d..637687b 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -159,15 +159,10 @@ public: QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const; QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const; - void itemUpdated(QGraphicsItem *item, const QRectF &rect); bool fullUpdatePending; - QList dirtyRects; - QList dirtyRegions; - int dirtyRectCount; + QRegion dirtyRegion; QRect dirtyBoundingRect; - void updateLater(); - bool updatingLater; - void _q_updateLaterSlot(); + void processPendingUpdates(); void updateAll(); void updateRect(const QRect &rect); void updateRegion(const QRegion ®ion); diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 0c5ebf6..23d7a94 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -1317,8 +1317,9 @@ void tst_QGraphicsScene::removeItem() scene.removeItem(hoverItem); hoverItem->setAcceptsHoverEvents(false); scene.addItem(hoverItem); - qApp->processEvents(); // update - qApp->processEvents(); // draw + qApp->processEvents(); // <- delayed update is called + qApp->processEvents(); // <- scene schedules pending update + qApp->processEvents(); // <- pending update is sent to view QVERIFY(!hoverItem->isHovered); } -- cgit v0.12 From 8afef542ead463b6937ec907c0b35a7977ed4a83 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 10:13:12 +0200 Subject: simplify and cleanup handling of transformations in QGraphicsItem Removed some experimental code to handle scaling and rotating around different axis. It cuased setTransform and transform not to behave symmetrically and caused some performance regressions. Additionally moved the QTransform out of the (relatively slow) extra list and made it a pointer in QGraphicsItemPrivate. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 429 ++------------------------------- src/gui/graphicsview/qgraphicsitem.h | 37 +-- src/gui/graphicsview/qgraphicsitem_p.h | 12 +- src/gui/graphicsview/qgraphicswidget.h | 9 +- 4 files changed, 23 insertions(+), 464 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index ec6b35b..14658cf 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1102,6 +1102,9 @@ QGraphicsItem::~QGraphicsItem() if (d_ptr->scene) d_ptr->scene->d_func()->_q_removeItemLater(this); + if (d_ptr->transform) + delete d_ptr->transform; + delete d_ptr; qt_dataStore()->data.remove(this); @@ -2627,403 +2630,9 @@ QMatrix QGraphicsItem::matrix() const */ QTransform QGraphicsItem::transform() const { - if (!d_ptr->hasTransform) + if (!d_ptr->hasTransform || !d_ptr->transform) return QTransform(); - if (d_ptr->hasDecomposedTransform && d_ptr->dirtyTransform) { - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - QTransform x; - decomposed->generateTransform(&x); - QVariant v(x); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, v); - d_ptr->dirtyTransform = 0; - const_cast(this)->itemChange(ItemTransformHasChanged, v); - return x; - } - return qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)); -} - -/*! - \since 4.6 - - Returns the rotation around the X axis. - - The default is 0 - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setXRotation(), {Transformations} -*/ -qreal QGraphicsItem::xRotation() const -{ - return d_ptr->decomposedTransform()->xRotation; -} - -/*! - \since 4.6 - - Sets the rotation around the X axis to \a angle degrees. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa xRotation(), {Transformations} -*/ -void QGraphicsItem::setXRotation(qreal angle) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->xRotation = angle; - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; -} - -/*! - \since 4.6 - - Returns the rotation around the Y axis. - - The default is 0 - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setYRotation(), {Transformations} -*/ -qreal QGraphicsItem::yRotation() const -{ - return d_ptr->decomposedTransform()->yRotation; -} - -/*! - \since 4.6 - - Sets the rotation around the Y axis to \a angle degrees. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa yRotation(), {Transformations} -*/ -void QGraphicsItem::setYRotation(qreal angle) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->yRotation = angle; - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; -} - -/*! - \since 4.6 - - Returns the rotation around the Z axis. - - The default is 0 - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setZRotation(), {Transformations} -*/ -qreal QGraphicsItem::zRotation() const -{ - return d_ptr->decomposedTransform()->zRotation; -} - -/*! - \since 4.6 - - Sets the rotation around the Z axis to \a angle degrees. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa zRotation(), {Transformations} -*/ -void QGraphicsItem::setZRotation(qreal angle) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->zRotation = angle; - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; -} - -/*! - \since 4.6 - - This convenience function set the rotation angles around the 3 axes - to \a x, \a y and \a z. - - \sa setXRotation(), setYRotation(), setZRotation() -*/ -void QGraphicsItem::setRotation(qreal x, qreal y, qreal z) -{ - setXRotation(x); - setYRotation(y); - setZRotation(z); -} - -/*! - \since 4.6 - - Returns the scale factor on the X axis. - - The default is 1 - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setXScale(), {Transformations} -*/ -qreal QGraphicsItem::xScale() const -{ - return d_ptr->decomposedTransform()->xScale; -} - -/*! - \since 4.6 - - Sets the scale factor on the X axis to \a factor. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa xScale(), {Transformations} -*/ -void QGraphicsItem::setXScale(qreal factor) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->xScale = factor; - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; -} - -/*! - \since 4.6 - - Returns the scale factor on the Y axis. - - The default is 1 - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setYScale(), {Transformations} -*/ -qreal QGraphicsItem::yScale() const -{ - return d_ptr->decomposedTransform()->yScale; -} - -/*! - \since 4.6 - - Sets the scale factor on the Y axis to \a factor. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa yScale(), {Transformations} -*/ -void QGraphicsItem::setYScale(qreal factor) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->yScale = factor; - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; -} - -/*! - \since 4.6 - - This convenience function set the scaling factors on X and Y axis to \a sx and \a sy. - - \sa setXScale(), setYScale() -*/ -void QGraphicsItem::setScale(qreal sx, qreal sy) -{ - setXScale(sx); - setYScale(sy); -} - -/*! - \since 4.6 - - Returns the horizontal shear. - - The default is 0 - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setHorizontalShear(), {Transformations} -*/ -qreal QGraphicsItem::horizontalShear() const -{ - return d_ptr->decomposedTransform()->horizontalShear; -} - -/*! - \since 4.6 - - Sets the horizontal shear to \a shear. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa horizontalShear(), {Transformations} -*/ -void QGraphicsItem::setHorizontalShear(qreal shear) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->horizontalShear = shear; - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; -} - -/*! - \since 4.6 - - Returns the vertical shear. - - The default is 0 - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setHorizontalShear(), {Transformations} -*/ -qreal QGraphicsItem::verticalShear() const -{ - return d_ptr->decomposedTransform()->verticalShear; -} - -/*! - \since 4.6 - - Sets the vertical shear to \a shear. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa verticalShear(), {Transformations} -*/ -void QGraphicsItem::setVerticalShear(qreal shear) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->verticalShear = shear; - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; -} - -/*! - \since 4.6 - - This convenience function sets the horizontal shear to \a sh and the vertical shear to \a sv. - - \sa setHorizontalShear(), setVerticalShear() -*/ -void QGraphicsItem::setShear(qreal sh, qreal sv) -{ - setHorizontalShear(sh); - setVerticalShear(sv); -} - -/*! - \since 4.6 - - Returns the transformation origin for the transformation properties. - - The default is QPointF(0,0). - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, this function return the default value. - - \sa setTransformOrigin(), {Transformations} -*/ -QPointF QGraphicsItem::transformOrigin() const -{ - const QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - return QPointF(decomposed->xOrigin, decomposed->yOrigin); -} - -/*! - \fn inline void setTransformOrigin(qreal x, qreal y) - - \since 4.6 - - This is an overloaded member function, provided for convenience. - Sets the transformation origin for the transformation - properties to the point(\a x, \a y). - - \sa setTransformOrigin(), {Transformations} -*/ - -/*! - \since 4.6 - - Sets the transformation origin for the transformation properties to \a origin. - This does not apply to the transformation set by setTransform. - - \warning setting this property is conflicting with calling setTransform. - If a transform has been set, it will be overwritten. - - \sa transformOrigin(), {Transformations} -*/ -void QGraphicsItem::setTransformOrigin(const QPointF &origin) -{ - if (!d_ptr->dirtyTransform) { - d_ptr->fullUpdateHelper(true); - prepareGeometryChange(); - } - QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform(); - decomposed->xOrigin = origin.x(); - decomposed->yOrigin = origin.y(); - if (!d_ptr->dirtyTransform) - d_ptr->invalidateSceneTransformCache(); - d_ptr->dirtyTransform = 1; - d_ptr->hasTransform = 1; + return *d_ptr->transform; } /*! @@ -3306,11 +2915,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) { QTransform oldTransform = this->transform(); - QTransform newTransform; - if (!combine) - newTransform = QTransform(matrix); - else - newTransform = QTransform(matrix) * oldTransform; + QTransform newTransform(combine ? QTransform(matrix) * oldTransform : QTransform(matrix)); if (oldTransform == newTransform) return; @@ -3324,9 +2929,10 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); d_ptr->hasTransform = !newTransform.isIdentity(); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); - d_ptr->dirtyTransformComponents = 1; - d_ptr->dirtyTransform = 0; + if(!d_ptr->transform) + d_ptr->transform = new QTransform(newTransform); + else + *d_ptr->transform = newTransform; d_ptr->invalidateSceneTransformCache(); // Send post-notification. @@ -3358,11 +2964,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) { QTransform oldTransform = this->transform(); - QTransform newTransform; - if (!combine) - newTransform = matrix; - else - newTransform = matrix * oldTransform; + QTransform newTransform(combine ? matrix * oldTransform : matrix); if (oldTransform == newTransform) return; @@ -3376,9 +2978,10 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); d_ptr->hasTransform = !newTransform.isIdentity(); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); - d_ptr->dirtyTransformComponents = 1; - d_ptr->dirtyTransform = 0; + if(!d_ptr->transform) + d_ptr->transform = new QTransform(newTransform); + else + *d_ptr->transform = newTransform; d_ptr->invalidateSceneTransformCache(); // Send post-notification. @@ -6359,7 +5962,7 @@ void QGraphicsItem::prepareGeometryChange() } QGraphicsItem *parent = this; - while (parent = parent->d_ptr->parent) + while ((parent = parent->d_ptr->parent)) parent->d_ptr->dirtyChildrenBoundingRect = 1; if (d_ptr->inSetPosHelper) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index f6ee197..def773e 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -242,39 +242,10 @@ public: void setTransform(const QTransform &matrix, bool combine = false); void resetTransform(); - void rotate(qreal angle); // ### obsolete - void scale(qreal sx, qreal sy); // ### obsolete - void shear(qreal sh, qreal sv); // ### obsolete - void translate(qreal dx, qreal dy); // ### obsolete - - qreal xRotation() const; - void setXRotation(qreal angle); - - qreal yRotation() const; - void setYRotation(qreal angle); - - qreal zRotation() const; - void setZRotation(qreal angle); - void setRotation(qreal x, qreal y, qreal z); - - qreal xScale() const; - void setXScale(qreal factor); - - qreal yScale() const; - void setYScale(qreal factor); - void setScale(qreal sx, qreal sy); - - qreal horizontalShear() const; - void setHorizontalShear(qreal shear); - - qreal verticalShear() const; - void setVerticalShear(qreal shear); - void setShear(qreal sh, qreal sv); - - QPointF transformOrigin() const; - void setTransformOrigin(const QPointF &origin); - inline void setTransformOrigin(qreal x, qreal y) - { setTransformOrigin(QPointF(x,y)); } + void rotate(qreal angle); + void scale(qreal sx, qreal sy); + void shear(qreal sh, qreal sv); + void translate(qreal dx, qreal dy); virtual void advance(int phase); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 1d4b37a..5c7e67c 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -95,17 +95,7 @@ class Q_AUTOTEST_EXPORT QGraphicsItemPrivate { Q_DECLARE_PUBLIC(QGraphicsItem) public: - struct TransformData - { - TransformData() : rotationX(0),rotationY(0),rotationZ(0),scaleX(1),scaleY(1), dirty(true) {} - QTransform baseTransform; - QTransform transform; - QPointF transformCenter; - qreal rotationX,rotationY,rotationZ,scaleX,scaleY; - bool dirty; - }; enum Extra { - ExtraTransform, ExtraToolTip, ExtraCursor, ExtraCacheData, @@ -127,6 +117,7 @@ public: : z(0), scene(0), parent(0), + transform(0), siblingIndex(-1), index(-1), depth(0), @@ -329,6 +320,7 @@ public: QGraphicsScene *scene; QGraphicsItem *parent; QList children; + QTransform *transform; int siblingIndex; int index; int depth; diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index a5c9068..34f1c5f 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -81,14 +81,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, publi Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) Q_PROPERTY(QPointF pos READ pos WRITE setPos) Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry) - Q_PROPERTY(QPointF transformOrigin READ transformOrigin WRITE setTransformOrigin) - Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation) - Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation) - Q_PROPERTY(qreal zRotation READ zRotation WRITE setZRotation) - Q_PROPERTY(qreal xScale READ xScale WRITE setXScale) - Q_PROPERTY(qreal yScale READ yScale WRITE setYScale) - Q_PROPERTY(qreal horizontalShear READ horizontalShear WRITE setHorizontalShear) - Q_PROPERTY(qreal verticalShear READ verticalShear WRITE setVerticalShear) + public: QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); ~QGraphicsWidget(); -- cgit v0.12 From 5ea28946b53b001a6fcbc1c382f80f798ac6ab4b Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 28 May 2009 11:31:24 +0200 Subject: Remove scene transform cache from QGraphicsItem. Now that we have a recursive painting algorithm these types of optimizations are no longer necessary. In fact they only cause more problems and clutter up the code unnecessarily. Removing this also removes extra overhead from moving and transforming items. Reviewed-by: Lars --- src/gui/graphicsview/qgraphicsitem.cpp | 64 +++++---------------------------- src/gui/graphicsview/qgraphicsitem_p.h | 3 -- src/gui/graphicsview/qgraphicsscene.cpp | 17 ++------- src/gui/graphicsview/qgraphicsscene_p.h | 4 --- 4 files changed, 10 insertions(+), 78 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 14658cf..c1848e0 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -918,9 +918,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de // Resolve depth. resolveDepth(parent ? parent->d_ptr->depth : -1); - // Invalidate transform cache. - invalidateSceneTransformCache(); - // Deliver post-change notification q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); } @@ -2526,7 +2523,6 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) if (scene) q->prepareGeometryChange(); this->pos = newPos; - invalidateSceneTransformCache(); // Send post-notification. q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); @@ -2667,44 +2663,15 @@ QMatrix QGraphicsItem::sceneMatrix() const */ QTransform QGraphicsItem::sceneTransform() const { - // Check if there's any entry in the transform cache. - QGraphicsScenePrivate *sd = d_ptr->scene ? d_ptr->scene->d_func() : 0; - int index = d_ptr->sceneTransformIndex; - if (sd && index != -1 && sd->validTransforms.testBit(index)) - return sd->sceneTransformCache[index]; - - // Calculate local transform. QTransform m; - if (d_ptr->hasTransform) { - m = transform(); - if (!d_ptr->pos.isNull()) - m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()); - } else if (!d_ptr->pos.isNull()) { - m = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()); - } - - // Combine with parent and add to cache. - if (d_ptr->parent) { - m *= d_ptr->parent->sceneTransform(); - // Don't cache toplevels - if (sd) { - if (index == -1) { - if (!sd->freeSceneTransformSlots.isEmpty()) { - index = sd->freeSceneTransformSlots.last(); - sd->freeSceneTransformSlots.pop_back(); - } else { - index = sd->sceneTransformCache.size(); - } - d_ptr->sceneTransformIndex = index; - if (index >= sd->validTransforms.size()) { - sd->validTransforms.resize(index + 1); - sd->sceneTransformCache.resize(index + 1); - } - } - sd->validTransforms.setBit(index, 1); - sd->sceneTransformCache[index] = m; - } - } + const QGraphicsItem *p = this; + do { + if (p->d_ptr->hasTransform) + m *= p->transform(); + const QPointF &pos = p->d_ptr->pos; + if (!pos.isNull()) + m *= QTransform::fromTranslate(pos.x(), pos.y()); + } while ((p = p->d_ptr->parent)); return m; } @@ -2933,7 +2900,6 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->transform = new QTransform(newTransform); else *d_ptr->transform = newTransform; - d_ptr->invalidateSceneTransformCache(); // Send post-notification. // NB! We have to change the value from QMatrix to QTransform. @@ -2982,7 +2948,6 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) d_ptr->transform = new QTransform(newTransform); else *d_ptr->transform = newTransform; - d_ptr->invalidateSceneTransformCache(); // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -3912,19 +3877,6 @@ void QGraphicsItemPrivate::resolveDepth(int parentDepth) /*! \internal */ -void QGraphicsItemPrivate::invalidateSceneTransformCache() -{ - if (!scene || (parent && sceneTransformIndex == -1)) - return; - if (sceneTransformIndex != -1) - scene->d_func()->validTransforms.setBit(sceneTransformIndex, 0); - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->invalidateSceneTransformCache(); -} - -/*! - \internal -*/ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) { child->d_ptr->siblingIndex = children.size(); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 5c7e67c..5a6401a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -155,7 +155,6 @@ public: inDirtyList(0), paintedViewBoundingRectsNeedRepaint(0), globalStackingOrder(-1), - sceneTransformIndex(-1), q_ptr(0) { } @@ -182,7 +181,6 @@ public: void updateEffectiveOpacity(); void resolveEffectiveOpacity(qreal effectiveParentOpacity); void resolveDepth(int parentDepth); - void invalidateSceneTransformCache(); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); void setParentItemHelper(QGraphicsItem *parent, bool deleting); @@ -365,7 +363,6 @@ public: // Optional stacking order int globalStackingOrder; - int sceneTransformIndex; struct DecomposedTransform; DecomposedTransform *decomposedTransform() const diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index d004ed2..86e7cdb 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -823,13 +823,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) ++iterator; } - // Remove from scene transform cache - int transformIndex = item->d_func()->sceneTransformIndex; - if (transformIndex != -1) { - validTransforms.setBit(transformIndex, 0); - freeSceneTransformSlots.append(transformIndex); - } - // Reset the mouse grabber if (mouseGrabberItems.contains(item)) ungrabMouse(item, /* item is dying */ true); @@ -3340,14 +3333,6 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->unindexedItems.removeAll(item); } - // Remove from scene transform cache - int transformIndex = item->d_func()->sceneTransformIndex; - if (transformIndex != -1) { - d->validTransforms.setBit(transformIndex, 0); - d->freeSceneTransformSlots.append(transformIndex); - item->d_func()->sceneTransformIndex = -1; - } - if (item == d->focusItem) d->focusItem = 0; if (item == d->lastFocusItem) @@ -3817,6 +3802,8 @@ bool QGraphicsScene::event(QEvent *event) // items from inside event handlers, this list can quickly end up // having stale pointers in it. We need to clear it before dispatching // events that use it. + // ### this should only be cleared if we received a new mouse move event, + // which relies on us fixing the replay mechanism in QGraphicsView. d->cachedItemsUnderMouse.clear(); default: break; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f2226bf..bf7ac0a 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -289,10 +289,6 @@ public: void setPalette_helper(const QPalette &palette); void resolvePalette(); void updatePalette(const QPalette &palette); - - mutable QVector sceneTransformCache; - mutable QBitArray validTransforms; - mutable QVector freeSceneTransformSlots; }; QT_END_NAMESPACE -- cgit v0.12 From f233dafed58b6429d693ae0248f596a0377cd547 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 12:25:21 +0200 Subject: get rid of the hasTransform flag in QGraphicsItem Since the transform is now a pointer in QGraphicsItemPrivate, we can use this pointer directly and there's no need for a separate bitflag anymore. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 81 ++++++++++++++++----------------- src/gui/graphicsview/qgraphicsitem_p.h | 3 +- src/gui/graphicsview/qgraphicsscene.cpp | 16 +++---- src/gui/graphicsview/qgraphicsview.cpp | 2 +- 4 files changed, 48 insertions(+), 54 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index c1848e0..26da858 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -937,12 +937,11 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec for (int i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); QGraphicsItemPrivate *childd = child->d_ptr; - bool hasX = childd->hasTransform; bool hasPos = !childd->pos.isNull(); - if (hasPos || hasX) { + if (hasPos || childd->transform) { QTransform matrix; - if (hasX) - matrix = child->transform(); + if (childd->transform) + matrix = *childd->transform; if (hasPos) { const QPointF &p = childd->pos; matrix *= QTransform::fromTranslate(p.x(), p.y()); @@ -2626,7 +2625,7 @@ QMatrix QGraphicsItem::matrix() const */ QTransform QGraphicsItem::transform() const { - if (!d_ptr->hasTransform || !d_ptr->transform) + if (!d_ptr->transform) return QTransform(); return *d_ptr->transform; } @@ -2666,8 +2665,8 @@ QTransform QGraphicsItem::sceneTransform() const QTransform m; const QGraphicsItem *p = this; do { - if (p->d_ptr->hasTransform) - m *= p->transform(); + if (p->d_ptr->transform) + m *= *p->d_ptr->transform; const QPointF &pos = p->d_ptr->pos; if (!pos.isNull()) m *= QTransform::fromTranslate(pos.x(), pos.y()); @@ -2777,17 +2776,17 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co *ok = true; const QPointF &itemPos = d_ptr->pos; if (itemPos.isNull()) - return d_ptr->hasTransform ? transform() : QTransform(); - if (d_ptr->hasTransform) - return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y()); + return d_ptr->transform ? *d_ptr->transform : QTransform(); + if (d_ptr->transform) + return *d_ptr->transform * QTransform::fromTranslate(itemPos.x(), itemPos.y()); return QTransform::fromTranslate(itemPos.x(), itemPos.y()); } // This is other's parent if (otherParent == this) { const QPointF &otherPos = other->d_ptr->pos; - if (other->d_ptr->hasTransform) { - QTransform otherToParent = other->transform(); + if (other->d_ptr->transform) { + QTransform otherToParent = *other->d_ptr->transform; if (!otherPos.isNull()) otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y()); return otherToParent.inverted(ok); @@ -2800,12 +2799,10 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co // Siblings if (parent == otherParent) { - bool hasTr = d_ptr->hasTransform; - bool otherHasTr = other->d_ptr->hasTransform; const QPointF &itemPos = d_ptr->pos; const QPointF &otherPos = other->d_ptr->pos; - if (!hasTr && !otherHasTr) { + if (!d_ptr->transform && !other->d_ptr->transform) { QPointF delta = itemPos - otherPos; if (ok) *ok = true; @@ -2813,12 +2810,12 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co } QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y()); - if (hasTr) - itemToParent = itemPos.isNull() ? transform() : transform() * itemToParent; + if (d_ptr->transform) + itemToParent = itemPos.isNull() ? *d_ptr->transform : *d_ptr->transform * itemToParent; QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y()); - if (otherHasTr) - otherToParent = otherPos.isNull() ? other->transform() : other->transform() * otherToParent; + if (other->d_ptr->transform) + otherToParent = otherPos.isNull() ? *other->d_ptr->transform : *other->d_ptr->transform * otherToParent; return itemToParent * otherToParent.inverted(ok); } @@ -2856,8 +2853,8 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co const QGraphicsItem *p = child; do { const QGraphicsItemPrivate *pd = p->d_ptr; - if (pd->hasTransform) - x *= p->transform(); + if (pd->transform) + x *= *pd->transform; if (!pd->pos.isNull()) x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y()); } while ((p = p->d_ptr->parent) && p != root); @@ -2895,7 +2892,6 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); - d_ptr->hasTransform = !newTransform.isIdentity(); if(!d_ptr->transform) d_ptr->transform = new QTransform(newTransform); else @@ -2943,7 +2939,6 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); - d_ptr->hasTransform = !newTransform.isIdentity(); if(!d_ptr->transform) d_ptr->transform = new QTransform(newTransform); else @@ -3214,7 +3209,7 @@ QRectF QGraphicsItem::sceneBoundingRect() const const QGraphicsItemPrivate *itemd; do { itemd = parentItem->d_ptr; - if (itemd->hasTransform) + if (itemd->transform) break; offset += itemd->pos; } while ((parentItem = itemd->parent)); @@ -3984,13 +3979,13 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n // Find closest clip ancestor and transform. Q_Q(QGraphicsItem); - QTransform thisToParentTransform = hasTransform - ? q->transform() * QTransform::fromTranslate(newPos.x(), newPos.y()) + QTransform thisToParentTransform = transform + ? *transform * QTransform::fromTranslate(newPos.x(), newPos.y()) : QTransform::fromTranslate(newPos.x(), newPos.y()); QGraphicsItem *clipParent = parent; while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) { - if (clipParent->d_ptr->hasTransform) - thisToParentTransform *= clipParent->transform(); + if (clipParent->d_ptr->transform) + thisToParentTransform *= *clipParent->d_ptr->transform; if (!clipParent->d_ptr->pos.isNull()) { thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(), clipParent->d_ptr->pos.y()); @@ -4357,9 +4352,9 @@ QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point */ QPointF QGraphicsItem::mapToParent(const QPointF &point) const { - if (!d_ptr->hasTransform) + if (!d_ptr->transform) return point + d_ptr->pos; - return transform().map(point) + d_ptr->pos; + return d_ptr->transform->map(point) + d_ptr->pos; } /*! @@ -4424,9 +4419,9 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect */ QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const { - if (!d_ptr->hasTransform) + if (!d_ptr->transform) return rect.translated(d_ptr->pos); - return transform().map(rect).translated(d_ptr->pos); + return d_ptr->transform->map(rect).translated(d_ptr->pos); } /*! @@ -4493,7 +4488,7 @@ QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rec */ QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const { - QRectF r = !d_ptr->hasTransform ? rect : transform().mapRect(rect); + QRectF r = !d_ptr->transform ? rect : d_ptr->transform->mapRect(rect); return r.translated(d_ptr->pos); } @@ -4566,7 +4561,7 @@ QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &r QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const { QRectF r = rect.translated(-d_ptr->pos); - return d_ptr->hasTransform ? transform().inverted().mapRect(r) : r; + return d_ptr->transform ? d_ptr->transform->inverted().mapRect(r) : r; } /*! @@ -4625,9 +4620,9 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &p */ QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const { - if (!d_ptr->hasTransform) + if (!d_ptr->transform) return polygon.translated(d_ptr->pos); - return transform().map(polygon).translated(d_ptr->pos); + return d_ptr->transform->map(polygon).translated(d_ptr->pos); } /*! @@ -4669,9 +4664,9 @@ QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterP */ QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const { - if (!d_ptr->hasTransform) + if (!d_ptr->transform) return path.translated(d_ptr->pos); - return transform().map(path).translated(d_ptr->pos); + return d_ptr->transform->map(path).translated(d_ptr->pos); } /*! @@ -4720,8 +4715,8 @@ QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &poi */ QPointF QGraphicsItem::mapFromParent(const QPointF &point) const { - if (d_ptr->hasTransform) - return transform().inverted().map(point - d_ptr->pos); + if (d_ptr->transform) + return d_ptr->transform->inverted().map(point - d_ptr->pos); return point - d_ptr->pos; } @@ -4789,7 +4784,7 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &re QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const { QRectF r = rect.translated(-d_ptr->pos); - return d_ptr->hasTransform ? transform().inverted().map(r) : r; + return d_ptr->transform ? d_ptr->transform->inverted().map(r) : r; } /*! @@ -4846,7 +4841,7 @@ QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const { QPolygonF p = polygon; p.translate(-d_ptr->pos); - return d_ptr->hasTransform ? transform().inverted().map(p) : p; + return d_ptr->transform ? d_ptr->transform->inverted().map(p) : p; } /*! @@ -4888,7 +4883,7 @@ QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const { QPainterPath p(path); p.translate(-d_ptr->pos); - return d_ptr->hasTransform ? transform().inverted().map(p) : p; + return d_ptr->transform ? d_ptr->transform->inverted().map(p) : p; } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 5a6401a..35305b4 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -132,7 +132,6 @@ public: isMemberOfGroup(0), handlesChildEvents(0), itemDiscovered(0), - hasTransform(0), hasCursor(0), ancestorFlags(0), cacheMode(0), @@ -335,7 +334,6 @@ public: quint32 isMemberOfGroup : 1; quint32 handlesChildEvents : 1; quint32 itemDiscovered : 1; - quint32 hasTransform : 1; quint32 hasCursor : 1; quint32 ancestorFlags : 3; quint32 cacheMode : 2; @@ -349,6 +347,7 @@ public: quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; + quint32 unused : 1; // New 32 bits quint32 flags : 10; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 86e7cdb..b105c9c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1679,7 +1679,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) continue; // Skip invisible items and all their children. @@ -1719,7 +1719,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) continue; // Skip invisible items and all their children. @@ -1755,7 +1755,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { // Recurse into children. - if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) { + if (!item->d_ptr->transform || item->d_ptr->transform->type() <= QTransform::TxScale) { // Rect childItems_helper(items, item, item->mapRectFromParent(rect), mode); } else { @@ -1785,7 +1785,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) continue; // Skip invisible items. @@ -1844,7 +1844,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) continue; // Skip invisible items. @@ -5065,9 +5065,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } else { const QPointF &pos = item->d_ptr->pos; bool posNull = pos.isNull(); - if (!posNull || item->d_ptr->hasTransform) { - if (item->d_ptr->hasTransform) { - QTransform x = item->transform(); + if (!posNull || item->d_ptr->transform) { + if (item->d_ptr->transform) { + QTransform x = *item->d_ptr->transform; if (!posNull) x *= QTransform::fromTranslate(pos.x(), pos.y()); transform = x * parentTransform; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index acf26e1..68c0e39 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -753,7 +753,7 @@ QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRect const QGraphicsItemPrivate *itemd; do { itemd = parentItem->d_ptr; - if (itemd->hasTransform) + if (itemd->transform) break; offset += itemd->pos; } while ((parentItem = itemd->parent)); -- cgit v0.12 From 7c164da956c3b55b6b38df1c9e13dcd821b5062f Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 15:31:46 +0200 Subject: simplify opacity handling in QGraphicsItem Greatly simplify how we handle opacity and store it as a member in QGraphicsItemPrivate. Remove the caching of effectiveOpacity. It's faster to calculate it on the fly, and the recursive painting algorithm will make even that need go away. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 114 +++++---------------------------- src/gui/graphicsview/qgraphicsitem_p.h | 28 ++++---- 2 files changed, 31 insertions(+), 111 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 26da858..3f6b83c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -912,9 +912,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de scene->d_func()->invalidateSortCache(); } - // Resolve opacity. - updateEffectiveOpacity(); - // Resolve depth. resolveDepth(parent ? parent->d_ptr->depth : -1); @@ -1372,11 +1369,6 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) // Update flags. d_ptr->flags = flags; - // Reresolve effective opacity if the opacity flags change. - static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren; - if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask)) - d_ptr->updateEffectiveOpacity(); - if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) { // Clear focus on the item if it has focus when the focusable flag // is unset. @@ -1981,12 +1973,7 @@ void QGraphicsItem::setSelected(bool selected) */ qreal QGraphicsItem::opacity() const { - if (d_ptr->hasOpacity) { - QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity); - if (!o.isNull()) - return o.toDouble(); - } - return qreal(1.0); + return d_ptr->opacity; } /*! @@ -2002,11 +1989,20 @@ qreal QGraphicsItem::opacity() const */ qreal QGraphicsItem::effectiveOpacity() const { - if (!d_ptr->hasEffectiveOpacity) - return qreal(1.0); + if (!d_ptr->parent) + return d_ptr->opacity; + + QGraphicsItem::GraphicsItemFlags myFlags = flags(); + QGraphicsItem::GraphicsItemFlags parentFlags = d_ptr->parent ? d_ptr->parent->flags() : QGraphicsItem::GraphicsItemFlags(0); + + // If I have a parent, and I don't ignore my parent's opacity, and my + // parent propagates to me, then combine my local opacity with my parent's + // effective opacity into my effective opacity. + if (!(myFlags & QGraphicsItem::ItemIgnoresParentOpacity) + && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + return d_ptr->opacity * d_ptr->parent->effectiveOpacity(); - QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity); - return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble()); + return d_ptr->opacity; } /*! @@ -2041,24 +2037,10 @@ void QGraphicsItem::setOpacity(qreal opacity) newOpacity = qBound(0.0, newOpacity, 1.0); // No change? Done. - if (qFuzzyIsNull(newOpacity - this->opacity())) + if (newOpacity == d_ptr->opacity) return; - // Assign local opacity. - if (qFuzzyIsNull(newOpacity - 1)) { - // Opaque, unset opacity. - d_ptr->hasOpacity = 0; - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity); - } else { - d_ptr->hasOpacity = 1; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity)); - } - - // Resolve effective opacity. - if (QGraphicsItem *p = d_ptr->parent) - d_ptr->resolveEffectiveOpacity(p->effectiveOpacity()); - else - d_ptr->resolveEffectiveOpacity(1.0); + d_ptr->opacity = newOpacity; // Notify change. itemChange(ItemOpacityHasChanged, newOpacity); @@ -3793,70 +3775,6 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore || (!ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); } -static inline bool allChildrenCombineOpacityHelper(QGraphicsItem *parent) -{ - Q_ASSERT(parent); - if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) - return false; - - const QList children(parent->childItems()); - for (int i = 0; i < children.size(); ++i) { - if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity) - return false; - } - return true; -} - -void QGraphicsItemPrivate::updateEffectiveOpacity() -{ - Q_Q(QGraphicsItem); - if (parent) { - resolveEffectiveOpacity(parent->effectiveOpacity()); - parent->d_ptr->allChildrenCombineOpacity = allChildrenCombineOpacityHelper(parent); - } else { - resolveEffectiveOpacity(1.0); - } - allChildrenCombineOpacity = allChildrenCombineOpacityHelper(q); -} - -/*! - \internal - - Resolves and propagates this item's effective opacity to its children. -*/ -void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity) -{ - Q_Q(QGraphicsItem); - QGraphicsItem::GraphicsItemFlags myFlags = q->flags(); - QGraphicsItem::GraphicsItemFlags parentFlags = parent ? parent->flags() : QGraphicsItem::GraphicsItemFlags(0); - - // My local opacity is always part of my effective opacity. - qreal myEffectiveOpacity = q->opacity(); - - // If I have a parent, and I don't ignore my parent's opacity, and my - // parent propagates to me, then combine my local opacity with my parent's - // effective opacity into my effective opacity. - if (parent - && !(myFlags & QGraphicsItem::ItemIgnoresParentOpacity) - && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { - myEffectiveOpacity *= parentEffectiveOpacity; - } - - // Set this item's resolved opacity. - if (qFuzzyIsNull(myEffectiveOpacity - 1)) { - // Opaque, unset effective opacity. - hasEffectiveOpacity = 0; - unsetExtra(ExtraEffectiveOpacity); - } else { - hasEffectiveOpacity = 1; - setExtra(ExtraEffectiveOpacity, myEffectiveOpacity); - } - - // Resolve children always. - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->resolveEffectiveOpacity(myEffectiveOpacity); -} - /*! \internal diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 35305b4..c999378 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -100,10 +100,7 @@ public: ExtraCursor, ExtraCacheData, ExtraMaxDeviceCoordCacheSize, - ExtraBoundingRegionGranularity, - ExtraOpacity, - ExtraEffectiveOpacity, - ExtraDecomposedTransform + ExtraBoundingRegionGranularity }; enum AncestorFlag { @@ -115,6 +112,7 @@ public: inline QGraphicsItemPrivate() : z(0), + opacity(1.), scene(0), parent(0), transform(0), @@ -136,8 +134,6 @@ public: ancestorFlags(0), cacheMode(0), hasBoundingRegionGranularity(0), - hasOpacity(0), - hasEffectiveOpacity(0), isWidget(0), dirty(0), dirtyChildren(0), @@ -177,8 +173,6 @@ public: void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; - void updateEffectiveOpacity(); - void resolveEffectiveOpacity(qreal effectiveParentOpacity); void resolveDepth(int parentDepth); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); @@ -278,10 +272,19 @@ public: void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); inline bool isFullyTransparent() const - { return hasEffectiveOpacity && qFuzzyIsNull(q_func()->effectiveOpacity()); } + { return q_func()->effectiveOpacity() < .001; } inline bool childrenCombineOpacity() const - { return allChildrenCombineOpacity || children.isEmpty(); } + { + if (!children.size() || flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) + return false; + + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity) + return false; + } + return true; + } inline bool isClippedAway() const { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } @@ -314,6 +317,7 @@ public: QMap paintedViewBoundingRects; QPointF pos; qreal z; + qreal opacity; QGraphicsScene *scene; QGraphicsItem *parent; QList children; @@ -338,8 +342,6 @@ public: quint32 ancestorFlags : 3; quint32 cacheMode : 2; quint32 hasBoundingRegionGranularity : 1; - quint32 hasOpacity : 1; - quint32 hasEffectiveOpacity : 1; quint32 isWidget : 1; quint32 dirty : 1; quint32 dirtyChildren : 1; @@ -347,7 +349,7 @@ public: quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; - quint32 unused : 1; + quint32 unused : 3; // New 32 bits quint32 flags : 10; -- cgit v0.12 From ce5b4c468d98bb4ec64429fa362554b9b3614496 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 16:08:25 +0200 Subject: smaller optimisation in setTransform --- src/gui/graphicsview/qgraphicsitem.cpp | 40 +++++++++++++++------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3f6b83c..486e0b5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2860,28 +2860,25 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co */ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) { - QTransform oldTransform = this->transform(); - QTransform newTransform(combine ? QTransform(matrix) * oldTransform : QTransform(matrix)); - if (oldTransform == newTransform) + if(!d_ptr->transform) + d_ptr->transform = new QTransform; + + QTransform newTransform(combine ? QTransform(matrix) * *d_ptr->transform : QTransform(matrix)); + if(*d_ptr->transform == newTransform) return; - // Notify the item that the matrix is changing. - QVariant newTransformVariant(itemChange(ItemMatrixChange, - qVariantFromValue(newTransform.toAffine()))); - newTransform = QTransform(qVariantValue(newTransformVariant)); - if (oldTransform == newTransform) + // Notify the item that the transformation matrix is changing. + const QVariant newTransformVariant(itemChange(ItemTransformChange, + qVariantFromValue(newTransform))); + newTransform = qVariantValue(newTransformVariant); + if (*d_ptr->transform == newTransform) return; // Update and set the new transformation. prepareGeometryChange(); - if(!d_ptr->transform) - d_ptr->transform = new QTransform(newTransform); - else - *d_ptr->transform = newTransform; + *d_ptr->transform = newTransform; // Send post-notification. - // NB! We have to change the value from QMatrix to QTransform. - qVariantSetValue(newTransformVariant, newTransform); itemChange(ItemTransformHasChanged, newTransformVariant); } @@ -2907,24 +2904,23 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) */ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) { - QTransform oldTransform = this->transform(); - QTransform newTransform(combine ? matrix * oldTransform : matrix); - if (oldTransform == newTransform) + if(!d_ptr->transform) + d_ptr->transform = new QTransform; + + QTransform newTransform(combine ? matrix * *d_ptr->transform : matrix); + if(*d_ptr->transform == newTransform) return; // Notify the item that the transformation matrix is changing. const QVariant newTransformVariant(itemChange(ItemTransformChange, qVariantFromValue(newTransform))); newTransform = qVariantValue(newTransformVariant); - if (oldTransform == newTransform) + if (*d_ptr->transform == newTransform) return; // Update and set the new transformation. prepareGeometryChange(); - if(!d_ptr->transform) - d_ptr->transform = new QTransform(newTransform); - else - *d_ptr->transform = newTransform; + *d_ptr->transform = newTransform; // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); -- cgit v0.12 From fa256ad3758e0d8794136975f0e93ddfa91216f5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 16:09:38 +0200 Subject: remove now unused flag --- src/gui/graphicsview/qgraphicsitem_p.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index c999378..95a7733 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -142,10 +142,6 @@ public: emptyClipPath(0), inSetPosHelper(0), flags(0), - allChildrenCombineOpacity(1), - hasDecomposedTransform(0), - dirtyTransform(0), - dirtyTransformComponents(0), dirtyChildrenBoundingRect(1), inDirtyList(0), paintedViewBoundingRectsNeedRepaint(0), @@ -353,14 +349,10 @@ public: // New 32 bits quint32 flags : 10; - quint32 allChildrenCombineOpacity : 1; - quint32 hasDecomposedTransform : 1; - quint32 dirtyTransform : 1; - quint32 dirtyTransformComponents : 1; quint32 dirtyChildrenBoundingRect : 1; quint32 inDirtyList : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 padding : 15; // feel free to use + quint32 padding : 19; // feel free to use // Optional stacking order int globalStackingOrder; -- cgit v0.12 From 72e083c98c3adb07bb1578fb7f28f121fc3f34ac Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 16:47:29 +0200 Subject: greatly speed up QTransform::mapRect() for projective transforms The code so far was converting the rect to a painterpath, mapping that one and then taking the bounding rect. It is actually sufficient to simply map the four corners of the rectangle and take the bounding rect of these four points even in the projective case. Reviewed-by: Andreas --- src/gui/painting/qtransform.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index c00012a..86e594c 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1788,7 +1788,7 @@ QRect QTransform::mapRect(const QRect &rect) const y -= h; } return QRect(x, y, w, h); - } else if (t < TxProject) { + } else { // see mapToPolygon for explanations of the algorithm. qreal x = 0, y = 0; MAP(rect.left(), rect.top(), x, y); @@ -1812,10 +1812,6 @@ QRect QTransform::mapRect(const QRect &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin)); - } else { - QPainterPath path; - path.addRect(rect); - return map(path).boundingRect().toRect(); } } @@ -1858,7 +1854,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const y -= h; } return QRectF(x, y, w, h); - } else if (t < TxProject) { + } else { qreal x = 0, y = 0; MAP(rect.x(), rect.y(), x, y); qreal xmin = x; @@ -1881,10 +1877,6 @@ QRectF QTransform::mapRect(const QRectF &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRectF(xmin, ymin, xmax-xmin, ymax - ymin); - } else { - QPainterPath path; - path.addRect(rect); - return map(path).boundingRect(); } } -- cgit v0.12 From bea8a19742ed1decbd63464e36e57980fbde7016 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 22:55:49 +0200 Subject: fix a small logic bug in childrenCombineOpacity Regression introduced during refactoring earlier today. --- src/gui/graphicsview/qgraphicsitem_p.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 95a7733..acd2fcc 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -272,7 +272,9 @@ public: inline bool childrenCombineOpacity() const { - if (!children.size() || flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) + if (!children.size()) + return true; + if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) return false; for (int i = 0; i < children.size(); ++i) { -- cgit v0.12 From c563cff78b9606bf5869707fcbe6183198508d60 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 08:54:31 +0200 Subject: Introduce QGraphicsItem::ItemHasNoContents. This flag helps optimize the case where an item is used only as a transformation node in a scene graph, and where the item itself doesn't paint anything. This is the default for FxItem (the subclasses that do paint enable the HasContents flag). This lets Graphics View know whether there's any point in setting up the world transform, opacity and other things. Reviewed-by: Lars --- src/gui/graphicsview/qgraphicsitem.cpp | 8 ++++++++ src/gui/graphicsview/qgraphicsitem.h | 3 ++- src/gui/graphicsview/qgraphicsitem_p.h | 4 ++-- src/gui/graphicsview/qgraphicsscene.cpp | 30 ++++++++++++++++++++---------- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 486e0b5..12aaba5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -309,6 +309,11 @@ and is always initialized to 1. Use QStyleOptionGraphicsItem::levelOfDetailFromTransform for a more fine-grained value. + + \value ItemHasNoContents The item does not paint anything (i.e., calling + paint() on the item has no effect). You should set this flag on items that + do not need to be painted to ensure that Graphics View avoids unnecessary + painting preparations. */ /*! @@ -9108,6 +9113,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemUsesExtendedStyleOption: str = "ItemUsesExtendedStyleOption"; break; + case QGraphicsItem::ItemHasNoContents: + str = "ItemHasNoContents"; + break; } debug << str; return debug; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index def773e..737ea80 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -95,7 +95,8 @@ public: ItemIgnoresParentOpacity = 0x40, ItemDoesntPropagateOpacityToChildren = 0x80, ItemStacksBehindParent = 0x100, - ItemUsesExtendedStyleOption = 0x200 + ItemUsesExtendedStyleOption = 0x200, + ItemHasNoContents = 0x400 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index acd2fcc..9d5b58a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -350,11 +350,11 @@ public: quint32 unused : 3; // New 32 bits - quint32 flags : 10; + quint32 flags : 11; quint32 dirtyChildrenBoundingRect : 1; quint32 inDirtyList : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 padding : 19; // feel free to use + quint32 padding : 18; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b105c9c..eaebd1a 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -295,9 +295,13 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) static inline void _q_adjustRect(QRectF *rect) { Q_ASSERT(rect); - if (!rect->width()) + bool nullWidth = !rect->width(); + bool nullHeight = !rect->height(); + if (nullWidth && nullHeight) + return; + if (nullWidth) rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) + else if (nullHeight) rect->adjust(0, -0.00001, 0, 0.00001); } @@ -5079,22 +5083,23 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } } QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - const QRect paintedViewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); - item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); - viewBoundingRect = paintedViewBoundingRect & exposedRegion.boundingRect(); + if (!brect.size().isNull()) { + // ### This does not take the clip into account. + _q_adjustRect(&brect); + const QRect paintedViewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); + item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); + viewBoundingRect = paintedViewBoundingRect & exposedRegion.boundingRect(); + } } else { transform = parentTransform; } - // Find and sort children. - QList children = item ? item->d_ptr->children : topLevelItems; - qSort(children.begin(), children.end(), qt_notclosestLeaf); - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); bool dontDrawItem = !item || viewBoundingRect.isEmpty(); bool dontDrawChildren = item && dontDrawItem && childClip; childClip &= !dontDrawChildren & !children.isEmpty(); + if (item && item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) + dontDrawItem = true; // Clip children. if (childClip) { @@ -5103,6 +5108,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setClipPath(item->shape(), Qt::IntersectClip); } + // Find and sort children. + QList children = item ? item->d_ptr->children : topLevelItems; + if (!dontDrawChildren) + qSort(children.begin(), children.end(), qt_notclosestLeaf); + // Draw children behind int i; if (!dontDrawChildren) { -- cgit v0.12 From 33c1496689c090561657c698321442ae655ccec3 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 28 May 2009 11:31:24 +0200 Subject: Remove scene transform cache from QGraphicsItem. Now that we have a recursive painting algorithm these types of optimizations are no longer necessary. In fact they only cause more problems and clutter up the code unnecessarily. Removing this also removes extra overhead from moving and transforming items. Reviewed-by: Lars --- src/gui/graphicsview/qgraphicsitem.cpp | 232 +++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 12aaba5..0990e16 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2652,8 +2652,13 @@ QTransform QGraphicsItem::sceneTransform() const QTransform m; const QGraphicsItem *p = this; do { +<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp if (p->d_ptr->transform) m *= *p->d_ptr->transform; +======= + if (p->d_ptr->hasTransform) + m *= p->transform(); +>>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp const QPointF &pos = p->d_ptr->pos; if (!pos.isNull()) m *= QTransform::fromTranslate(pos.x(), pos.y()); @@ -2881,7 +2886,13 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); +<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp *d_ptr->transform = newTransform; +======= + transformData->baseTransform = newTransform; + transformData->dirty = true; + d_ptr->hasTransform = true; +>>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -2925,7 +2936,14 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); +<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp *d_ptr->transform = newTransform; +======= + transformData->baseTransform = newTransform; + transformData->dirty = true; + d_ptr->hasTransform = true; + transform(); // ### update transform, bad! +>>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -3036,6 +3054,220 @@ void QGraphicsItem::translate(qreal dx, qreal dy) } /*! +<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp +======= + Returns the origin point used for all transformations. + */ +QPointF QGraphicsItem::transformOrigin() const +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) + return QPointF(); + + return transformData->transformCenter; +} + +/*! + Set a \a center for all transformations. +*/ +void QGraphicsItem::setTransformOrigin(const QPointF ¢er) +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) { + if (center.isNull()) + return; + transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); + } + if (transformData->transformCenter == center) + return; + + prepareGeometryChange(); + + transformData->transformCenter = center; + + transformData->dirty = true; + d_ptr->hasTransform = true; +} + +/*! + Returns the x scale factor. + */ +qreal QGraphicsItem::xScale() const +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) + return 1; + + return transformData->scaleX; +} + +/*! + Sets the x scale factor to \a factor. + */ +void QGraphicsItem::setXScale(qreal factor) +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) { + if (factor == 1) + return; + transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); + } + if (transformData->scaleX == factor) + return; + + prepareGeometryChange(); + + transformData->scaleX = factor; + transformData->dirty = true; + d_ptr->hasTransform = true; +} + +/*! + Returns the y scale factor. + */ +qreal QGraphicsItem::yScale() const +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) + return 1; + + return transformData->scaleY; +} + +/*! + Sets the y scale factor to \a factor. + */ +void QGraphicsItem::setYScale(qreal factor) +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) { + if (factor == 1) + return; + transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); + } + if (transformData->scaleY == factor) + return; + + prepareGeometryChange(); + + transformData->scaleY = factor; + transformData->dirty = true; + d_ptr->hasTransform = true; +} + +/*! + Returns the x rotation angle. + */ +qreal QGraphicsItem::xRotation() const +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) + return 0; + return transformData->rotationX; +} + +/*! + Sets the x rotation angle to \a angle. + */ +void QGraphicsItem::setXRotation(qreal angle) +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) { + if (qFuzzyCompare(angle + 1, 1)) + return; + transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); + } + + prepareGeometryChange(); + + transformData->rotationX = angle; + + transformData->dirty = true; + d_ptr->hasTransform = true; +} + +/*! + Returns the y rotation angle. + */ +qreal QGraphicsItem::yRotation() const +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) + return 0; + return transformData->rotationY; +} + +/*! + Sets the y rotation angle to \a angle. + */ +void QGraphicsItem::setYRotation(qreal angle) +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) { + if (qFuzzyCompare(angle + 1, 1)) + return; + transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); + } + + prepareGeometryChange(); + + transformData->rotationY = angle; + + transformData->dirty = true; + d_ptr->hasTransform = true; +} + +/*! + Returns the z rotation angle. + */ +qreal QGraphicsItem::zRotation() const +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) + return 0; + return transformData->rotationZ; +} + +/*! + Sets the z rotation angle to \a angle. + */ +void QGraphicsItem::setZRotation(qreal angle) +{ + QGraphicsItemPrivate::TransformData *transformData = static_cast( + qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); + if (!transformData) { + if (qFuzzyCompare(angle + 1, 1)) + return; + transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); + } + + prepareGeometryChange(); + + transformData->rotationZ = angle; + + transformData->dirty = true; + d_ptr->hasTransform = true; +} + +/*! +>>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp This virtual function is called twice for all items by the QGraphicsScene::advance() slot. In the first phase, all items are called with \a phase == 0, indicating that items on the scene are about to -- cgit v0.12 From e506c0816dadd336e8151a0af504bd8b814bbaf3 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 12:25:21 +0200 Subject: get rid of the hasTransform flag in QGraphicsItem Since the transform is now a pointer in QGraphicsItemPrivate, we can use this pointer directly and there's no need for a separate bitflag anymore. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 242 ++------------------------------- src/gui/graphicsview/qgraphicsitem_p.h | 2 +- 2 files changed, 9 insertions(+), 235 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 0990e16..3008997 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2652,13 +2652,8 @@ QTransform QGraphicsItem::sceneTransform() const QTransform m; const QGraphicsItem *p = this; do { -<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp if (p->d_ptr->transform) m *= *p->d_ptr->transform; -======= - if (p->d_ptr->hasTransform) - m *= p->transform(); ->>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp const QPointF &pos = p->d_ptr->pos; if (!pos.isNull()) m *= QTransform::fromTranslate(pos.x(), pos.y()); @@ -2886,13 +2881,10 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); -<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp - *d_ptr->transform = newTransform; -======= - transformData->baseTransform = newTransform; - transformData->dirty = true; - d_ptr->hasTransform = true; ->>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp + if(!d_ptr->transform) + d_ptr->transform = new QTransform(newTransform); + else + *d_ptr->transform = newTransform; // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -2936,14 +2928,10 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); -<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp - *d_ptr->transform = newTransform; -======= - transformData->baseTransform = newTransform; - transformData->dirty = true; - d_ptr->hasTransform = true; - transform(); // ### update transform, bad! ->>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp + if(!d_ptr->transform) + d_ptr->transform = new QTransform(newTransform); + else + *d_ptr->transform = newTransform; // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -3054,220 +3042,6 @@ void QGraphicsItem::translate(qreal dx, qreal dy) } /*! -<<<<<<< HEAD:src/gui/graphicsview/qgraphicsitem.cpp -======= - Returns the origin point used for all transformations. - */ -QPointF QGraphicsItem::transformOrigin() const -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) - return QPointF(); - - return transformData->transformCenter; -} - -/*! - Set a \a center for all transformations. -*/ -void QGraphicsItem::setTransformOrigin(const QPointF ¢er) -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) { - if (center.isNull()) - return; - transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); - } - if (transformData->transformCenter == center) - return; - - prepareGeometryChange(); - - transformData->transformCenter = center; - - transformData->dirty = true; - d_ptr->hasTransform = true; -} - -/*! - Returns the x scale factor. - */ -qreal QGraphicsItem::xScale() const -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) - return 1; - - return transformData->scaleX; -} - -/*! - Sets the x scale factor to \a factor. - */ -void QGraphicsItem::setXScale(qreal factor) -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) { - if (factor == 1) - return; - transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); - } - if (transformData->scaleX == factor) - return; - - prepareGeometryChange(); - - transformData->scaleX = factor; - transformData->dirty = true; - d_ptr->hasTransform = true; -} - -/*! - Returns the y scale factor. - */ -qreal QGraphicsItem::yScale() const -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) - return 1; - - return transformData->scaleY; -} - -/*! - Sets the y scale factor to \a factor. - */ -void QGraphicsItem::setYScale(qreal factor) -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) { - if (factor == 1) - return; - transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); - } - if (transformData->scaleY == factor) - return; - - prepareGeometryChange(); - - transformData->scaleY = factor; - transformData->dirty = true; - d_ptr->hasTransform = true; -} - -/*! - Returns the x rotation angle. - */ -qreal QGraphicsItem::xRotation() const -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) - return 0; - return transformData->rotationX; -} - -/*! - Sets the x rotation angle to \a angle. - */ -void QGraphicsItem::setXRotation(qreal angle) -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) { - if (qFuzzyCompare(angle + 1, 1)) - return; - transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); - } - - prepareGeometryChange(); - - transformData->rotationX = angle; - - transformData->dirty = true; - d_ptr->hasTransform = true; -} - -/*! - Returns the y rotation angle. - */ -qreal QGraphicsItem::yRotation() const -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) - return 0; - return transformData->rotationY; -} - -/*! - Sets the y rotation angle to \a angle. - */ -void QGraphicsItem::setYRotation(qreal angle) -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) { - if (qFuzzyCompare(angle + 1, 1)) - return; - transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); - } - - prepareGeometryChange(); - - transformData->rotationY = angle; - - transformData->dirty = true; - d_ptr->hasTransform = true; -} - -/*! - Returns the z rotation angle. - */ -qreal QGraphicsItem::zRotation() const -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) - return 0; - return transformData->rotationZ; -} - -/*! - Sets the z rotation angle to \a angle. - */ -void QGraphicsItem::setZRotation(qreal angle) -{ - QGraphicsItemPrivate::TransformData *transformData = static_cast( - qVariantValue(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform))); - if (!transformData) { - if (qFuzzyCompare(angle + 1, 1)) - return; - transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue(transformData)); - } - - prepareGeometryChange(); - - transformData->rotationZ = angle; - - transformData->dirty = true; - d_ptr->hasTransform = true; -} - -/*! ->>>>>>> Remove scene transform cache from QGraphicsItem.:src/gui/graphicsview/qgraphicsitem.cpp This virtual function is called twice for all items by the QGraphicsScene::advance() slot. In the first phase, all items are called with \a phase == 0, indicating that items on the scene are about to diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 9d5b58a..4deb6e5 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -347,7 +347,7 @@ public: quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; - quint32 unused : 3; + quint32 unused : 1; // New 32 bits quint32 flags : 11; -- cgit v0.12 From 0e650ed3a8e7e4bdf4c9d3eefd667d4abb318c5a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 15:31:46 +0200 Subject: simplify opacity handling in QGraphicsItem Greatly simplify how we handle opacity and store it as a member in QGraphicsItemPrivate. Remove the caching of effectiveOpacity. It's faster to calculate it on the fly, and the recursive painting algorithm will make even that need go away. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem_p.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 4deb6e5..aac1795 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -272,9 +272,7 @@ public: inline bool childrenCombineOpacity() const { - if (!children.size()) - return true; - if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) + if (!children.size() || flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) return false; for (int i = 0; i < children.size(); ++i) { @@ -347,7 +345,7 @@ public: quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; - quint32 unused : 1; + quint32 unused : 3; // New 32 bits quint32 flags : 11; -- cgit v0.12 From 910e3d807226027a48a3b02906ff8e15b662ad00 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 16:08:25 +0200 Subject: smaller optimisation in setTransform --- src/gui/graphicsview/qgraphicsitem.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3008997..12aaba5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2881,10 +2881,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); - if(!d_ptr->transform) - d_ptr->transform = new QTransform(newTransform); - else - *d_ptr->transform = newTransform; + *d_ptr->transform = newTransform; // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -2928,10 +2925,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); - if(!d_ptr->transform) - d_ptr->transform = new QTransform(newTransform); - else - *d_ptr->transform = newTransform; + *d_ptr->transform = newTransform; // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); -- cgit v0.12 From f8f185b99a12e14374ce29501b8d13c5e3d125fd Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 16:09:38 +0200 Subject: remove now unused flag --- src/gui/graphicsview/qgraphicsitem_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index aac1795..95a7733 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -348,11 +348,11 @@ public: quint32 unused : 3; // New 32 bits - quint32 flags : 11; + quint32 flags : 10; quint32 dirtyChildrenBoundingRect : 1; quint32 inDirtyList : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 padding : 18; // feel free to use + quint32 padding : 19; // feel free to use // Optional stacking order int globalStackingOrder; -- cgit v0.12 From 6e92cbd42ce7e68112de8bce8a0468532843a947 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 28 May 2009 22:55:49 +0200 Subject: fix a small logic bug in childrenCombineOpacity Regression introduced during refactoring earlier today. --- src/gui/graphicsview/qgraphicsitem_p.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 95a7733..acd2fcc 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -272,7 +272,9 @@ public: inline bool childrenCombineOpacity() const { - if (!children.size() || flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) + if (!children.size()) + return true; + if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) return false; for (int i = 0; i < children.size(); ++i) { -- cgit v0.12 From aba52a08d8868682e576d1b53d423cedb0a9134e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 08:54:31 +0200 Subject: Introduce QGraphicsItem::ItemHasNoContents. This flag helps optimize the case where an item is used only as a transformation node in a scene graph, and where the item itself doesn't paint anything. This is the default for FxItem (the subclasses that do paint enable the HasContents flag). This lets Graphics View know whether there's any point in setting up the world transform, opacity and other things. Reviewed-by: Lars --- src/gui/graphicsview/qgraphicsitem_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index acd2fcc..9d5b58a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -350,11 +350,11 @@ public: quint32 unused : 3; // New 32 bits - quint32 flags : 10; + quint32 flags : 11; quint32 dirtyChildrenBoundingRect : 1; quint32 inDirtyList : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 padding : 19; // feel free to use + quint32 padding : 18; // feel free to use // Optional stacking order int globalStackingOrder; -- cgit v0.12 From 32c09e7a36ecd41e8beb2a1f947944502793fd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 28 May 2009 20:16:20 +0200 Subject: More re-factoring of Graphics View's update mechanism. This time with a recursive approach of processing dirty items. I've kept the previous approach using a dirty list, but the recursive one is now the default. Use QT_GV_USE_DIRTY_LIST=1 to swap. I've also cached the item's device transform in both cases so that we can re-use it later when drawing the item. --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsitem_p.h | 21 ++- src/gui/graphicsview/qgraphicsscene.cpp | 241 +++++++++++++++++++++++--------- src/gui/graphicsview/qgraphicsscene_p.h | 4 + 4 files changed, 185 insertions(+), 83 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 12aaba5..c3744b2 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3769,7 +3769,7 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. return (!visible && !ignoreVisibleBit) - || (!ignoreDirtyBit && (dirty || hasDirtyAncestor())) + || (!ignoreDirtyBit && dirty) || !scene || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect) || (!ignoreClipping && (childrenClippedToShape() && isClippedAway())) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 9d5b58a..deaf30f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -145,6 +145,9 @@ public: dirtyChildrenBoundingRect(1), inDirtyList(0), paintedViewBoundingRectsNeedRepaint(0), + allChildrenDirty(0), + fullUpdatePending(0), + hasValidDeviceTransform(0), globalStackingOrder(-1), q_ptr(0) { @@ -297,18 +300,6 @@ public: || (childrenCombineOpacity() && isFullyTransparent()); } - inline bool hasDirtyAncestor() const - { - QGraphicsItem *p = parent; - while (p) { - if (p->d_ptr->dirtyChildren || (p->d_ptr->dirty && p->d_ptr->childrenClippedToShape())) - return true; - p = p->d_ptr->parent; - } - return false; - } - - QPainterPath cachedClipPath; QRectF childrenBoundingRect; QRectF needsRepaint; @@ -320,6 +311,7 @@ public: QGraphicsItem *parent; QList children; QTransform *transform; + QTransform deviceTransform; int siblingIndex; int index; int depth; @@ -354,7 +346,10 @@ public: quint32 dirtyChildrenBoundingRect : 1; quint32 inDirtyList : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 padding : 18; // feel free to use + quint32 allChildrenDirty : 1; + quint32 fullUpdatePending : 1; + quint32 hasValidDeviceTransform : 1; + quint32 padding : 15; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index eaebd1a..a5ac9d9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -337,6 +337,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() hasSceneRect(false), updateAll(false), calledEmitUpdated(false), + processDirtyItemsEmitted(false), selectionChanging(0), regenerateIndex(true), purgePending(false), @@ -683,73 +684,70 @@ void QGraphicsScenePrivate::_q_polishItems() void QGraphicsScenePrivate::_q_processDirtyItems() { - Q_Q(QGraphicsScene); - if (dirtyItems.isEmpty()) - return; + static int useDirtyListEnv = qgetenv("QT_GV_USE_DIRTY_LIST").toInt(); + processDirtyItemsEmitted = false; if (updateAll) { - for (int i = 0; i < dirtyItems.size(); ++i) - resetDirtyItem(dirtyItems.at(i)); - dirtyItems.clear(); + if (useDirtyListEnv) { + for (int i = 0; i < dirtyItems.size(); ++i) + resetDirtyItem(dirtyItems.at(i)); + dirtyItems.clear(); + } + return; + } + + if (!useDirtyListEnv) { + processDirtyItemsRecursive(0, views.at(0)->viewportTransform()); + for (int i = 0; i < views.size(); ++i) + views.at(i)->d_func()->processPendingUpdates(); return; } - const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); for (int i = 0; i < dirtyItems.size(); ++i) { QGraphicsItem *item = dirtyItems.at(i); - if (useCompatUpdate && !item->d_ptr->itemIsUntransformable() - && qFuzzyIsNull(item->boundingRegionGranularity())) { - // This block of code is kept for compatibility. Since 4.5, by default - // QGraphicsView does not connect the signal and we use the below - // method of delivering updates. - q->update(item->sceneBoundingRect()); - resetDirtyItem(item); - continue; + QGraphicsView *view = views.at(0); + QGraphicsViewPrivate *viewPrivate = view->d_func(); + const QTransform deviceTransform = item->deviceTransform(view->viewportTransform()); + + QRectF dirtyRect = adjustedItemBoundingRect(item); + if (!item->d_ptr->fullUpdatePending) { + _q_adjustRect(&item->d_ptr->needsRepaint); + dirtyRect &= item->d_ptr->needsRepaint; } - QRectF dirtyRect; - bool uninitializedDirtyRect = true; - - for (int j = 0; j < views.size(); ++j) { - QGraphicsView *view = views.at(j); - QGraphicsViewPrivate *viewPrivate = view->d_func(); - if (viewPrivate->fullUpdatePending) - continue; - switch (viewPrivate->viewportUpdateMode) { - case QGraphicsView::NoViewportUpdate: - continue; - case QGraphicsView::FullViewportUpdate: - view->viewport()->update(); - viewPrivate->fullUpdatePending = 1; - continue; - default: - break; - } - - if (uninitializedDirtyRect) { - dirtyRect = adjustedItemBoundingRect(item); - if (!item->d_ptr->dirty) { - _q_adjustRect(&item->d_ptr->needsRepaint); - dirtyRect &= item->d_ptr->needsRepaint; - } - - if (item->d_ptr->dirtyChildren && !item->d_ptr->children.isEmpty() - && !item->d_ptr->childrenClippedToShape()) { - QRectF childrenBounds = item->childrenBoundingRect(); - _q_adjustRect(&childrenBounds); - dirtyRect |= childrenBounds; - } - uninitializedDirtyRect = false; - } + if (item->d_ptr->allChildrenDirty && !item->d_ptr->children.isEmpty() + && !item->d_ptr->childrenClippedToShape()) { + QRectF childrenBounds = item->childrenBoundingRect(); + _q_adjustRect(&childrenBounds); + dirtyRect |= childrenBounds; + } - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) - viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) + viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); - if (!item->d_ptr->hasBoundingRegionGranularity) - viewPrivate->updateRect(viewPrivate->mapToViewRect(item, dirtyRect)); + bool dirtyRectOutsideViewport = false; + if (item->d_ptr->hasBoundingRegionGranularity) { + const QRegion dirtyViewRegion = deviceTransform.map(QRegion(dirtyRect.toRect())) + & viewPrivate->viewport->rect(); + if (!dirtyViewRegion.isEmpty()) + viewPrivate->updateRegion(dirtyViewRegion); else - viewPrivate->updateRegion(viewPrivate->mapToViewRegion(item, dirtyRect)); + dirtyRectOutsideViewport = true; + } else { + const QRect dirtyViewRect = deviceTransform.mapRect(dirtyRect).toRect() + & viewPrivate->viewport->rect(); + if (!dirtyViewRect.isEmpty()) + viewPrivate->updateRect(dirtyViewRect); + else + dirtyRectOutsideViewport = true; + } + if (!dirtyRectOutsideViewport) { + // We know for sure this item will be process in the paint event, hence + // store its device transform and re-use it when drawing. + item->d_ptr->hasValidDeviceTransform = 1; + item->d_ptr->deviceTransform = deviceTransform; } + resetDirtyItem(item); } @@ -5064,6 +5062,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QTransform transform; QRect viewBoundingRect; if (item) { + if (!item->d_ptr->hasValidDeviceTransform) { if (item->d_ptr->itemIsUntransformable()) { transform = item->deviceTransform(viewTransform); } else { @@ -5082,6 +5081,10 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * transform = parentTransform; } } + } else { + transform = item->d_ptr->deviceTransform; + item->d_ptr->hasValidDeviceTransform = 0; + } QRectF brect = item->boundingRect(); if (!brect.size().isNull()) { // ### This does not take the clip into account. @@ -5176,25 +5179,120 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (!fullItemUpdate && rect.isEmpty()) return; - if (dirtyItems.isEmpty()) + if (!processDirtyItemsEmitted) { QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection); + processDirtyItemsEmitted = true; + } + + item->d_ptr->dirty = 1; + if (fullItemUpdate) + item->d_ptr->fullUpdatePending = 1; + else if (!item->d_ptr->fullUpdatePending) + item->d_ptr->needsRepaint |= rect; - if (item->d_ptr->inDirtyList) { - if (fullItemUpdate) - item->d_ptr->dirty = 1; - else if (!item->d_ptr->dirty) - item->d_ptr->needsRepaint |= rect; + if (invalidateChildren) { + item->d_ptr->allChildrenDirty = 1; + item->d_ptr->dirtyChildren = 1; + } + + static int useDirtyListEnv = qgetenv("QT_GV_USE_DIRTY_LIST").toInt(); + if (useDirtyListEnv) { + if (!item->d_ptr->inDirtyList) { + dirtyItems.append(item); + item->d_ptr->inDirtyList = 1; + } } else { - dirtyItems.append(item); - item->d_ptr->inDirtyList = 1; - if (fullItemUpdate) - item->d_ptr->dirty = 1; - else if (!item->d_ptr->dirty) - item->d_ptr->needsRepaint = rect; + QGraphicsItem *p = item->d_ptr->parent; + while (p && !p->d_ptr->dirtyChildren) { + p->d_ptr->dirtyChildren = 1; + p = p->d_ptr->parent; + } } +} - if (invalidateChildren) - item->d_ptr->dirtyChildren = 1; +void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, const QTransform &parentTransform) +{ + Q_ASSERT(!item || item->d_ptr->dirty || item->d_ptr->dirtyChildren); + + // Calculate the full transform for this item. + QTransform transform; + if (item) { + if (item->d_ptr->itemIsUntransformable()) { + transform = item->deviceTransform(views.at(0)->viewportTransform()); + } else { + const QPointF &pos = item->d_ptr->pos; + bool posNull = pos.isNull(); + if (!posNull || item->d_ptr->transform) { + if (item->d_ptr->transform) { + transform = *item->d_ptr->transform; + if (!posNull) + transform *= QTransform::fromTranslate(pos.x(), pos.y()); + transform *= parentTransform; + } else { + transform = QTransform::fromTranslate(pos.x(), pos.y()) * parentTransform; + } + } else { + transform = parentTransform; + } + } + } else { + transform = parentTransform; + } + + // Process item. + if (item && item->d_ptr->dirty) { + QRectF dirtyRect = adjustedItemBoundingRect(item); + if (!item->d_ptr->fullUpdatePending) { + _q_adjustRect(&item->d_ptr->needsRepaint); + dirtyRect &= item->d_ptr->needsRepaint; + } + + QGraphicsViewPrivate *viewPrivate = views.at(0)->d_func(); + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) + viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + + bool dirtyRectOutsideViewport = false; + if (item->d_ptr->hasBoundingRegionGranularity) { + const QRegion dirtyViewRegion = transform.map(QRegion(dirtyRect.toRect())) + & viewPrivate->viewport->rect(); + if (!dirtyViewRegion.isEmpty()) + viewPrivate->updateRegion(dirtyViewRegion); + else + dirtyRectOutsideViewport = true; + } else { + const QRect dirtyViewRect = transform.mapRect(dirtyRect).toRect() + & viewPrivate->viewport->rect(); + if (!dirtyViewRect.isEmpty()) + viewPrivate->updateRect(dirtyViewRect); + else + dirtyRectOutsideViewport = true; + } + if (!dirtyRectOutsideViewport) { + // We know for sure this item will be process in the paint event, hence + // store its device transform and re-use it when drawing. + item->d_ptr->hasValidDeviceTransform = 1; + item->d_ptr->deviceTransform = transform; + } + } + + // Process root items / children. + if (!item || item->d_ptr->dirtyChildren) { + QList *children = item ? &item->d_ptr->children : &topLevelItems; + const bool allChildrenDirty = item && item->d_ptr->allChildrenDirty; + for (int i = 0; i < children->size(); ++i) { + QGraphicsItem *child = children->at(i); + if (allChildrenDirty) { + child->d_ptr->dirty = 1; + } else if (!child->d_ptr->dirty && !child->d_ptr->dirtyChildren) { + resetDirtyItem(child); + continue; + } + processDirtyItemsRecursive(child, transform); + } + } + + if (item) + resetDirtyItem(item); } /*! @@ -5302,7 +5400,12 @@ void QGraphicsScene::drawItems(QPainter *painter, } // Set up the painter transform - painter->setWorldTransform(item->deviceTransform(viewTransform), false); + if (item->d_ptr->hasValidDeviceTransform) { + painter->setWorldTransform(item->d_ptr->deviceTransform); + item->d_ptr->hasValidDeviceTransform = 0; + } else { + painter->setWorldTransform(item->deviceTransform(viewTransform), false); + } // Save painter bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape)); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index bf7ac0a..50c716c 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -105,6 +105,7 @@ public: QList updatedRects; bool updateAll; bool calledEmitUpdated; + bool processDirtyItemsEmitted; QPainterPath selectionArea; int selectionChanging; @@ -257,6 +258,7 @@ public: const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); + void processDirtyItemsRecursive(QGraphicsItem *item, const QTransform &); inline void resetDirtyItem(QGraphicsItem *item) { @@ -266,6 +268,8 @@ public: item->d_ptr->dirtyChildren = 0; item->d_ptr->inDirtyList = 0; item->d_ptr->needsRepaint = QRectF(); + item->d_ptr->allChildrenDirty = 0; + item->d_ptr->fullUpdatePending = 0; } inline void removeFromDirtyItems(QGraphicsItem *item) -- cgit v0.12 From f582ed67c29e2406adeb0a52c7a68a51e0c2e8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 29 May 2009 13:20:42 +0200 Subject: Only call qgetenv("QGRAPHICSVIEW_DIRECT") once. --- src/gui/graphicsview/qgraphicsview.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 68c0e39..369301e 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3313,9 +3313,8 @@ void QGraphicsView::paintEvent(QPaintEvent *event) int backgroundTime = stopWatch.elapsed() - exposedTime; #endif - const char *directEnv = getenv("QGRAPHICSVIEW_DIRECT"); - bool overrideDirectPaint = directEnv && atoi(directEnv) != 0; - if (overrideDirectPaint || (d->optimizationFlags & BypassDrawItems)) { + static int directEnv = getenv("QGRAPHICSVIEW_DIRECT").toInt(); + if (directEnv || (d->optimizationFlags & BypassDrawItems)) { d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, exposedRegion, viewport(), d->optimizationFlags); } else { -- cgit v0.12 From 669679d389ff0585bad30d41b085a4189d0e7a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 29 May 2009 13:24:02 +0200 Subject: Ooops. Compile :) --- src/gui/graphicsview/qgraphicsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 369301e..354feae 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3313,7 +3313,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) int backgroundTime = stopWatch.elapsed() - exposedTime; #endif - static int directEnv = getenv("QGRAPHICSVIEW_DIRECT").toInt(); + static int directEnv = qgetenv("QGRAPHICSVIEW_DIRECT").toInt(); if (directEnv || (d->optimizationFlags & BypassDrawItems)) { d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, exposedRegion, viewport(), d->optimizationFlags); -- cgit v0.12 From a10e4b983e228284202df536846e6b6d4a8cf40e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 14:40:32 +0200 Subject: Simplify the QTransform calculations. --- src/gui/graphicsview/qgraphicsscene.cpp | 46 ++++++++------------------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a5ac9d9..434cc8e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5059,28 +5059,18 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * return; // Calculate the full transform for this item. - QTransform transform; + QTransform transform = parentTransform; QRect viewBoundingRect; if (item) { if (!item->d_ptr->hasValidDeviceTransform) { - if (item->d_ptr->itemIsUntransformable()) { - transform = item->deviceTransform(viewTransform); - } else { - const QPointF &pos = item->d_ptr->pos; - bool posNull = pos.isNull(); - if (!posNull || item->d_ptr->transform) { - if (item->d_ptr->transform) { - QTransform x = *item->d_ptr->transform; - if (!posNull) - x *= QTransform::fromTranslate(pos.x(), pos.y()); - transform = x * parentTransform; - } else { - transform = QTransform::fromTranslate(pos.x(), pos.y()) * parentTransform; - } + if (item->d_ptr->itemIsUntransformable()) { + transform = item->deviceTransform(viewTransform); } else { - transform = parentTransform; + const QPointF &pos = item->d_ptr->pos; + transform.translate(pos.x(), pos.y()); + if (item->d_ptr->transform) + transform = *item->d_ptr->transform * transform; } - } } else { transform = item->d_ptr->deviceTransform; item->d_ptr->hasValidDeviceTransform = 0; @@ -5093,8 +5083,6 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); viewBoundingRect = paintedViewBoundingRect & exposedRegion.boundingRect(); } - } else { - transform = parentTransform; } bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); @@ -5215,28 +5203,16 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, cons Q_ASSERT(!item || item->d_ptr->dirty || item->d_ptr->dirtyChildren); // Calculate the full transform for this item. - QTransform transform; + QTransform transform = parentTransform; if (item) { if (item->d_ptr->itemIsUntransformable()) { transform = item->deviceTransform(views.at(0)->viewportTransform()); } else { const QPointF &pos = item->d_ptr->pos; - bool posNull = pos.isNull(); - if (!posNull || item->d_ptr->transform) { - if (item->d_ptr->transform) { - transform = *item->d_ptr->transform; - if (!posNull) - transform *= QTransform::fromTranslate(pos.x(), pos.y()); - transform *= parentTransform; - } else { - transform = QTransform::fromTranslate(pos.x(), pos.y()) * parentTransform; - } - } else { - transform = parentTransform; - } + transform.translate(pos.x(), pos.y()); + if (item->d_ptr->transform) + transform = *item->d_ptr->transform * transform; } - } else { - transform = parentTransform; } // Process item. -- cgit v0.12 From 2581606e0f86280546c498fec130d2625376dda7 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 15:10:44 +0200 Subject: Remove siblingIndex and use stable sorting instead. To avoid sorting siblings in real-time, ensure we lazily sort the list in place when needed. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 18 ++++++------------ src/gui/graphicsview/qgraphicsitem_p.h | 6 +++--- src/gui/graphicsview/qgraphicsscene.cpp | 27 ++++++++++++++------------- src/gui/graphicsview/qgraphicsscene_p.h | 1 + 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index c3744b2..9159381 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1997,15 +1997,16 @@ qreal QGraphicsItem::effectiveOpacity() const if (!d_ptr->parent) return d_ptr->opacity; - QGraphicsItem::GraphicsItemFlags myFlags = flags(); - QGraphicsItem::GraphicsItemFlags parentFlags = d_ptr->parent ? d_ptr->parent->flags() : QGraphicsItem::GraphicsItemFlags(0); + int myFlags = d_ptr->flags; + int parentFlags = d_ptr->parent ? d_ptr->parent->d_ptr->flags : 0; // If I have a parent, and I don't ignore my parent's opacity, and my // parent propagates to me, then combine my local opacity with my parent's // effective opacity into my effective opacity. if (!(myFlags & QGraphicsItem::ItemIgnoresParentOpacity) - && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { return d_ptr->opacity * d_ptr->parent->effectiveOpacity(); + } return d_ptr->opacity; } @@ -3793,7 +3794,7 @@ void QGraphicsItemPrivate::resolveDepth(int parentDepth) */ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) { - child->d_ptr->siblingIndex = children.size(); + needSortChildren = 1; children.append(child); } @@ -3802,14 +3803,7 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) */ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) { - int idx = child->d_ptr->siblingIndex; - int size = children.size(); - for (int i = idx; i < size - 1; ++i) { - QGraphicsItem *p = children[i + 1]; - children[i] = p; - p->d_ptr->siblingIndex = i; - } - children.removeLast(); + children.removeOne(child); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index deaf30f..80b1fb4 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -116,7 +116,6 @@ public: scene(0), parent(0), transform(0), - siblingIndex(-1), index(-1), depth(0), acceptedMouseButtons(0x1f), @@ -141,6 +140,7 @@ public: dirtyClipPath(1), emptyClipPath(0), inSetPosHelper(0), + needSortChildren(1), flags(0), dirtyChildrenBoundingRect(1), inDirtyList(0), @@ -312,7 +312,6 @@ public: QList children; QTransform *transform; QTransform deviceTransform; - int siblingIndex; int index; int depth; @@ -339,7 +338,8 @@ public: quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; - quint32 unused : 3; + quint32 needSortChildren : 1; + quint32 unused : 2; // New 32 bits quint32 flags : 11; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 434cc8e..52dc152 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -339,6 +339,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() calledEmitUpdated(false), processDirtyItemsEmitted(false), selectionChanging(0), + needSortTopLevelItems(true), regenerateIndex(true), purgePending(false), indexTimerId(0), @@ -631,7 +632,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() */ void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) { - item->d_ptr->siblingIndex = topLevelItems.size(); + needSortTopLevelItems = true; topLevelItems.append(item); } @@ -640,14 +641,7 @@ void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) */ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) { - int idx = item->d_ptr->siblingIndex; - int size = topLevelItems.size(); - for (int i = idx; i < size - 1; ++i) { - QGraphicsItem *p = topLevelItems[i + 1]; - topLevelItems[i] = p; - p->d_ptr->siblingIndex = i; - } - topLevelItems.removeLast(); + topLevelItems.removeOne(item); } /*! @@ -1910,7 +1904,7 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item if (f1 != f2) return f2; qreal z1 = d1->z; qreal z2 = d2->z; - return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex; + return z1 > z2; } static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) @@ -5100,9 +5094,16 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } // Find and sort children. - QList children = item ? item->d_ptr->children : topLevelItems; - if (!dontDrawChildren) - qSort(children.begin(), children.end(), qt_notclosestLeaf); + QList &children = item ? item->d_ptr->children : topLevelItems; + if (!dontDrawChildren) { + if (item && item->d_ptr->needSortChildren) { + item->d_ptr->needSortChildren = 0; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } else if (!item && needSortTopLevelItems) { + needSortTopLevelItems = false; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } + } // Draw children behind int i; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 50c716c..e7e96f5 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -116,6 +116,7 @@ public: QList pendingUpdateItems; QList unpolishedItems; QList topLevelItems; + bool needSortTopLevelItems; QMap movingItemsInitialPositions; void registerTopLevelItem(QGraphicsItem *item); void unregisterTopLevelItem(QGraphicsItem *item); -- cgit v0.12 From 5d54c09085979431831297f0e63f39c73f884d20 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 15:32:38 +0200 Subject: Avoid calling QGraphicsItem::effectiveOpacity() when rendering - instead just calculate it top-down. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 30 ++++++++++++++++++++++++------ src/gui/graphicsview/qgraphicsscene_p.h | 3 ++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 52dc152..1d33361 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5047,10 +5047,27 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, const QTransform &viewTransform, const QRegion &exposedRegion, QWidget *widget, - QGraphicsView::OptimizationFlags optimizationFlags) + QGraphicsView::OptimizationFlags optimizationFlags, + qreal parentOpacity) { - if (item && item->d_ptr->isInvisible()) - return; + // Calculate opacity. + qreal opacity; + if (item) { + if (!item->d_ptr->visible) + return; + QGraphicsItem *p = item->d_ptr->parent; + bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; + bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); + if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { + opacity = parentOpacity * item->opacity(); + } else { + opacity = item->d_ptr->opacity; + } + if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + return; + } else { + opacity = parentOpacity; + } // Calculate the full transform for this item. QTransform transform = parentTransform; @@ -5113,7 +5130,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; drawSubtreeRecursive(child, painter, transform, viewTransform, - exposedRegion, widget, optimizationFlags); + exposedRegion, widget, optimizationFlags, + opacity); } } @@ -5130,7 +5148,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setWorldTransform(transform); if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); - painter->setOpacity(item->effectiveOpacity()); + painter->setOpacity(opacity); drawItemHelper(item, painter, &option, widget, false); @@ -5142,7 +5160,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (!dontDrawChildren) { for (; i < children.size(); ++i) { drawSubtreeRecursive(children.at(i), painter, transform, viewTransform, - exposedRegion, widget, optimizationFlags); + exposedRegion, widget, optimizationFlags, opacity); } } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index e7e96f5..4facec3 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -256,7 +256,8 @@ public: void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, const QTransform &viewTransform, - const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags); + const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, + qreal parentOpacity = qreal(1.0)); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); void processDirtyItemsRecursive(QGraphicsItem *item, const QTransform &); -- cgit v0.12 From e5ffaeb4bc9b76a96fdddb31460d4acdc564ae3c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 16:04:59 +0200 Subject: Experimental change - disable itemChange notifications for move and transform. This change is only to test how much of an impact the itemChange mechanism has on performance. It's easy to revert later on. --- src/gui/graphicsview/qgraphicsitem.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 9159381..0b06613 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -39,6 +39,8 @@ ** ****************************************************************************/ +#define QGRAPHICSITEM_NO_ITEMCHANGE + /*! \class QGraphicsItem \brief The QGraphicsItem class is the base class for all graphical @@ -2036,8 +2038,12 @@ qreal QGraphicsItem::effectiveOpacity() const void QGraphicsItem::setOpacity(qreal opacity) { // Notify change. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity))); qreal newOpacity = newOpacityVariant.toDouble(); +#else + qreal newOpacity = opacity; +#endif // Normalize. newOpacity = qBound(0.0, newOpacity, 1.0); @@ -2049,7 +2055,9 @@ void QGraphicsItem::setOpacity(qreal opacity) d_ptr->opacity = newOpacity; // Notify change. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE itemChange(ItemOpacityHasChanged, newOpacity); +#endif // Update. if (d_ptr->scene) @@ -2499,10 +2507,14 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) return; // Notify the item that the position is changing. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos)); QPointF newPos = newPosVariant.toPointF(); if (newPos == this->pos) return; +#else + QPointF newPos = pos; +#endif // Update and repositition. inSetPosHelper = 1; @@ -2512,7 +2524,9 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) this->pos = newPos; // Send post-notification. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); +#endif inSetPosHelper = 0; } @@ -2874,18 +2888,22 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) return; // Notify the item that the transformation matrix is changing. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE const QVariant newTransformVariant(itemChange(ItemTransformChange, qVariantFromValue(newTransform))); newTransform = qVariantValue(newTransformVariant); if (*d_ptr->transform == newTransform) return; +#endif // Update and set the new transformation. prepareGeometryChange(); *d_ptr->transform = newTransform; // Send post-notification. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE itemChange(ItemTransformHasChanged, newTransformVariant); +#endif } /*! -- cgit v0.12 From d705abe962e309318ecad45064cbf61a2ffc79e2 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 16:05:55 +0200 Subject: Experimental change: replace all updates with repaints. This seems to be the only way to get a high frame rate, regardless of the performance of painting and all. --- src/gui/graphicsview/qgraphicsview.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 354feae..e205985 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -815,11 +815,11 @@ void QGraphicsViewPrivate::processPendingUpdates() if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - viewport->update(dirtyBoundingRect); + viewport->repaint(dirtyBoundingRect); else - viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); + viewport->repaint(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); } else { - viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. + viewport->repaint(dirtyRegion); // Already adjusted in updateRect/Region. } dirtyBoundingRect = QRect(); @@ -829,7 +829,7 @@ void QGraphicsViewPrivate::processPendingUpdates() void QGraphicsViewPrivate::updateAll() { Q_Q(QGraphicsView); - q->viewport()->update(); + q->viewport()->repaint(); fullUpdatePending = true; dirtyBoundingRect = QRect(); dirtyRegion = QRegion(); @@ -846,13 +846,13 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r) switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; - q->viewport()->update(); + q->viewport()->repaint(); break; case QGraphicsView::BoundingRectViewportUpdate: dirtyBoundingRect |= r.boundingRect(); if (dirtyBoundingRect.contains(q->viewport()->rect())) { fullUpdatePending = true; - q->viewport()->update(); + q->viewport()->repaint(); } break; case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE @@ -882,13 +882,13 @@ void QGraphicsViewPrivate::updateRect(const QRect &r) switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; - q->viewport()->update(); + q->viewport()->repaint(); break; case QGraphicsView::BoundingRectViewportUpdate: dirtyBoundingRect |= r; if (dirtyBoundingRect.contains(q->viewport()->rect())) { fullUpdatePending = true; - q->viewport()->update(); + q->viewport()->repaint(); } break; case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE -- cgit v0.12 From c714b0e5527377bf3189b15a3bea0063f8aecebf Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 16:47:08 +0200 Subject: Avoid recursive repaint by calling update() when there's a full scene update. --- src/gui/graphicsview/qgraphicsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index e205985..7f6fd5e 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -829,7 +829,7 @@ void QGraphicsViewPrivate::processPendingUpdates() void QGraphicsViewPrivate::updateAll() { Q_Q(QGraphicsView); - q->viewport()->repaint(); + q->viewport()->update(); fullUpdatePending = true; dirtyBoundingRect = QRect(); dirtyRegion = QRegion(); -- cgit v0.12 From 80321b092fa35eb398f3aaf6a549f20fc4a94624 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 09:23:04 +0200 Subject: Only repaint in QGraphicsViewPrivate::processPendingUpdates() Convert some repaint() calls back to updates(). This ensures that any updates triggered before this call are processed normally, while still keeping the synchronous repaint() call intact. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsview.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 7f6fd5e..2515069 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -846,13 +846,13 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r) switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; - q->viewport()->repaint(); + q->viewport()->update(); break; case QGraphicsView::BoundingRectViewportUpdate: dirtyBoundingRect |= r.boundingRect(); if (dirtyBoundingRect.contains(q->viewport()->rect())) { fullUpdatePending = true; - q->viewport()->repaint(); + q->viewport()->update(); } break; case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE @@ -882,13 +882,13 @@ void QGraphicsViewPrivate::updateRect(const QRect &r) switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; - q->viewport()->repaint(); + q->viewport()->update(); break; case QGraphicsView::BoundingRectViewportUpdate: dirtyBoundingRect |= r; if (dirtyBoundingRect.contains(q->viewport()->rect())) { fullUpdatePending = true; - q->viewport()->repaint(); + q->viewport()->update(); } break; case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE -- cgit v0.12 From bc3804458f29c8f13426ef53fcbacbf0877fc896 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 10:14:26 +0200 Subject: Fix QGraphicsScene::drawItems() to use the recursive path as well. This change also changes the direct painting path to be opt-in as a temporary testing measure to see what's broken when using the old code path. --- src/gui/graphicsview/qgraphicsscene.cpp | 130 +++++--------------------------- src/gui/graphicsview/qgraphicsscene_p.h | 2 +- src/gui/graphicsview/qgraphicsview.cpp | 56 +++----------- src/gui/graphicsview/qgraphicsview.h | 2 +- src/gui/graphicsview/qgraphicsview_p.h | 1 + 5 files changed, 34 insertions(+), 157 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 1d33361..30c7f97 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5048,6 +5048,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * const QTransform &viewTransform, const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, + QList *topLevelItems, qreal parentOpacity) { // Calculate opacity. @@ -5111,7 +5112,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } // Find and sort children. - QList &children = item ? item->d_ptr->children : topLevelItems; + QList &children = item ? item->d_ptr->children : (topLevelItems ? *topLevelItems : this->topLevelItems); if (!dontDrawChildren) { if (item && item->d_ptr->needSortChildren) { item->d_ptr->needSortChildren = 0; @@ -5123,7 +5124,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } // Draw children behind - int i; + int i = 0; if (!dontDrawChildren) { for (i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); @@ -5131,7 +5132,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * break; drawSubtreeRecursive(child, painter, transform, viewTransform, exposedRegion, widget, optimizationFlags, - opacity); + 0, opacity); } } @@ -5160,7 +5161,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (!dontDrawChildren) { for (; i < children.size(); ++i) { drawSubtreeRecursive(children.at(i), painter, transform, viewTransform, - exposedRegion, widget, optimizationFlags, opacity); + exposedRegion, widget, optimizationFlags, 0, opacity); } } @@ -5321,118 +5322,27 @@ void QGraphicsScene::drawItems(QPainter *painter, const QStyleOptionGraphicsItem options[], QWidget *widget) { Q_D(QGraphicsScene); - - // Detect if painter state protection is disabled. QTransform viewTransform = painter->worldTransform(); - QVarLengthArray childClippers; + Q_UNUSED(options); + // Draw each toplevel recursively. + QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; + QList topLevelItems; for (int i = 0; i < numItems; ++i) { - QGraphicsItem *item = items[i]; - if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - if (!childClippers.isEmpty()) { - // Item is not clipped to any ancestor: pop all current clippers. - for (int i = 0; i < childClippers.size(); ++i) - painter->restore(); - childClippers.clear(); - } - } else { - // Item is clipped to an ancestor, which may or may not be in our - // child clipper list. Let's start by finding the item's closest - // clipping ancestor. - QGraphicsItem *clipParent = item->parentItem(); - while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) - clipParent = clipParent->parentItem(); - - // Pop any in-between clippers. If the clipper is unknown, pop - // them all. ### QVarLengthArray::lastIndexOf(). - int index = -1; - for (int n = childClippers.size() - 1; n >= 0; --n) { - if (childClippers[n] == clipParent) { - index = n; - break; - } - } - if (index != -1) { - int toPop = childClippers.size() - index - 1; - if (toPop > 0) { - for (int i = 0; i < toPop; ++i) - painter->restore(); - childClippers.resize(index + 1); - } - } - - // Sanity check - if (!childClippers.isEmpty()) - Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent); - - // If the clipper list is empty at this point, but we're still - // clipped to an ancestor, then we need to build the clip chain - // ourselves. There is only one case that can produce this issue: - // This item is stacked behind an ancestor: - // ItemStacksBehindParent. - if (childClippers.isEmpty()) { - Q_ASSERT(clipParent != 0); - // Build a stack of clippers. - QVarLengthArray clippers; - QGraphicsItem *p = clipParent; - do { - if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) - clippers.append(p); - } while ((p = p->parentItem()) && (p->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)); - - // ### This code path can also use the itemTransform - // optimization, but it's hit very rarely. - for (int i = clippers.size() - 1; i >= 0; --i) { - QGraphicsItem *clipper = clippers[i]; - painter->setWorldTransform(clipper->deviceTransform(viewTransform), false); - - childClippers.append(clipper); - painter->save(); - painter->setClipPath(clipper->shape(), Qt::IntersectClip); - } - Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent); - } - } - - // Set up the painter transform - if (item->d_ptr->hasValidDeviceTransform) { - painter->setWorldTransform(item->d_ptr->deviceTransform); - item->d_ptr->hasValidDeviceTransform = 0; - } else { - painter->setWorldTransform(item->deviceTransform(viewTransform), false); - } - - // Save painter - bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape)); - if (saveState) - painter->save(); - - // Set local clip - if (item->flags() & QGraphicsItem::ItemClipsToShape) - painter->setClipPath(item->shape(), Qt::IntersectClip); - - // Setup opacity - painter->setOpacity(item->effectiveOpacity()); - - // Draw the item - d->drawItemHelper(item, painter, &options[i], widget, d->painterStateProtection); - const QRect paintedViewBoundingRect = painter->worldTransform().mapRect(options[i].rect).adjusted(-1, -1, 1, 1); - item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); - - if (saveState) - painter->restore(); - - if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape) { - // Clip descendents to this item's shape, and keep the painter - // saved. - childClippers.append(item); - painter->save(); - painter->setClipPath(item->shape(), Qt::IntersectClip); + QGraphicsItem *item = items[i]->topLevelItem(); + topLevelItems << item; + + if (!item->d_ptr->itemDiscovered) { + item->d_ptr->itemDiscovered = 1; + d->drawSubtreeRecursive(item, painter, viewTransform, viewTransform, + view->d_func()->exposedRegion, widget, + view->optimizationFlags()); } } - for (int i = 0; i < childClippers.size(); ++i) - painter->restore(); + // Reset discovery bits. + for (int i = 0; i < topLevelItems.size(); ++i) + topLevelItems.at(i)->d_ptr->itemDiscovered = 0; painter->setWorldTransform(viewTransform); } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 4facec3..2a036e3 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -257,7 +257,7 @@ public: void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, const QTransform &viewTransform, const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, - qreal parentOpacity = qreal(1.0)); + QList *topLevelItems = 0, qreal parentOpacity = qreal(1.0)); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); void processDirtyItemsRecursive(QGraphicsItem *item, const QTransform &); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2515069..8bafe50 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -//#define QGRAPHICSVIEW_DEBUG - static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50; static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < 2^9 @@ -3236,12 +3234,12 @@ void QGraphicsView::paintEvent(QPaintEvent *event) d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState); // Determine the exposed region - QRegion exposedRegion = event->region(); + d->exposedRegion = event->region(); if (!d->accelerateScrolling) - exposedRegion = viewport()->rect(); + d->exposedRegion = viewport()->rect(); else if (d->viewportUpdateMode == BoundingRectViewportUpdate) - exposedRegion = event->rect(); - QRectF exposedSceneRect = mapToScene(exposedRegion.boundingRect()).boundingRect(); + d->exposedRegion = event->rect(); + QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); // Set up the painter QPainter painter(viewport()); @@ -3258,16 +3256,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const QTransform viewTransform = viewportTransform(); painter.setTransform(viewTransform, true); -#ifdef QGRAPHICSVIEW_DEBUG - QTime stopWatch; - stopWatch.start(); - qDebug() << "QGraphicsView::paintEvent(" << exposedRegion << ')'; -#endif - - // Find all exposed items - bool allItems = false; - QList itemList = d->findItems(exposedRegion, &allItems); - + // Draw background if ((d->cacheMode & CacheBackground) #ifdef Q_WS_X11 && X11->use_xrender @@ -3309,18 +3298,14 @@ void QGraphicsView::paintEvent(QPaintEvent *event) painter.restore(); } -#ifdef QGRAPHICSVIEW_DEBUG - int backgroundTime = stopWatch.elapsed() - exposedTime; -#endif - - static int directEnv = qgetenv("QGRAPHICSVIEW_DIRECT").toInt(); - if (directEnv || (d->optimizationFlags & BypassDrawItems)) { - d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, exposedRegion, - viewport(), d->optimizationFlags); + // Items + if ((d->optimizationFlags & IndirectPainting)) { + d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, d->exposedRegion, + viewport(), d->optimizationFlags, 0); } else { // Find all exposed items bool allItems = false; - QList itemList = d->findItems(exposedRegion, &allItems); + QList itemList = d->findItems(d->exposedRegion, &allItems); if (!itemList.isEmpty()) { // Generate the style options. @@ -3328,24 +3313,16 @@ void QGraphicsView::paintEvent(QPaintEvent *event) QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); for (int i = 0; i < numItems; ++i) - itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, exposedRegion, allItems); + itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems); // Draw the items. drawItems(&painter, numItems, itemArray, styleOptionArray); d->freeStyleOptionsArray(styleOptionArray); } } -#ifdef QGRAPHICSVIEW_DEBUG - int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime; -#endif - // Foreground drawForeground(&painter, exposedSceneRect); -#ifdef QGRAPHICSVIEW_DEBUG - int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime; -#endif - #ifndef QT_NO_RUBBERBAND // Rubberband if (d->rubberBanding && !d->rubberBandRect.isEmpty()) { @@ -3367,17 +3344,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event) painter.end(); -#ifdef QGRAPHICSVIEW_DEBUG - qDebug() << "\tItem discovery....... " << exposedTime << "msecs (" << itemList.size() << "items," - << (exposedTime > 0 ? (itemList.size() * 1000.0 / exposedTime) : -1) << "/ sec )"; - qDebug() << "\tDrawing background... " << backgroundTime << "msecs (" << exposedRegion.numRects() << "segments )"; - qDebug() << "\tDrawing items........ " << itemsTime << "msecs (" - << (itemsTime > 0 ? (itemList.size() * 1000.0 / itemsTime) : -1) << "/ sec )"; - qDebug() << "\tDrawing foreground... " << foregroundTime << "msecs (" << exposedRegion.numRects() << "segments )"; - qDebug() << "\tTotal rendering time: " << stopWatch.elapsed() << "msecs (" - << (stopWatch.elapsed() > 0 ? (1000.0 / stopWatch.elapsed()) : -1.0) << "fps )"; -#endif - // Restore painter state protection. d->scene->d_func()->painterStateProtection = true; } diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h index deed1d0..b7a9906 100644 --- a/src/gui/graphicsview/qgraphicsview.h +++ b/src/gui/graphicsview/qgraphicsview.h @@ -113,7 +113,7 @@ public: DontClipPainter = 0x1, // obsolete DontSavePainterState = 0x2, DontAdjustForAntialiasing = 0x4, - BypassDrawItems = 0x8 + IndirectPainting = 0x8 }; Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag) diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 637687b..814e476 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -167,6 +167,7 @@ public: void updateRect(const QRect &rect); void updateRegion(const QRegion ®ion); bool updateSceneSlotReimplementedChecked; + QRegion exposedRegion; QList findItems(const QRegion &exposedRegion, bool *allItems) const; }; -- cgit v0.12 From 1fc2406f35594706a9aafa9374694cf0a65cee30 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 11:26:30 +0200 Subject: Refactor QTransform combining code, and mark all code that combines. This change introduces two helper functions in QGraphicsItemPrivate, that combine the item's transform into the current transform, effectively merging the code that calculates any item's combined to-parent transform. This makes the code more readable, and also makes it easier for us to reintroduce the componentized transform API in QGraphicsItem (which was previously reverted). --- src/gui/graphicsview/qgraphicsitem.cpp | 131 +++++++++++++++++++------------- src/gui/graphicsview/qgraphicsitem_p.h | 3 + src/gui/graphicsview/qgraphicsscene.cpp | 30 ++++---- src/gui/graphicsview/qgraphicsview.cpp | 3 +- 4 files changed, 98 insertions(+), 69 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 0b06613..e1389b5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -787,6 +787,49 @@ bool QGraphicsItemPrivate::itemIsUntransformable() const || (ancestorFlags & AncestorIgnoresTransformations); } + +/*! + \internal + + Combines this item's position and transform onto \a transform. + + If you need to change this function (e.g., adding more transformation + modes / options), make sure to change all places marked with COMBINE. +*/ +void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const +{ + // COMBINE + if (viewTransform && itemIsUntransformable()) { + *x = q_ptr->deviceTransform(*viewTransform); + } else { + if (transform) + *x *= *transform; + if (!pos.isNull()) + *x *= QTransform::fromTranslate(pos.x(), pos.y()); + } +} + +/*! + \internal + + Combines this item's position and transform onto \a transform. + + If you need to change this function (e.g., adding more transformation + modes / options), make sure to change QGraphicsItem::deviceTransform() as + well. +*/ +void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const +{ + // COMBINE + if (viewTransform && itemIsUntransformable()) { + *x = q_ptr->deviceTransform(*viewTransform); + } else { + x->translate(pos.x(), pos.y()); + if (transform) + *x = *transform * *x; + } +} + /*! \internal @@ -943,6 +986,7 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec QGraphicsItemPrivate *childd = child->d_ptr; bool hasPos = !childd->pos.isNull(); if (hasPos || childd->transform) { + // COMBINE QTransform matrix; if (childd->transform) matrix = *childd->transform; @@ -2667,11 +2711,7 @@ QTransform QGraphicsItem::sceneTransform() const QTransform m; const QGraphicsItem *p = this; do { - if (p->d_ptr->transform) - m *= *p->d_ptr->transform; - const QPointF &pos = p->d_ptr->pos; - if (!pos.isNull()) - m *= QTransform::fromTranslate(pos.x(), pos.y()); + p->d_ptr->combineTransformToParent(&m); } while ((p = p->d_ptr->parent)); return m; } @@ -2723,6 +2763,8 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c // First translate the base untransformable item. QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0)); + + // COMBINE QTransform matrix; matrix.translate(mappedPoint.x(), mappedPoint.y()); matrix = untransformedAncestor->transform() * matrix; @@ -2730,10 +2772,7 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c // Then transform and translate all children. for (int i = 0; i < parents.size(); ++i) { const QGraphicsItem *parent = parents.at(i); - QPointF pos = parent->pos(); - QTransform moveMatrix; - moveMatrix.translate(pos.x(), pos.y()); - matrix = (parent->transform() * moveMatrix) * matrix; + parent->d_ptr->combineTransformFromParent(&matrix); } return matrix; @@ -2776,34 +2815,29 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co if (parent == other) { if (ok) *ok = true; - const QPointF &itemPos = d_ptr->pos; - if (itemPos.isNull()) - return d_ptr->transform ? *d_ptr->transform : QTransform(); - if (d_ptr->transform) - return *d_ptr->transform * QTransform::fromTranslate(itemPos.x(), itemPos.y()); - return QTransform::fromTranslate(itemPos.x(), itemPos.y()); + QTransform x; + d_ptr->combineTransformFromParent(&x); + return x; } // This is other's parent if (otherParent == this) { const QPointF &otherPos = other->d_ptr->pos; if (other->d_ptr->transform) { - QTransform otherToParent = *other->d_ptr->transform; - if (!otherPos.isNull()) - otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y()); + QTransform otherToParent; + other->d_ptr->combineTransformFromParent(&otherToParent); return otherToParent.inverted(ok); - } else { - if (ok) - *ok = true; - return QTransform::fromTranslate(-otherPos.x(), -otherPos.y()); } + if (ok) + *ok = true; + return QTransform::fromTranslate(-otherPos.x(), -otherPos.y()); } // Siblings if (parent == otherParent) { + // COMBINE const QPointF &itemPos = d_ptr->pos; const QPointF &otherPos = other->d_ptr->pos; - if (!d_ptr->transform && !other->d_ptr->transform) { QPointF delta = itemPos - otherPos; if (ok) @@ -2811,14 +2845,10 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co return QTransform::fromTranslate(delta.x(), delta.y()); } - QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y()); - if (d_ptr->transform) - itemToParent = itemPos.isNull() ? *d_ptr->transform : *d_ptr->transform * itemToParent; - - QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y()); - if (other->d_ptr->transform) - otherToParent = otherPos.isNull() ? *other->d_ptr->transform : *other->d_ptr->transform * otherToParent; - + QTransform itemToParent; + d_ptr->combineTransformFromParent(&itemToParent); + QTransform otherToParent; + other->d_ptr->combineTransformFromParent(&otherToParent); return itemToParent * otherToParent.inverted(ok); } @@ -2854,11 +2884,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co QTransform x; const QGraphicsItem *p = child; do { - const QGraphicsItemPrivate *pd = p->d_ptr; - if (pd->transform) - x *= *pd->transform; - if (!pd->pos.isNull()) - x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y()); + p->d_ptr->combineTransformToParent(&x); } while ((p = p->d_ptr->parent) && p != root); if (parentOfOther) return x.inverted(ok); @@ -3206,6 +3232,7 @@ QRectF QGraphicsItem::childrenBoundingRect() const QRectF QGraphicsItem::sceneBoundingRect() const { // Find translate-only offset + // COMBINE QPointF offset; const QGraphicsItem *parentItem = this; const QGraphicsItemPrivate *itemd; @@ -3910,11 +3937,13 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n // Find closest clip ancestor and transform. Q_Q(QGraphicsItem); + // COMBINE QTransform thisToParentTransform = transform ? *transform * QTransform::fromTranslate(newPos.x(), newPos.y()) : QTransform::fromTranslate(newPos.x(), newPos.y()); QGraphicsItem *clipParent = parent; while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) { + // COMBINE if (clipParent->d_ptr->transform) thisToParentTransform *= *clipParent->d_ptr->transform; if (!clipParent->d_ptr->pos.isNull()) { @@ -4145,13 +4174,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) static const QLineF left(0, 0, -1, 0); static const QLineF right(0, 0, 1, 0); - QTransform deviceTr; - if (d->itemIsUntransformable()) { - deviceTr = deviceTransform(view->viewportTransform()); - } else { - deviceTr = sceneTransform() * view->viewportTransform(); - } - + QTransform deviceTr = deviceTransform(view->viewportTransform()); QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect(); QLineF v1 = deviceTr.map(right); QLineF v2 = deviceTr.map(down); @@ -4283,6 +4306,7 @@ QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point */ QPointF QGraphicsItem::mapToParent(const QPointF &point) const { + // COMBINE if (!d_ptr->transform) return point + d_ptr->pos; return d_ptr->transform->map(point) + d_ptr->pos; @@ -4350,6 +4374,7 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect */ QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const { + // COMBINE if (!d_ptr->transform) return rect.translated(d_ptr->pos); return d_ptr->transform->map(rect).translated(d_ptr->pos); @@ -4419,6 +4444,7 @@ QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rec */ QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const { + // COMBINE QRectF r = !d_ptr->transform ? rect : d_ptr->transform->mapRect(rect); return r.translated(d_ptr->pos); } @@ -4491,6 +4517,7 @@ QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &r */ QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const { + // COMBINE QRectF r = rect.translated(-d_ptr->pos); return d_ptr->transform ? d_ptr->transform->inverted().mapRect(r) : r; } @@ -4551,6 +4578,7 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &p */ QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const { + // COMBINE if (!d_ptr->transform) return polygon.translated(d_ptr->pos); return d_ptr->transform->map(polygon).translated(d_ptr->pos); @@ -4595,6 +4623,7 @@ QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterP */ QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const { + // COMBINE if (!d_ptr->transform) return path.translated(d_ptr->pos); return d_ptr->transform->map(path).translated(d_ptr->pos); @@ -4646,6 +4675,7 @@ QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &poi */ QPointF QGraphicsItem::mapFromParent(const QPointF &point) const { + // COMBINE if (d_ptr->transform) return d_ptr->transform->inverted().map(point - d_ptr->pos); return point - d_ptr->pos; @@ -4714,6 +4744,7 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &re */ QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const { + // COMBINE QRectF r = rect.translated(-d_ptr->pos); return d_ptr->transform ? d_ptr->transform->inverted().map(r) : r; } @@ -4770,6 +4801,7 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPolygonF */ QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const { + // COMBINE QPolygonF p = polygon; p.translate(-d_ptr->pos); return d_ptr->transform ? d_ptr->transform->inverted().map(p) : p; @@ -4812,6 +4844,7 @@ QPainterPath QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPainte */ QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const { + // COMBINE QPainterPath p(path); p.translate(-d_ptr->pos); return d_ptr->transform ? d_ptr->transform->inverted().map(p) : p; @@ -5540,21 +5573,13 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) if ((item->flags() & ItemIsMovable) && !QGraphicsItemPrivate::movableAncestorIsSelected(item)) { QPointF currentParentPos; QPointF buttonDownParentPos; - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations) { + if (item->d_ptr->itemIsUntransformable()) { // Items whose ancestors ignore transformations need to // map screen coordinates to local coordinates, then map // those to the parent. QTransform viewToItemTransform = (item->deviceTransform(view->viewportTransform())).inverted(); currentParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->screenPos())))); buttonDownParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton))))); - } else if (item->flags() & ItemIgnoresTransformations) { - // Root items that ignore transformations need to - // calculate their diff by mapping viewport coordinates - // directly to parent coordinates. - QTransform viewToParentTransform = (item->transform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y())) - * (item->sceneTransform() * view->viewportTransform()).inverted(); - currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos()))); - buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton)))); } else { // All other items simply map from the scene. currentParentPos = item->mapToParent(item->mapFromScene(event->scenePos())); @@ -8884,6 +8909,8 @@ void QGraphicsItemGroup::addToGroup(QGraphicsItem *item) return; } + // COMBINE + // ### Use itemTransform() instead. QTransform oldSceneMatrix = item->sceneTransform(); item->setPos(mapFromItem(item, 0, 0)); item->setParentItem(this); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 80b1fb4..7fe7d95 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -163,6 +163,9 @@ public: QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; bool itemIsUntransformable() const; + void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; + void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; + // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; static bool movableAncestorIsSelected(const QGraphicsItem *item); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 30c7f97..b1d1742 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5075,14 +5075,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QRect viewBoundingRect; if (item) { if (!item->d_ptr->hasValidDeviceTransform) { - if (item->d_ptr->itemIsUntransformable()) { - transform = item->deviceTransform(viewTransform); - } else { - const QPointF &pos = item->d_ptr->pos; - transform.translate(pos.x(), pos.y()); - if (item->d_ptr->transform) - transform = *item->d_ptr->transform * transform; - } + item->d_ptr->combineTransformFromParent(&transform, &viewTransform); } else { transform = item->d_ptr->deviceTransform; item->d_ptr->hasValidDeviceTransform = 0; @@ -5226,12 +5219,10 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, cons QTransform transform = parentTransform; if (item) { if (item->d_ptr->itemIsUntransformable()) { - transform = item->deviceTransform(views.at(0)->viewportTransform()); + QTransform x = views.at(0)->viewportTransform(); + item->d_ptr->combineTransformFromParent(&transform, &x); } else { - const QPointF &pos = item->d_ptr->pos; - transform.translate(pos.x(), pos.y()); - if (item->d_ptr->transform) - transform = *item->d_ptr->transform * transform; + item->d_ptr->combineTransformFromParent(&transform); } } @@ -5325,8 +5316,16 @@ void QGraphicsScene::drawItems(QPainter *painter, QTransform viewTransform = painter->worldTransform(); Q_UNUSED(options); - // Draw each toplevel recursively. + // Determine view, expose and flags. QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; + QRegion expose; + QGraphicsView::OptimizationFlags flags; + if (view) { + expose = view->d_func()->exposedRegion; + flags = view->optimizationFlags(); + } + + // Draw each toplevel recursively. QList topLevelItems; for (int i = 0; i < numItems; ++i) { QGraphicsItem *item = items[i]->topLevelItem(); @@ -5335,8 +5334,7 @@ void QGraphicsScene::drawItems(QPainter *painter, if (!item->d_ptr->itemDiscovered) { item->d_ptr->itemDiscovered = 1; d->drawSubtreeRecursive(item, painter, viewTransform, viewTransform, - view->d_func()->exposedRegion, widget, - view->optimizationFlags()); + expose, widget, flags); } } diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 8bafe50..d410a53 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -746,6 +746,7 @@ QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRect } // Translate-only + // COMBINE QPointF offset; const QGraphicsItem *parentItem = item; const QGraphicsItemPrivate *itemd; @@ -783,7 +784,7 @@ QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const Q const_cast(this)->updateScroll(); // Accurate bounding region - QTransform itv = item->sceneTransform() * q->viewportTransform(); + QTransform itv = item->deviceTransform(q->viewportTransform()); return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect(); } -- cgit v0.12 From 99318bd50bf044c8202f670b667dc990ce90cfe1 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 12:39:02 +0200 Subject: Fix sorting bug and ensure render functions work. Make direct default. Mark the children list for sorting when the Z value for items changes. Change the signature of the recursive draw function slightly so that the expose region is optional, and ensure we don't intersect with this region if it's not available. This change also flips the direct painting so that the default is to use the recursive approach. --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 24 +++++++++++------------- src/gui/graphicsview/qgraphicsscene_p.h | 2 +- src/gui/graphicsview/qgraphicsview.cpp | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index e1389b5..17cab45 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3151,6 +3151,7 @@ void QGraphicsItem::setZValue(qreal z) if (newZ == d_ptr->z) return; d_ptr->z = newZ; + d_ptr->needSortChildren = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b1d1742..fcb6352 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2522,7 +2522,6 @@ QList QGraphicsScene::items(const QPointF &pos) const return d->items_helper(pos); } - /*! \fn QList QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const @@ -5046,7 +5045,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, const QTransform &viewTransform, - const QRegion &exposedRegion, QWidget *widget, + QRegion *exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, QList *topLevelItems, qreal parentOpacity) @@ -5084,10 +5083,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (!brect.size().isNull()) { // ### This does not take the clip into account. _q_adjustRect(&brect); - const QRect paintedViewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); - item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); - viewBoundingRect = paintedViewBoundingRect & exposedRegion.boundingRect(); - } + viewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); + item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); + if (exposedRegion) + viewBoundingRect &= exposedRegion->boundingRect(); + } } bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); @@ -5132,7 +5132,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw item if (!dontDrawItem) { QStyleOptionGraphicsItem option; - item->d_ptr->initStyleOption(&option, transform, exposedRegion); + item->d_ptr->initStyleOption(&option, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); bool savePainter = clipsToShape || !(optimizationFlags & QGraphicsView::DontSavePainterState); @@ -5143,7 +5143,6 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - drawItemHelper(item, painter, &option, widget, false); if (savePainter) @@ -5318,20 +5317,19 @@ void QGraphicsScene::drawItems(QPainter *painter, // Determine view, expose and flags. QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; - QRegion expose; + QRegion *expose = 0; QGraphicsView::OptimizationFlags flags; if (view) { - expose = view->d_func()->exposedRegion; + expose = &view->d_func()->exposedRegion; flags = view->optimizationFlags(); } - // Draw each toplevel recursively. + // Find all toplevels, they are already sorted. QList topLevelItems; for (int i = 0; i < numItems; ++i) { QGraphicsItem *item = items[i]->topLevelItem(); - topLevelItems << item; - if (!item->d_ptr->itemDiscovered) { + topLevelItems << item; item->d_ptr->itemDiscovered = 1; d->drawSubtreeRecursive(item, painter, viewTransform, viewTransform, expose, widget, flags); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 2a036e3..2e82a4a 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -256,7 +256,7 @@ public: void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, const QTransform &viewTransform, - const QRegion &exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, + QRegion *exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, QList *topLevelItems = 0, qreal parentOpacity = qreal(1.0)); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index d410a53..caa3ffc 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3300,8 +3300,8 @@ void QGraphicsView::paintEvent(QPaintEvent *event) } // Items - if ((d->optimizationFlags & IndirectPainting)) { - d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, d->exposedRegion, + if (!(d->optimizationFlags & IndirectPainting)) { + d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, &d->exposedRegion, viewport(), d->optimizationFlags, 0); } else { // Find all exposed items -- cgit v0.12 From 1b78999dcd5512ce46e2fac20811ad63f3e93ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 2 Jun 2009 12:46:32 +0200 Subject: Graphics View cleanup: Remove iterative processing of dirty items. The recursive approach is faster and fits better into the new scene transform cache we'll do later. --- src/gui/graphicsview/qgraphicsitem_p.h | 13 ++--- src/gui/graphicsview/qgraphicsscene.cpp | 89 +++------------------------------ src/gui/graphicsview/qgraphicsscene_p.h | 14 ------ 3 files changed, 11 insertions(+), 105 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 7fe7d95..d962ad0 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -141,12 +141,11 @@ public: emptyClipPath(0), inSetPosHelper(0), needSortChildren(1), + allChildrenDirty(0), + fullUpdatePending(0), flags(0), dirtyChildrenBoundingRect(1), - inDirtyList(0), paintedViewBoundingRectsNeedRepaint(0), - allChildrenDirty(0), - fullUpdatePending(0), hasValidDeviceTransform(0), globalStackingOrder(-1), q_ptr(0) @@ -342,17 +341,15 @@ public: quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; quint32 needSortChildren : 1; - quint32 unused : 2; + quint32 allChildrenDirty : 1; + quint32 fullUpdatePending : 1; // New 32 bits quint32 flags : 11; quint32 dirtyChildrenBoundingRect : 1; - quint32 inDirtyList : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 allChildrenDirty : 1; - quint32 fullUpdatePending : 1; quint32 hasValidDeviceTransform : 1; - quint32 padding : 15; // feel free to use + quint32 padding : 18; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index fcb6352..eac057e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -614,11 +614,6 @@ void QGraphicsScenePrivate::_q_emitUpdated() } } - // Ensure all dirty items's current positions are recorded in the list of - // updated rects. - for (int i = 0; i < dirtyItems.size(); ++i) - updatedRects += dirtyItems.at(i)->sceneBoundingRect(); - // Notify the changes to anybody interested. QList oldUpdatedRects; oldUpdatedRects = updateAll ? (QList() << q->sceneRect()) : updatedRects; @@ -678,74 +673,12 @@ void QGraphicsScenePrivate::_q_polishItems() void QGraphicsScenePrivate::_q_processDirtyItems() { - static int useDirtyListEnv = qgetenv("QT_GV_USE_DIRTY_LIST").toInt(); processDirtyItemsEmitted = false; - if (updateAll) { - if (useDirtyListEnv) { - for (int i = 0; i < dirtyItems.size(); ++i) - resetDirtyItem(dirtyItems.at(i)); - dirtyItems.clear(); - } - return; - } - - if (!useDirtyListEnv) { - processDirtyItemsRecursive(0, views.at(0)->viewportTransform()); - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->processPendingUpdates(); + if (updateAll) return; - } - - for (int i = 0; i < dirtyItems.size(); ++i) { - QGraphicsItem *item = dirtyItems.at(i); - QGraphicsView *view = views.at(0); - QGraphicsViewPrivate *viewPrivate = view->d_func(); - const QTransform deviceTransform = item->deviceTransform(view->viewportTransform()); - QRectF dirtyRect = adjustedItemBoundingRect(item); - if (!item->d_ptr->fullUpdatePending) { - _q_adjustRect(&item->d_ptr->needsRepaint); - dirtyRect &= item->d_ptr->needsRepaint; - } - - if (item->d_ptr->allChildrenDirty && !item->d_ptr->children.isEmpty() - && !item->d_ptr->childrenClippedToShape()) { - QRectF childrenBounds = item->childrenBoundingRect(); - _q_adjustRect(&childrenBounds); - dirtyRect |= childrenBounds; - } - - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) - viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); - - bool dirtyRectOutsideViewport = false; - if (item->d_ptr->hasBoundingRegionGranularity) { - const QRegion dirtyViewRegion = deviceTransform.map(QRegion(dirtyRect.toRect())) - & viewPrivate->viewport->rect(); - if (!dirtyViewRegion.isEmpty()) - viewPrivate->updateRegion(dirtyViewRegion); - else - dirtyRectOutsideViewport = true; - } else { - const QRect dirtyViewRect = deviceTransform.mapRect(dirtyRect).toRect() - & viewPrivate->viewport->rect(); - if (!dirtyViewRect.isEmpty()) - viewPrivate->updateRect(dirtyViewRect); - else - dirtyRectOutsideViewport = true; - } - if (!dirtyRectOutsideViewport) { - // We know for sure this item will be process in the paint event, hence - // store its device transform and re-use it when drawing. - item->d_ptr->hasValidDeviceTransform = 1; - item->d_ptr->deviceTransform = deviceTransform; - } - - resetDirtyItem(item); - } - - dirtyItems.clear(); + processDirtyItemsRecursive(0, views.at(0)->viewportTransform()); for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); } @@ -808,7 +741,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) hoverItems.removeAll(item); cachedItemsUnderMouse.removeAll(item); unpolishedItems.removeAll(item); - removeFromDirtyItems(item); //We remove all references of item from the sceneEventFilter arrays QMultiMap::iterator iterator = sceneEventFilters.begin(); @@ -3347,7 +3279,6 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->pendingUpdateItems.removeAll(item); d->cachedItemsUnderMouse.removeAll(item); d->unpolishedItems.removeAll(item); - d->removeFromDirtyItems(item); //We remove all references of item from the sceneEventFilter arrays QMultiMap::iterator iterator = d->sceneEventFilters.begin(); @@ -5195,18 +5126,10 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b item->d_ptr->dirtyChildren = 1; } - static int useDirtyListEnv = qgetenv("QT_GV_USE_DIRTY_LIST").toInt(); - if (useDirtyListEnv) { - if (!item->d_ptr->inDirtyList) { - dirtyItems.append(item); - item->d_ptr->inDirtyList = 1; - } - } else { - QGraphicsItem *p = item->d_ptr->parent; - while (p && !p->d_ptr->dirtyChildren) { - p->d_ptr->dirtyChildren = 1; - p = p->d_ptr->parent; - } + QGraphicsItem *p = item->d_ptr->parent; + while (p && !p->d_ptr->dirtyChildren) { + p->d_ptr->dirtyChildren = 1; + p = p->d_ptr->parent; } } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 2e82a4a..9e9ef6b 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -112,7 +112,6 @@ public: QSet selectedItems; QList unindexedItems; QList indexedItems; - QVector dirtyItems; QList pendingUpdateItems; QList unpolishedItems; QList topLevelItems; @@ -268,24 +267,11 @@ public: item->d_ptr->dirty = 0; item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; item->d_ptr->dirtyChildren = 0; - item->d_ptr->inDirtyList = 0; item->d_ptr->needsRepaint = QRectF(); item->d_ptr->allChildrenDirty = 0; item->d_ptr->fullUpdatePending = 0; } - inline void removeFromDirtyItems(QGraphicsItem *item) - { - int i = 0; - while (i < dirtyItems.size()) { - if (dirtyItems.at(i) == item) - dirtyItems.remove(i); - else - ++i; - } - resetDirtyItem(item); - } - QStyle *style; QFont font; void setFont_helper(const QFont &font); -- cgit v0.12 From d44332954b2a8e66ba4129c230e8ccc65fd972ea Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 13:50:28 +0200 Subject: Don't construct new style option objects in a tight loop. The QStyleOption constructor is expensive, as it allocates a QFont, a QPalette and a QFontMetrics. By simply reusing a temporary style option object instead we carve away wasted cycles. Reviewed-by: Ariya --- src/gui/graphicsview/qgraphicsscene.cpp | 17 ++++++++--------- src/gui/graphicsview/qgraphicsscene_p.h | 3 +++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index eac057e..0c679de 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4763,7 +4763,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte // Generate the item's exposedRect and map its list of expose // rects to device coordinates. - QStyleOptionGraphicsItem cacheOption = *option; + styleOptionTmp = *option; QRegion pixmapExposed; QRectF exposedRect; if (!itemCache->allExposed) { @@ -4775,11 +4775,11 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } else { exposedRect = brect; } - cacheOption.exposedRect = exposedRect; + styleOptionTmp.exposedRect = exposedRect; // Render. _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(), - &cacheOption, painterStateProtection); + &styleOptionTmp, painterStateProtection); // insert this pixmap into the cache. itemCache->key = QPixmapCache::insert(pix); @@ -4940,12 +4940,12 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte foreach (QRect r, scrollExposure.rects()) br |= pixmapToItem.mapRect(r); } - QStyleOptionGraphicsItem cacheOption = *option; - cacheOption.exposedRect = br.adjusted(-1, -1, 1, 1); + styleOptionTmp = *option; + styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1); // Render the exposed areas. _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(), - &cacheOption, painterStateProtection); + &styleOptionTmp, painterStateProtection); // Reset expose data. pixModified = true; @@ -5062,8 +5062,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw item if (!dontDrawItem) { - QStyleOptionGraphicsItem option; - item->d_ptr->initStyleOption(&option, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); + item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); bool savePainter = clipsToShape || !(optimizationFlags & QGraphicsView::DontSavePainterState); @@ -5074,7 +5073,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - drawItemHelper(item, painter, &option, widget, false); + drawItemHelper(item, painter, &styleOptionTmp, widget, false); if (savePainter) painter->restore(); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 9e9ef6b..d74591c 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -69,6 +69,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -281,6 +282,8 @@ public: void setPalette_helper(const QPalette &palette); void resolvePalette(); void updatePalette(const QPalette &palette); + + QStyleOptionGraphicsItem styleOptionTmp; }; QT_END_NAMESPACE -- cgit v0.12 From 6f218ce216021ff2e8ecf828b2f29b1b9d82b401 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 14:00:03 +0200 Subject: Microoptimize: make this function inline. Also change the order of comparisons, as the transformable flags are most likely to fail first. --- src/gui/graphicsview/qgraphicsitem.cpp | 16 ++-------------- src/gui/graphicsview/qgraphicsitem_p.h | 6 +++++- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 17cab45..ca39713 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -779,18 +779,6 @@ QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos, /*! \internal - Returns true if this item or any of its ancestors are untransformable. -*/ -bool QGraphicsItemPrivate::itemIsUntransformable() const -{ - return (flags & QGraphicsItem::ItemIgnoresTransformations) - || (ancestorFlags & AncestorIgnoresTransformations); -} - - -/*! - \internal - Combines this item's position and transform onto \a transform. If you need to change this function (e.g., adding more transformation @@ -799,7 +787,7 @@ bool QGraphicsItemPrivate::itemIsUntransformable() const void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const { // COMBINE - if (viewTransform && itemIsUntransformable()) { + if (itemIsUntransformable() && viewTransform) { *x = q_ptr->deviceTransform(*viewTransform); } else { if (transform) @@ -821,7 +809,7 @@ void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransf void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const { // COMBINE - if (viewTransform && itemIsUntransformable()) { + if (itemIsUntransformable() && viewTransform) { *x = q_ptr->deviceTransform(*viewTransform); } else { x->translate(pos.x(), pos.y()); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index d962ad0..61f6496 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -160,7 +160,11 @@ public: void setIsMemberOfGroup(bool enabled); void remapItemPos(QEvent *event, QGraphicsItem *item); QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; - bool itemIsUntransformable() const; + inline bool itemIsUntransformable() const + { + return (flags & QGraphicsItem::ItemIgnoresTransformations) + || (ancestorFlags & AncestorIgnoresTransformations); + } void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; -- cgit v0.12 From fe640c1245075cabdafa88a16bdd33f9b49452c0 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 16:07:51 +0200 Subject: A faster item discovery function for rectangles (recursive). This function works much faster than the last one, but still it can be much faster. The main expense right now it seems is the transform calculations, and the item->collidesWithPath call. There's still much to gain here. This function does not make use of the BSP tree's fast lookup so it makes lookups slower in (e.g.) the chip demo. --- src/gui/graphicsview/qgraphicsscene.cpp | 110 +++++++++++++++++++++++++++++++- src/gui/graphicsview/qgraphicsscene_p.h | 4 ++ 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0c679de..963c615 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -250,6 +250,8 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; QT_BEGIN_NAMESPACE +static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2); + static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) { qreal xp = s.left(); @@ -1372,6 +1374,110 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } +void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect, + QList *items, + const QTransform &parentTransform, + const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, + qreal parentOpacity) const +{ + // Calculate opacity. + qreal opacity; + if (item) { + if (!item->d_ptr->visible) + return; + QGraphicsItem *p = item->d_ptr->parent; + bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; + bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); + if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { + opacity = parentOpacity * item->opacity(); + } else { + opacity = item->d_ptr->opacity; + } + if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + return; + } else { + opacity = parentOpacity; + } + + // Calculate the full transform for this item. + QTransform transform = parentTransform; + bool keep = false; + if (item) { + item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + + QRectF brect = item->boundingRect(); + if (!brect.size().isNull()) { + // ### This does not take the clip into account. + _q_adjustRect(&brect); + + keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)); + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = item->collidesWithPath(transform.inverted().map(rectPath)); + } + } + } + + bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); + bool dontProcessItem = !item || !keep; + bool dontProcessChildren = item && dontProcessItem && childClip; + childClip &= !dontProcessChildren & !children.isEmpty(); + + // Clip. + if (childClip) + rect &= transform.map(item->shape()).controlPointRect(); + + // Find and sort children. + QList &children = item ? item->d_ptr->children : const_cast(this)->topLevelItems; + if (!dontProcessChildren) { + if (item && item->d_ptr->needSortChildren) { + item->d_ptr->needSortChildren = 0; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } else if (!item && needSortTopLevelItems) { + const_cast(this)->needSortTopLevelItems = false; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } + } + + // Process children behind + int i = 0; + if (!dontProcessChildren) { + for (i = 0; i < children.size(); ++i) { + QGraphicsItem *child = children.at(i); + if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) + break; + recursive_items_helper(child, rect, items, transform, viewTransform, + mode, order, opacity); + } + } + + // Process item + if (!dontProcessItem) + items->append(item); + + // Process children in front + if (!dontProcessChildren) { + for (; i < children.size(); ++i) + recursive_items_helper(children.at(i), rect, items, transform, viewTransform, + mode, order, opacity); + } + + if (!item && order == Qt::AscendingOrder) { + int n = items->size(); + for (int i = 0; i < n / 2; ++i) { + QGraphicsItem *tmp = (*items)[n - i - 1]; + (*items)[n - i - 1] = (*items)[i]; + (*items)[i] = tmp; + } + } +} QList QGraphicsScenePrivate::items_helper(const QPointF &pos) const { @@ -2470,7 +2576,9 @@ QList QGraphicsScene::items(const QPointF &pos) const QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->items_helper(rect, mode, Qt::AscendingOrder); + QList itemList; + d->recursive_items_helper(0, rect, &itemList, QTransform(), QTransform(), mode, Qt::AscendingOrder); + return itemList; } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index d74591c..6b4476c 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -204,6 +204,10 @@ public: void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; + void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList *items, + const QTransform &parentTransform, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; + QList items_helper(const QPointF &pos) const; QList items_helper(const QRectF &rect, Qt::ItemSelectionMode mode, -- cgit v0.12 From de776b777bd9c1884bda4049d8f75020d6092ab7 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 2 Jun 2009 17:27:22 +0200 Subject: Remove crash, remove item from pending updates when deleted. This caused a crash in the contacts demo. --- src/gui/graphicsview/qgraphicsscene.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 963c615..73d6a93 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -743,6 +743,7 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) hoverItems.removeAll(item); cachedItemsUnderMouse.removeAll(item); unpolishedItems.removeAll(item); + pendingUpdateItems.removeAll(item); //We remove all references of item from the sceneEventFilter arrays QMultiMap::iterator iterator = sceneEventFilters.begin(); -- cgit v0.12 From bdb0c0fc98fc1998f6a7ee21be29513534be3713 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 2 Jun 2009 20:25:49 +0200 Subject: Optimise effectiveOpacity and make it inlineable. This cut's off some cycles in discardUpdateRequest() which is called from most places when something in the items changes. --- src/gui/graphicsview/qgraphicsitem.cpp | 16 +--------------- src/gui/graphicsview/qgraphicsitem_p.h | 26 +++++++++++++++++++++++++- src/gui/graphicsview/qgraphicsscene.cpp | 4 ++-- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index ca39713..b913d89 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2028,21 +2028,7 @@ qreal QGraphicsItem::opacity() const */ qreal QGraphicsItem::effectiveOpacity() const { - if (!d_ptr->parent) - return d_ptr->opacity; - - int myFlags = d_ptr->flags; - int parentFlags = d_ptr->parent ? d_ptr->parent->d_ptr->flags : 0; - - // If I have a parent, and I don't ignore my parent's opacity, and my - // parent propagates to me, then combine my local opacity with my parent's - // effective opacity into my effective opacity. - if (!(myFlags & QGraphicsItem::ItemIgnoresParentOpacity) - && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { - return d_ptr->opacity * d_ptr->parent->effectiveOpacity(); - } - - return d_ptr->opacity; + return d_ptr->effectiveOpacity(); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 61f6496..d92d76e 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -277,7 +277,31 @@ public: void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); inline bool isFullyTransparent() const - { return q_func()->effectiveOpacity() < .001; } + { return effectiveOpacity() < .001; } + + inline qreal effectiveOpacity() const { + if (!parent) + return opacity; + + qreal o = opacity; + QGraphicsItem *p = parent; + int myFlags = flags; + while (p) { + int parentFlags = p->d_ptr->flags; + + // If I have a parent, and I don't ignore my parent's opacity, and my + // parent propagates to me, then combine my local opacity with my parent's + // effective opacity into my effective opacity. + if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity) + || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + break; + + o *= parent->d_ptr->opacity; + p = p->d_ptr->parent; + myFlags = parentFlags; + } + return o; + } inline bool childrenCombineOpacity() const { diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 73d6a93..25ac279 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -419,7 +419,7 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & if (QGraphicsItem *item = unindexedItems.at(i)) { if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) + if (item->d_ptr->visible && !item->d_ptr->isFullyTransparent()) itemsInRect << item; } } @@ -427,7 +427,7 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & if (QGraphicsItem *item = indexedItems.at(i)) { if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) + if (item->d_ptr->visible && item->d_ptr->isFullyTransparent()) itemsInRect << item; } } -- cgit v0.12 From 07dca7a30d4bd1efd8032915700420cca3fd60fa Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 2 Jun 2009 21:02:42 +0200 Subject: implement equality operator in a more sane way Using qFuzzyCompare for checking whether two transformations are equal doesn't give us too much and is inconsistent with our other matrix classes. Using simple floating point equality is a lot faster as well. --- src/gui/painting/qtransform.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 86e594c..bd2ea31 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -700,11 +700,15 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) */ bool QTransform::operator==(const QTransform &o) const { -#define qFZ qFuzzyCompare - return qFZ(affine._m11, o.affine._m11) && qFZ(affine._m12, o.affine._m12) && qFZ(m_13, o.m_13) - && qFZ(affine._m21, o.affine._m21) && qFZ(affine._m22, o.affine._m22) && qFZ(m_23, o.m_23) - && qFZ(affine._dx, o.affine._dx) && qFZ(affine._dy, o.affine._dy) && qFZ(m_33, o.m_33); -#undef qFZ + return affine._m11 == o.affine._m11 && + affine._m12 == o.affine._m12 && + affine._m21 == o.affine._m21 && + affine._m22 == o.affine._m22 && + affine._dx == o.affine._dx && + affine._dy == o.affine._dy && + m_13 == o.m_13 && + m_23 == o.m_23 && + m_33 == o.m_33; } /*! -- cgit v0.12 From e5b83ec3dc4e2f4c18b67d45a5699da5a3f05f10 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 2 Jun 2009 22:05:01 +0200 Subject: optimise isFullyTransparent() This cuts down quite some intructions in some use cases, making esp. discardUpdateRequest() a bit cheaper. --- src/gui/graphicsview/qgraphicsitem_p.h | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index d92d76e..d007f03 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -276,13 +276,8 @@ public: void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); - inline bool isFullyTransparent() const - { return effectiveOpacity() < .001; } - - inline qreal effectiveOpacity() const { - if (!parent) - return opacity; - + inline qreal calcEffectiveOpacity() const + { qreal o = opacity; QGraphicsItem *p = parent; int myFlags = flags; @@ -303,6 +298,23 @@ public: return o; } + inline bool isFullyTransparent() const + { + if (opacity < 0.001) + return true; + if (!parent) + return false; + + return calcEffectiveOpacity() < 0.001; + } + + inline qreal effectiveOpacity() const { + if (!parent || !opacity) + return opacity; + + return calcEffectiveOpacity(); + } + inline bool childrenCombineOpacity() const { if (!children.size()) -- cgit v0.12 From 6887a89b0e0ee7a0eaff2adc34ae71ab01e2ba2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 2 Jun 2009 13:53:01 +0200 Subject: Generalize QGrahicsScenePrivate::processDirtyItemsRecursive. Add back compatibility support and make it independent of the views. Also store the sceneTransform instead of the deviceTransform. This will later be the item's cached scene transform (coming in another commit). --- src/gui/graphicsview/qgraphicsitem_p.h | 6 +- src/gui/graphicsview/qgraphicsscene.cpp | 99 ++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index d007f03..0e0a121 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -146,7 +146,7 @@ public: flags(0), dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), - hasValidDeviceTransform(0), + hasValidSceneTransform(0), globalStackingOrder(-1), q_ptr(0) { @@ -353,7 +353,7 @@ public: QGraphicsItem *parent; QList children; QTransform *transform; - QTransform deviceTransform; + QTransform sceneTransform; int index; int depth; @@ -388,7 +388,7 @@ public: quint32 flags : 11; quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 hasValidDeviceTransform : 1; + quint32 hasValidSceneTransform : 1; quint32 padding : 18; // feel free to use // Optional stacking order diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 25ac279..34c7dc1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -680,7 +680,7 @@ void QGraphicsScenePrivate::_q_processDirtyItems() if (updateAll) return; - processDirtyItemsRecursive(0, views.at(0)->viewportTransform()); + processDirtyItemsRecursive(0, QTransform()); for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); } @@ -5113,12 +5113,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QTransform transform = parentTransform; QRect viewBoundingRect; if (item) { - if (!item->d_ptr->hasValidDeviceTransform) { - item->d_ptr->combineTransformFromParent(&transform, &viewTransform); - } else { - transform = item->d_ptr->deviceTransform; - item->d_ptr->hasValidDeviceTransform = 0; - } + item->d_ptr->combineTransformFromParent(&transform, &viewTransform); QRectF brect = item->boundingRect(); if (!brect.size().isNull()) { // ### This does not take the clip into account. @@ -5244,51 +5239,67 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, const QTransform &parentTransform) { Q_ASSERT(!item || item->d_ptr->dirty || item->d_ptr->dirtyChildren); + Q_Q(QGraphicsScene); - // Calculate the full transform for this item. + // Calculate the full scene transform for this item. QTransform transform = parentTransform; - if (item) { - if (item->d_ptr->itemIsUntransformable()) { - QTransform x = views.at(0)->viewportTransform(); - item->d_ptr->combineTransformFromParent(&transform, &x); - } else { - item->d_ptr->combineTransformFromParent(&transform); - } + if (item && !item->d_ptr->itemIsUntransformable()) { + item->d_ptr->combineTransformFromParent(&transform); + item->d_ptr->sceneTransform = transform; + item->d_ptr->hasValidSceneTransform = 1; } // Process item. if (item && item->d_ptr->dirty) { - QRectF dirtyRect = adjustedItemBoundingRect(item); - if (!item->d_ptr->fullUpdatePending) { - _q_adjustRect(&item->d_ptr->needsRepaint); - dirtyRect &= item->d_ptr->needsRepaint; - } + const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); + if (useCompatUpdate && !item->d_ptr->itemIsUntransformable() + && qFuzzyIsNull(item->boundingRegionGranularity())) { + // This block of code is kept for compatibility. Since 4.5, by default + // QGraphicsView does not connect the signal and we use the below + // method of delivering updates. + q->update(item->sceneBoundingRect()); + } else { + QRectF dirtyRect; + bool uninitializedDirtyRect = true; + + for (int j = 0; j < views.size(); ++j) { + QGraphicsView *view = views.at(j); + QGraphicsViewPrivate *viewPrivate = view->d_func(); + if (viewPrivate->fullUpdatePending) + continue; + switch (viewPrivate->viewportUpdateMode) { + case QGraphicsView::NoViewportUpdate: + continue; + case QGraphicsView::FullViewportUpdate: + view->viewport()->update(); + viewPrivate->fullUpdatePending = 1; + continue; + default: + break; + } - QGraphicsViewPrivate *viewPrivate = views.at(0)->d_func(); - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) - viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + if (uninitializedDirtyRect) { + dirtyRect = adjustedItemBoundingRect(item); + if (!item->d_ptr->fullUpdatePending) { + _q_adjustRect(&item->d_ptr->needsRepaint); + dirtyRect &= item->d_ptr->needsRepaint; + uninitializedDirtyRect = false; + } + } - bool dirtyRectOutsideViewport = false; - if (item->d_ptr->hasBoundingRegionGranularity) { - const QRegion dirtyViewRegion = transform.map(QRegion(dirtyRect.toRect())) - & viewPrivate->viewport->rect(); - if (!dirtyViewRegion.isEmpty()) - viewPrivate->updateRegion(dirtyViewRegion); - else - dirtyRectOutsideViewport = true; - } else { - const QRect dirtyViewRect = transform.mapRect(dirtyRect).toRect() - & viewPrivate->viewport->rect(); - if (!dirtyViewRect.isEmpty()) - viewPrivate->updateRect(dirtyViewRect); - else - dirtyRectOutsideViewport = true; - } - if (!dirtyRectOutsideViewport) { - // We know for sure this item will be process in the paint event, hence - // store its device transform and re-use it when drawing. - item->d_ptr->hasValidDeviceTransform = 1; - item->d_ptr->deviceTransform = transform; + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) + viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + + if (item->d_ptr->hasBoundingRegionGranularity) { + const QRegion dirtyViewRegion = item->deviceTransform(view->viewportTransform()) + .map(QRegion(dirtyRect.toRect())); + viewPrivate->updateRegion(dirtyViewRegion); + } else { + const QRect dirtyViewRect = item->deviceTransform(view->viewportTransform()) + .mapRect(dirtyRect).toRect(); + viewPrivate->updateRect(dirtyViewRect); + } + } } } -- cgit v0.12 From 95949e7ef88eb14b7b22b06d235603f8581f6aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 2 Jun 2009 18:53:42 +0200 Subject: Cache QGrahicsItem's scene transform. Invalidating the scene transform is just a matter of setting a bit on the item. Then, when we ask for the item's scene transform, we traverse its ancestors recursively and find the top-most dirty item. The algorithm then backtracks to that item and start calculating the scene transform for the item itself and all its children in the call stack. If the item itself and all its ancestors are "clean", nothing is calculated, only traversed. We use this approach when processing dirty items / drawing items as well. That way we ensure the scene transform is only calculated once when absolutely needed. G'night :) --- src/gui/graphicsview/qgraphicsitem.cpp | 50 ++++++++++++++++++--- src/gui/graphicsview/qgraphicsitem_p.h | 11 ++++- src/gui/graphicsview/qgraphicsscene.cpp | 80 ++++++++++++++++++++++----------- src/gui/graphicsview/qgraphicsscene_p.h | 5 +-- src/gui/graphicsview/qgraphicsview.cpp | 2 +- 5 files changed, 109 insertions(+), 39 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b913d89..57ca2ef 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -952,6 +952,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de // Resolve depth. resolveDepth(parent ? parent->d_ptr->depth : -1); + dirtySceneTransform = 1; // Deliver post-change notification q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); @@ -2540,6 +2541,7 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) if (scene) q->prepareGeometryChange(); this->pos = newPos; + dirtySceneTransform = 1; // Send post-notification. #ifndef QGRAPHICSITEM_NO_ITEMCHANGE @@ -2682,12 +2684,17 @@ QMatrix QGraphicsItem::sceneMatrix() const */ QTransform QGraphicsItem::sceneTransform() const { - QTransform m; - const QGraphicsItem *p = this; - do { - p->d_ptr->combineTransformToParent(&m); - } while ((p = p->d_ptr->parent)); - return m; + if (d_ptr->dirtySceneTransform) { + // This item and all its descendants have dirty scene transforms. + // We're about to validate this item's scene transform, so we have to + // invalidate all the children; otherwise there's no way for the descendants + // to detect that the ancestor has changed. + d_ptr->invalidateChildrenSceneTransform(); + } + + QGraphicsItem *that = const_cast(this); + d_ptr->ensureSceneTransformRecursive(&that); + return d_ptr->sceneTransform; } /*! @@ -2899,6 +2906,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); *d_ptr->transform = newTransform; + d_ptr->dirtySceneTransform = 1; // Send post-notification. #ifndef QGRAPHICSITEM_NO_ITEMCHANGE @@ -2945,6 +2953,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Update and set the new transformation. prepareGeometryChange(); *d_ptr->transform = newTransform; + d_ptr->dirtySceneTransform = 1; // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -3966,6 +3975,35 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n } } +// Traverses all the ancestors up to the top-level and updates the pointer to +// always point to the top-most item that has a dirty scene transform. +// It then backtracks to the top-most dirty item and start calculating the +// scene transform by combining the item's transform (+pos) with the parent's +// cached scene transform (which we at this point know for sure is valid). +void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem) +{ + Q_ASSERT(topMostDirtyItem); + + if (dirtySceneTransform) + *topMostDirtyItem = q_ptr; + + if (parent) + parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem); + + if (*topMostDirtyItem == q_ptr) { + if (!dirtySceneTransform) + return; // OK, neither my ancestors nor I have dirty scene transforms. + *topMostDirtyItem = 0; + } else if (*topMostDirtyItem) { + return; // Continue backtrack. + } + + // COMBINE my transform with the parent's scene transform. + sceneTransform = parent ? parent->d_ptr->sceneTransform : QTransform(); + combineTransformFromParent(&sceneTransform); + dirtySceneTransform = 0; +} + /*! \internal diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 0e0a121..f9d63fb 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -146,7 +146,7 @@ public: flags(0), dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), - hasValidSceneTransform(0), + dirtySceneTransform(1), globalStackingOrder(-1), q_ptr(0) { @@ -275,6 +275,13 @@ public: void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); + void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem); + + inline void invalidateChildrenSceneTransform() + { + for (int i = 0; i < children.size(); ++i) + children.at(i)->d_ptr->dirtySceneTransform = 1; + } inline qreal calcEffectiveOpacity() const { @@ -388,7 +395,7 @@ public: quint32 flags : 11; quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 hasValidSceneTransform : 1; + quint32 dirtySceneTransform : 1; quint32 padding : 18; // feel free to use // Optional stacking order diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 34c7dc1..2773bdd 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -680,7 +680,7 @@ void QGraphicsScenePrivate::_q_processDirtyItems() if (updateAll) return; - processDirtyItemsRecursive(0, QTransform()); + processDirtyItemsRecursive(0); for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); } @@ -5083,7 +5083,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } } -void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, +void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, QRegion *exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, @@ -5110,10 +5110,24 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } // Calculate the full transform for this item. - QTransform transform = parentTransform; + QTransform transform; QRect viewBoundingRect; + bool wasDirtyParentSceneTransform = false; if (item) { - item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + if (item->d_ptr->itemIsUntransformable()) { + transform = item->deviceTransform(viewTransform); + } else { + if (item->d_ptr->dirtySceneTransform) { + item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform + : transform; + item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); + item->d_ptr->dirtySceneTransform = 0; + wasDirtyParentSceneTransform = true; + } + transform = item->d_ptr->sceneTransform; + transform *= viewTransform; + } + QRectF brect = item->boundingRect(); if (!brect.size().isNull()) { // ### This does not take the clip into account. @@ -5156,11 +5170,12 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (!dontDrawChildren) { for (i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); + if (wasDirtyParentSceneTransform) + child->d_ptr->dirtySceneTransform = 1; if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; - drawSubtreeRecursive(child, painter, transform, viewTransform, - exposedRegion, widget, optimizationFlags, - 0, opacity); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, + optimizationFlags, 0, opacity); } } @@ -5186,9 +5201,14 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw children in front if (!dontDrawChildren) { for (; i < children.size(); ++i) { - drawSubtreeRecursive(children.at(i), painter, transform, viewTransform, - exposedRegion, widget, optimizationFlags, 0, opacity); + QGraphicsItem *child = children.at(i); + if (wasDirtyParentSceneTransform) + child->d_ptr->dirtySceneTransform = 1; + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, + widget, optimizationFlags, 0, opacity); } + } else if (wasDirtyParentSceneTransform) { + item->d_ptr->invalidateChildrenSceneTransform(); } // Restore child clip @@ -5236,17 +5256,19 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } } -void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, const QTransform &parentTransform) +void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) { Q_ASSERT(!item || item->d_ptr->dirty || item->d_ptr->dirtyChildren); Q_Q(QGraphicsScene); // Calculate the full scene transform for this item. - QTransform transform = parentTransform; - if (item && !item->d_ptr->itemIsUntransformable()) { - item->d_ptr->combineTransformFromParent(&transform); - item->d_ptr->sceneTransform = transform; - item->d_ptr->hasValidSceneTransform = 1; + bool wasDirtyParentSceneTransform = false; + if (item && item->d_ptr->dirtySceneTransform && !item->d_ptr->itemIsUntransformable()) { + item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform + : QTransform(); + item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); + item->d_ptr->dirtySceneTransform = 0; + wasDirtyParentSceneTransform = true; } // Process item. @@ -5261,6 +5283,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, cons } else { QRectF dirtyRect; bool uninitializedDirtyRect = true; + const bool untransformableItem = item->d_ptr->itemIsUntransformable(); for (int j = 0; j < views.size(); ++j) { QGraphicsView *view = views.at(j); @@ -5290,15 +5313,15 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, cons if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); - if (item->d_ptr->hasBoundingRegionGranularity) { - const QRegion dirtyViewRegion = item->deviceTransform(view->viewportTransform()) - .map(QRegion(dirtyRect.toRect())); - viewPrivate->updateRegion(dirtyViewRegion); - } else { - const QRect dirtyViewRect = item->deviceTransform(view->viewportTransform()) - .mapRect(dirtyRect).toRect(); - viewPrivate->updateRect(dirtyViewRect); - } + QTransform deviceTransform = item->d_ptr->sceneTransform; + if (!untransformableItem) + deviceTransform *= view->viewportTransform(); + else + deviceTransform = item->deviceTransform(view->viewportTransform()); + if (item->d_ptr->hasBoundingRegionGranularity) + viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect()))); + else + viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect()); } } } @@ -5309,14 +5332,18 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, cons const bool allChildrenDirty = item && item->d_ptr->allChildrenDirty; for (int i = 0; i < children->size(); ++i) { QGraphicsItem *child = children->at(i); + if (wasDirtyParentSceneTransform) + child->d_ptr->dirtySceneTransform = 1; if (allChildrenDirty) { child->d_ptr->dirty = 1; } else if (!child->d_ptr->dirty && !child->d_ptr->dirtyChildren) { resetDirtyItem(child); continue; } - processDirtyItemsRecursive(child, transform); + processDirtyItemsRecursive(child); } + } else if (wasDirtyParentSceneTransform) { + item->d_ptr->invalidateChildrenSceneTransform(); } if (item) @@ -5373,8 +5400,7 @@ void QGraphicsScene::drawItems(QPainter *painter, if (!item->d_ptr->itemDiscovered) { topLevelItems << item; item->d_ptr->itemDiscovered = 1; - d->drawSubtreeRecursive(item, painter, viewTransform, viewTransform, - expose, widget, flags); + d->drawSubtreeRecursive(item, painter, viewTransform, expose, widget, flags); } } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 6b4476c..e0c48a6 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -258,13 +258,12 @@ public: const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); - void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &parentTransform, - const QTransform &viewTransform, + void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, QRegion *exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, QList *topLevelItems = 0, qreal parentOpacity = qreal(1.0)); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); - void processDirtyItemsRecursive(QGraphicsItem *item, const QTransform &); + void processDirtyItemsRecursive(QGraphicsItem *item); inline void resetDirtyItem(QGraphicsItem *item) { diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index caa3ffc..e9a432e 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3301,7 +3301,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Items if (!(d->optimizationFlags & IndirectPainting)) { - d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, viewTransform, &d->exposedRegion, + d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion, viewport(), d->optimizationFlags, 0); } else { // Find all exposed items -- cgit v0.12 From 062b7b1280ef228567d16187951fe43e2ac0f78c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 3 Jun 2009 07:06:57 +0200 Subject: Remove leftover code from merge conflict. --- src/gui/graphicsview/qgraphicsitem_p.h | 66 ------------- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 126 ------------------------- 2 files changed, 192 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index f9d63fb..b0b940b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -401,77 +401,11 @@ public: // Optional stacking order int globalStackingOrder; - struct DecomposedTransform; - DecomposedTransform *decomposedTransform() const - { - QGraphicsItemPrivate *that = const_cast(this); - DecomposedTransform *decomposed; - if (hasDecomposedTransform) { - decomposed = qVariantValue(extra(ExtraDecomposedTransform)); - } else { - decomposed = new DecomposedTransform; - that->setExtra(ExtraDecomposedTransform, qVariantFromValue(decomposed)); - that->hasDecomposedTransform = 1; - if (!dirtyTransformComponents) - decomposed->reset(); - } - if (dirtyTransformComponents) { - decomposed->initFrom(q_ptr->transform()); - that->dirtyTransformComponents = 0; - } - return decomposed; - } - - struct DecomposedTransform { - qreal xScale; - qreal yScale; - qreal xRotation; - qreal yRotation; - qreal zRotation; - qreal horizontalShear; - qreal verticalShear; - qreal xOrigin; - qreal yOrigin; - - inline void reset() - { - xScale = 1.0; - yScale = 1.0; - xRotation = 0.0; - yRotation = 0.0; - zRotation = 0.0; - horizontalShear = 0.0; - verticalShear = 0.0; - xOrigin = 0.0; - yOrigin = 0.0; - } - - inline void initFrom(const QTransform &x) - { - reset(); - // ### decompose transform - Q_UNUSED(x); - } - - inline void generateTransform(QTransform *x) const - { - x->translate(xOrigin, yOrigin); - x->rotate(xRotation, Qt::XAxis); - x->rotate(yRotation, Qt::YAxis); - x->rotate(zRotation, Qt::ZAxis); - x->shear(horizontalShear, verticalShear); - x->scale(xScale, yScale); - x->translate(-xOrigin, -yOrigin); - } - }; - QGraphicsItem *q_ptr; }; QT_END_NAMESPACE -Q_DECLARE_METATYPE(QGraphicsItemPrivate::DecomposedTransform *) - #endif // QT_NO_GRAPHICSVIEW #endif diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 8afdeb4..9cfd897 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -219,8 +219,6 @@ private slots: void updateCachedItemAfterMove(); void deviceTransform_data(); void deviceTransform(); - void setTransformProperties_data(); - void setTransformProperties(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -6428,129 +6426,5 @@ void tst_QGraphicsItem::deviceTransform() QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3); } -void tst_QGraphicsItem::setTransformProperties_data() -{ - QTest::addColumn("origin"); - QTest::addColumn("rotationX"); - QTest::addColumn("rotationY"); - QTest::addColumn("rotationZ"); - QTest::addColumn("scaleX"); - QTest::addColumn("scaleY"); - QTest::addColumn("shearX"); - QTest::addColumn("shearY"); - - QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0); - - QTest::newRow("rotationZ") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(42.2) - << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0); - - QTest::newRow("rotationXY") << QPointF() << qreal(12.5) << qreal(53.6) << qreal(0.0) - << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0); - - QTest::newRow("rotationXYZ") << QPointF() << qreal(-25) << qreal(12) << qreal(556) - << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0); - - QTest::newRow("rotationXYZ dicentred") << QPointF(-53, 25.2) - << qreal(-2578.2) << qreal(4565.2) << qreal(56) - << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0); - - QTest::newRow("Scale") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(6) << qreal(0.5) << qreal(0.0) << qreal(0.0); - - QTest::newRow("Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(1) << qreal(1) << qreal(2.2) << qreal(0.5); - - QTest::newRow("Scale and Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(5.2) << qreal(2.1) << qreal(5.2) << qreal(5.5); - - QTest::newRow("Everything") << QPointF() << qreal(41) << qreal(-23) << qreal(0.56) - << qreal(8.2) << qreal(-0.2) << qreal(-12) << qreal(-0.8); - - QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196) << qreal(-1260) - << qreal(4) << qreal(2) << qreal(2.56) << qreal(0.8); -} - -void tst_QGraphicsItem::setTransformProperties() -{ - QFETCH(QPointF,origin); - QFETCH(qreal,rotationX); - QFETCH(qreal,rotationY); - QFETCH(qreal,rotationZ); - QFETCH(qreal,scaleX); - QFETCH(qreal,scaleY); - QFETCH(qreal,shearX); - QFETCH(qreal,shearY); - - QTransform result; - result.translate(origin.x(), origin.y()); - result.rotate(rotationX, Qt::XAxis); - result.rotate(rotationY, Qt::YAxis); - result.rotate(rotationZ, Qt::ZAxis); - result.shear(shearX, shearY); - result.scale(scaleX, scaleY); - result.translate(-origin.x(), -origin.y()); - - QGraphicsScene scene; - QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); - scene.addItem(item); - item->setPos(100, 100); - - item->setRotation(rotationX, rotationY, rotationZ); - item->setScale(scaleX, scaleY); - item->setShear(shearX, shearY); - item->setTransformOrigin(origin); - - QCOMPARE(item->xRotation(), rotationX); - QCOMPARE(item->yRotation(), rotationY); - QCOMPARE(item->zRotation(), rotationZ); - QCOMPARE(item->xScale(), scaleX); - QCOMPARE(item->yScale(), scaleY); - QCOMPARE(item->horizontalShear(), shearX); - QCOMPARE(item->verticalShear(), shearY); - QCOMPARE(item->transformOrigin(), origin); - - QCOMPARE(result, item->transform()); - - //----------------------------------------------------------------- - //Change the rotation Z - item->setZRotation(45); - QTransform result2; - result2.translate(origin.x(), origin.y()); - result2.rotate(rotationX, Qt::XAxis); - result2.rotate(rotationY, Qt::YAxis); - result2.rotate(45, Qt::ZAxis); - result2.shear(shearX, shearY); - result2.scale(scaleX, scaleY); - result2.translate(-origin.x(), -origin.y()); - - QCOMPARE(item->xRotation(), rotationX); - QCOMPARE(item->yRotation(), rotationY); - QCOMPARE(item->zRotation(), 45.0); - QCOMPARE(item->xScale(), scaleX); - QCOMPARE(item->yScale(), scaleY); - QCOMPARE(item->horizontalShear(), shearX); - QCOMPARE(item->verticalShear(), shearY); - QCOMPARE(item->transformOrigin(), origin); - - QCOMPARE(result2, item->transform()); - - //----------------------------------------------------------------- - // calling setTransform() should reset the properties to their default - item->setTransform(result); - - QCOMPARE(item->xRotation(), 0.0); - QCOMPARE(item->yRotation(), 0.0); - QCOMPARE(item->zRotation(), 0.0); - QCOMPARE(item->xScale(), 1.0); - QCOMPARE(item->yScale(), 1.0); - QCOMPARE(item->horizontalShear(), 0.0); - QCOMPARE(item->verticalShear(), 0.0); - QCOMPARE(item->transformOrigin(), QPointF(0,0)); - - QCOMPARE(result, item->transform()); -} - - QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 8af81877bb11d58099189bfab21d21e3021b7b8b Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 3 Jun 2009 07:35:06 +0200 Subject: Add QGraphicsView::isTransformed(), and use it to avoid view transforms. Ensure that we don't ask for or multiply with the view transform if the view is not transformed. --- src/gui/graphicsview/qgraphicsscene.cpp | 10 ++++++---- src/gui/graphicsview/qgraphicsview.cpp | 12 ++++++++++++ src/gui/graphicsview/qgraphicsview.h | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 2773bdd..7bf58c3 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5314,10 +5314,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); QTransform deviceTransform = item->d_ptr->sceneTransform; - if (!untransformableItem) - deviceTransform *= view->viewportTransform(); - else - deviceTransform = item->deviceTransform(view->viewportTransform()); + if (view->isTransformed()) { + if (!untransformableItem) + deviceTransform *= view->viewportTransform(); + else + deviceTransform = item->deviceTransform(view->viewportTransform()); + } if (item->d_ptr->hasBoundingRegionGranularity) viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect()))); else diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index e9a432e..c91e0d1 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3555,6 +3555,18 @@ QTransform QGraphicsView::viewportTransform() const } /*! + Returns true if the view is transformed (i.e., a non-identity transform + has been assigned, or the scrollbars are adjusted). + + \sa setTransform(), horizontalScrollBar(), verticalScrollBar() +*/ +bool QGraphicsView::isTransformed() const +{ + Q_D(const QGraphicsView); + return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll(); +} + +/*! Sets the view's current transformation matrix to \a matrix. If \a combine is true, then \a matrix is combined with the current matrix; diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h index b7a9906..387fa01 100644 --- a/src/gui/graphicsview/qgraphicsview.h +++ b/src/gui/graphicsview/qgraphicsview.h @@ -170,6 +170,7 @@ public: void resetMatrix(); QTransform transform() const; QTransform viewportTransform() const; + bool isTransformed() const; void setTransform(const QTransform &matrix, bool combine = false); void resetTransform(); void rotate(qreal angle); -- cgit v0.12 From b5d987298b0502dd593dd09d7e4e1233d6e30dd6 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 3 Jun 2009 07:50:33 +0200 Subject: Avoid constructing empty temporary QTransforms. This is a microoptimization. --- src/gui/graphicsview/qgraphicsscene.cpp | 19 +++++++++---------- src/gui/graphicsview/qgraphicsscene_p.h | 1 + 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7bf58c3..188165d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5110,29 +5110,28 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } // Calculate the full transform for this item. - QTransform transform; QRect viewBoundingRect; bool wasDirtyParentSceneTransform = false; if (item) { if (item->d_ptr->itemIsUntransformable()) { - transform = item->deviceTransform(viewTransform); + transformTmp = item->deviceTransform(viewTransform); } else { if (item->d_ptr->dirtySceneTransform) { item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform - : transform; + : QTransform(); item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); item->d_ptr->dirtySceneTransform = 0; wasDirtyParentSceneTransform = true; } - transform = item->d_ptr->sceneTransform; - transform *= viewTransform; + transformTmp = item->d_ptr->sceneTransform; + transformTmp *= viewTransform; } - + QRectF brect = item->boundingRect(); if (!brect.size().isNull()) { // ### This does not take the clip into account. _q_adjustRect(&brect); - viewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); + viewBoundingRect = transformTmp.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); if (exposedRegion) viewBoundingRect &= exposedRegion->boundingRect(); @@ -5149,7 +5148,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Clip children. if (childClip) { painter->save(); - painter->setWorldTransform(transform); + painter->setWorldTransform(transformTmp); painter->setClipPath(item->shape(), Qt::IntersectClip); } @@ -5181,14 +5180,14 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw item if (!dontDrawItem) { - item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); + item->d_ptr->initStyleOption(&styleOptionTmp, transformTmp, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); bool savePainter = clipsToShape || !(optimizationFlags & QGraphicsView::DontSavePainterState); if (savePainter) painter->save(); if (!childClip) - painter->setWorldTransform(transform); + painter->setWorldTransform(transformTmp); if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index e0c48a6..8bc25b6 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -287,6 +287,7 @@ public: void updatePalette(const QPalette &palette); QStyleOptionGraphicsItem styleOptionTmp; + QTransform transformTmp; }; QT_END_NAMESPACE -- cgit v0.12 From 31a7de5cbecad8f5cc106c8886c79c63f07c9b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 3 Jun 2009 10:43:49 +0200 Subject: Correct minor mistake after re-refactoring. We don't want to re-calculate the dirty rect for each view. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 188165d..f8b3b0a 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5305,8 +5305,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) if (!item->d_ptr->fullUpdatePending) { _q_adjustRect(&item->d_ptr->needsRepaint); dirtyRect &= item->d_ptr->needsRepaint; - uninitializedDirtyRect = false; } + uninitializedDirtyRect = false; } if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) -- cgit v0.12 From 33473417a73cafa0c0d9283c00b1e716becba0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 3 Jun 2009 14:34:54 +0200 Subject: Speed up processing of dirty items when ancestor clips children. This patch also contains a bug fix where a child item didn't update due to a bit not being properly set. No more rendering artifacts :) --- src/gui/graphicsview/qgraphicsscene.cpp | 33 +++++++++++++++++++++++++++------ src/gui/graphicsview/qgraphicsscene_p.h | 2 +- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f8b3b0a..ec0e87b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5255,7 +5255,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } } -void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) +void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren) { Q_ASSERT(!item || item->d_ptr->dirty || item->d_ptr->dirtyChildren); Q_Q(QGraphicsScene); @@ -5271,7 +5271,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) } // Process item. - if (item && item->d_ptr->dirty) { + if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); if (useCompatUpdate && !item->d_ptr->itemIsUntransformable() && qFuzzyIsNull(item->boundingRegionGranularity())) { @@ -5300,6 +5300,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) break; } + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) + viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + + if (!item->d_ptr->dirty) + continue; + if (uninitializedDirtyRect) { dirtyRect = adjustedItemBoundingRect(item); if (!item->d_ptr->fullUpdatePending) { @@ -5309,9 +5315,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) uninitializedDirtyRect = false; } - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) - viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); - QTransform deviceTransform = item->d_ptr->sceneTransform; if (view->isTransformed()) { if (!untransformableItem) @@ -5331,17 +5334,35 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item) if (!item || item->d_ptr->dirtyChildren) { QList *children = item ? &item->d_ptr->children : &topLevelItems; const bool allChildrenDirty = item && item->d_ptr->allChildrenDirty; + if (!dirtyAncestorContainsChildren) { + dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending + && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); + } for (int i = 0; i < children->size(); ++i) { QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; + if (allChildrenDirty) { child->d_ptr->dirty = 1; + child->d_ptr->fullUpdatePending = 1; + child->d_ptr->dirtyChildren = 1; + child->d_ptr->allChildrenDirty = 1; } else if (!child->d_ptr->dirty && !child->d_ptr->dirtyChildren) { resetDirtyItem(child); continue; } - processDirtyItemsRecursive(child); + + if (dirtyAncestorContainsChildren) { + // No need to process this child's dirty rect, hence reset the dirty state. + // However, we have to continue the recursion because it might have a dirty + // view bounding rect that needs repaint. We also have to reset the dirty + // state of its descendants. + child->d_ptr->dirty = 0; + child->d_ptr->fullUpdatePending = 0; + } + + processDirtyItemsRecursive(child, dirtyAncestorContainsChildren); } } else if (wasDirtyParentSceneTransform) { item->d_ptr->invalidateChildrenSceneTransform(); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 8bc25b6..f4964f2 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -263,7 +263,7 @@ public: QList *topLevelItems = 0, qreal parentOpacity = qreal(1.0)); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); - void processDirtyItemsRecursive(QGraphicsItem *item); + void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false); inline void resetDirtyItem(QGraphicsItem *item) { -- cgit v0.12 From 1598ef761a8c3f0c9cccf5318e3de30f6c50880f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 3 Jun 2009 15:18:25 +0200 Subject: Compatibility fix: Updates made on the scene must be processed with a queued connection This connection was queued in the views before, but we don't do that anymore, instead we re-use the _q_emitUpdated slot and process pending updates on the views there. Makes tst_QGraphicsView::viewportUpdateMode happy again. --- src/gui/graphicsview/qgraphicsscene.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ec0e87b..8641fe2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -614,6 +614,10 @@ void QGraphicsScenePrivate::_q_emitUpdated() views.at(i), SLOT(updateScene(QList))); } } + } else { + for (int i = 0; i < views.size(); ++i) + views.at(i)->d_func()->processPendingUpdates(); + return; } // Notify the changes to anybody interested. @@ -3721,7 +3725,7 @@ void QGraphicsScene::update(const QRectF &rect) } } - if (!directUpdates && !d->calledEmitUpdated) { + if (!d->calledEmitUpdated) { d->calledEmitUpdated = true; QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection); } -- cgit v0.12 From 728179ed60b43187d28c77a2d6930a74a62791d6 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 3 Jun 2009 16:34:58 +0200 Subject: Add QGraphicsItem::itemChangeEnabled(). This function allows the user to disable notifications for item changes. In QSimpleCanvasItem, all notifications are disabled by default, and you can enable them one at a time. QGraphicsItem's behavior is to by default enable all notifications. A side effect of this change is that I've removed one optimization in favor of another: by not constructing a QVariant at all when there's no notification we get maximum performance, at the expense of constructing it twice if there is a notification. --- src/gui/graphicsview/qgraphicsitem.cpp | 251 ++++++++++++++++++++++---------- src/gui/graphicsview/qgraphicsitem.h | 5 + src/gui/graphicsview/qgraphicsitem_p.h | 4 +- src/gui/graphicsview/qgraphicsscene.cpp | 30 ++-- 4 files changed, 202 insertions(+), 88 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 57ca2ef..2eb5150 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -#define QGRAPHICSITEM_NO_ITEMCHANGE - /*! \class QGraphicsItem \brief The QGraphicsItem class is the base class for all graphical @@ -851,11 +849,13 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de if (newParent == parent) return; - const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue(newParent))); - newParent = qVariantValue(newParentVariant); - if (newParent == parent) - return; + bool notify = q->itemChangeEnabled(QGraphicsItem::ItemParentChange); + if (notify) { + newParent = qVariantValue(q->itemChange(QGraphicsItem::ItemParentChange, + qVariantFromValue(newParent))); + if (newParent == parent) + return; + } if (QGraphicsWidget *w = isWidget ? static_cast(q) : q->parentWidget()) { // Update the child focus chain; when reparenting a widget that has a @@ -955,7 +955,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de dirtySceneTransform = 1; // Deliver post-change notification - q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); + if (notify) + q->itemChange(QGraphicsItem::ItemParentHasChanged, qVariantFromValue(newParent)); } /*! @@ -1393,9 +1394,14 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) // Notify change and check for adjustment. if (quint32(d_ptr->flags) == quint32(flags)) return; - flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); - if (quint32(d_ptr->flags) == quint32(flags)) - return; + + // Notify + bool notify = itemChangeEnabled(ItemFlagsChange); + if (notify) { + flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); + if (quint32(d_ptr->flags) == quint32(flags)) + return; + } // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); @@ -1443,7 +1449,78 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) } // Notify change. - itemChange(ItemFlagsHaveChanged, quint32(flags)); + if (notify) + itemChange(ItemFlagsHaveChanged, quint32(flags)); +} + +static const int itemChangeBits[] = { + /* ItemPositionChange */ 1 << 1, + /* ItemMatrixChange */ 1 << 2, + /* ItemVisibleChange */ 1 << 3, + /* ItemEnabledChange */ 1 << 4, + /* ItemSelectedChange */ 1 << 5, + /* ItemParentChange */ 1 << 6, + /* ItemChildAddedChange */ 1 << 7, + /* ItemChildRemovedChange */ 1 << 8, + /* ItemTransformChange */ 1 << 9, + /* ItemPositionHasChanged */ 1 << 1, + /* ItemTransformHasChanged */ 1 << 9, + /* ItemSceneChange */ 1 << 10, + /* ItemVisibleHasChanged */ 1 << 3, + /* ItemEnabledHasChanged */ 1 << 4, + /* ItemSelectedHasChanged */ 1 << 5, + /* ItemParentHasChanged */ 1 << 6, + /* ItemSceneHasChanged */ 1 << 10, + /* ItemCursorChange */ 1 << 11, + /* ItemCursorHasChanged */ 1 << 11, + /* ItemToolTipChange */ 1 << 12, + /* ItemToolTipHasChanged */ 1 << 12, + /* ItemFlagsChange */ 1 << 13, + /* ItemFlagsHaveChanged */ 1 << 13, + /* ItemZValueChange */ 1 << 14, + /* ItemZValueHasChanged */ 1 << 14, + /* ItemOpacityChange */ 1 << 15, + /* ItemOpacityHasChanged */ 1 << 15 +}; + +/*! + Returns true if \a change is enabled (i.e., QGraphicsItem will call + itemChange() whenever the respective change occurs); otherwise returns + false. + + \sa setItemChangeEnabled(), setItemChangesEnabled(), itemChange() +*/ +bool QGraphicsItem::itemChangeEnabled(GraphicsItemChange change) const +{ + return d_ptr->itemChangesEnabled & itemChangeBits[change]; +} + +/*! + If \a enabled is true, notifications for \a change are enabled; otherwise + they are disabled. By default, QGraphicsItem sends notifications for all + changes by calling itemChange(). + + \sa itemChangeEnabled(), setItemChangesEnabled(), itemChange() +*/ +void QGraphicsItem::setItemChangeEnabled(GraphicsItemChange change, bool enabled) +{ + if (enabled) { + d_ptr->itemChangesEnabled |= itemChangeBits[change]; + } else { + d_ptr->itemChangesEnabled &= itemChangeBits[change]; + } +} + +/*! + If \a enabled is true, all item change notifications are enabled; + otherwise, they are disabled. You can toggle individual notifications by + calling setItemChangeEnabled(). + + \sa itemChangeEnabled(), itemChange() +*/ +void QGraphicsItem::setItemChangesEnabled(bool enabled) +{ + d_ptr->itemChangesEnabled = enabled ? 0xffff : 0; } /*! @@ -1532,9 +1609,13 @@ QString QGraphicsItem::toolTip() const */ void QGraphicsItem::setToolTip(const QString &toolTip) { - const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip)); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString()); - itemChange(ItemToolTipHasChanged, toolTipVariant); + bool notify = itemChangeEnabled(ItemToolTipChange); + QVariant toolTipVariant = toolTip; + if (notify) + toolTipVariant = itemChange(ItemToolTipChange, toolTipVariant); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant); + if (notify) + itemChange(ItemToolTipHasChanged, toolTipVariant); } #endif // QT_NO_TOOLTIP @@ -1576,8 +1657,11 @@ QCursor QGraphicsItem::cursor() const */ void QGraphicsItem::setCursor(const QCursor &cursor) { - const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue(cursor))); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue(cursorVariant)); + bool notify = itemChangeEnabled(ItemCursorChange); + QVariant cursorVariant = qVariantFromValue(cursor); + if (notify) + cursorVariant = itemChange(ItemCursorChange, cursorVariant); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, cursorVariant); d_ptr->hasCursor = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; @@ -1596,7 +1680,8 @@ void QGraphicsItem::setCursor(const QCursor &cursor) } } } - itemChange(ItemCursorHasChanged, cursorVariant); + if (notify) + itemChange(ItemCursorHasChanged, cursorVariant); } /*! @@ -1693,10 +1778,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo if (parent && newVisible && !parent->d_ptr->visible) return; + // Notify + bool notify = q->itemChangeEnabled(QGraphicsItem::ItemVisibleChange); + if (notify) + newVisible = q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, quint32(newVisible)).toBool(); + // Modify the property. - const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, - quint32(newVisible))); - newVisible = newVisibleVariant.toBool(); if (visible == quint32(newVisible)) return; visible = newVisible; @@ -1763,7 +1850,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant); + if (notify) + q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisible); } /*! @@ -1869,9 +1957,10 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Modify the property. - const QVariant newEnabledVariant(q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, - quint32(newEnabled))); - enabled = newEnabledVariant.toBool(); + bool notify = q_ptr->itemChangeEnabled(QGraphicsItem::ItemEnabledChange); + if (notify) + newEnabled = q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, quint32(newEnabled)).toBool(); + enabled = newEnabled; // Schedule redraw. if (update && scene) @@ -1883,7 +1972,8 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant); + if (notify) + q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabled); } /*! @@ -1970,10 +2060,13 @@ void QGraphicsItem::setSelected(bool selected) selected = false; if (d_ptr->selected == selected) return; - const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected))); - bool newSelected = newSelectedVariant.toBool(); - if (d_ptr->selected == newSelected) - return; + bool notify = itemChangeEnabled(ItemSelectedChange); + bool newSelected = selected; + if (notify) { + newSelected = itemChange(ItemSelectedChange, quint32(selected)).toBool(); + if (d_ptr->selected == newSelected) + return; + } d_ptr->selected = newSelected; if (d_ptr->scene) { @@ -1990,7 +2083,8 @@ void QGraphicsItem::setSelected(bool selected) } // Deliver post-change notification. - itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant); + if (notify) + itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelected); } /*! @@ -2056,13 +2150,12 @@ qreal QGraphicsItem::effectiveOpacity() const */ void QGraphicsItem::setOpacity(qreal opacity) { - // Notify change. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity))); - qreal newOpacity = newOpacityVariant.toDouble(); -#else qreal newOpacity = opacity; -#endif + + // Notify + bool notify = itemChangeEnabled(ItemOpacityChange); + if (notify) + newOpacity = itemChange(ItemOpacityChange, double(newOpacity)).toDouble(); // Normalize. newOpacity = qBound(0.0, newOpacity, 1.0); @@ -2073,10 +2166,9 @@ void QGraphicsItem::setOpacity(qreal opacity) d_ptr->opacity = newOpacity; - // Notify change. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - itemChange(ItemOpacityHasChanged, newOpacity); -#endif + // Notify + if (notify) + itemChange(ItemOpacityHasChanged, newOpacity); // Update. if (d_ptr->scene) @@ -2525,15 +2617,15 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) if (this->pos == pos) return; - // Notify the item that the position is changing. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos)); - QPointF newPos = newPosVariant.toPointF(); - if (newPos == this->pos) - return; -#else QPointF newPos = pos; -#endif + + // Notify + bool notify = q->itemChangeEnabled(QGraphicsItem::ItemPositionChange); + if (notify) { + newPos = q->itemChange(QGraphicsItem::ItemPositionChange, pos).toPointF(); + if (newPos == this->pos) + return; + } // Update and repositition. inSetPosHelper = 1; @@ -2544,9 +2636,9 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) dirtySceneTransform = 1; // Send post-notification. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); -#endif + if (notify) + q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPos); + inSetPosHelper = 0; } @@ -2887,21 +2979,21 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co */ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) { - if(!d_ptr->transform) + if (!d_ptr->transform) d_ptr->transform = new QTransform; QTransform newTransform(combine ? QTransform(matrix) * *d_ptr->transform : QTransform(matrix)); - if(*d_ptr->transform == newTransform) + if (*d_ptr->transform == newTransform) return; // Notify the item that the transformation matrix is changing. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue(newTransform))); - newTransform = qVariantValue(newTransformVariant); - if (*d_ptr->transform == newTransform) - return; -#endif + bool notify = itemChangeEnabled(ItemMatrixChange); + if (notify) { + newTransform = QTransform(qVariantValue(itemChange(ItemMatrixChange, + qVariantFromValue(newTransform.toAffine())))); + if (*d_ptr->transform == newTransform) + return; + } // Update and set the new transformation. prepareGeometryChange(); @@ -2909,9 +3001,8 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->dirtySceneTransform = 1; // Send post-notification. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - itemChange(ItemTransformHasChanged, newTransformVariant); -#endif + if (notify) + itemChange(ItemTransformHasChanged, qVariantFromValue(newTransform)); } /*! @@ -2936,19 +3027,20 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) */ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) { - if(!d_ptr->transform) + if (!d_ptr->transform) d_ptr->transform = new QTransform; QTransform newTransform(combine ? matrix * *d_ptr->transform : matrix); - if(*d_ptr->transform == newTransform) + if (*d_ptr->transform == newTransform) return; // Notify the item that the transformation matrix is changing. - const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue(newTransform))); - newTransform = qVariantValue(newTransformVariant); - if (*d_ptr->transform == newTransform) - return; + bool notify = itemChangeEnabled(ItemTransformChange); + if (notify) { + newTransform = qVariantValue(itemChange(ItemTransformChange, qVariantFromValue(newTransform))); + if (*d_ptr->transform == newTransform) + return; + } // Update and set the new transformation. prepareGeometryChange(); @@ -2956,7 +3048,8 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) d_ptr->dirtySceneTransform = 1; // Send post-notification. - itemChange(ItemTransformHasChanged, newTransformVariant); + if (notify) + itemChange(ItemTransformHasChanged, qVariantFromValue(newTransform)); } /*! @@ -3129,10 +3222,13 @@ qreal QGraphicsItem::zValue() const */ void QGraphicsItem::setZValue(qreal z) { - const QVariant newZVariant(itemChange(ItemZValueChange, double(z))); - qreal newZ = qreal(newZVariant.toDouble()); - if (newZ == d_ptr->z) - return; + bool notify = itemChangeEnabled(ItemZValueChange); + qreal newZ = z; + if (notify) { + newZ = itemChange(ItemZValueChange, double(z)).toDouble(); + if (newZ == d_ptr->z) + return; + } d_ptr->z = newZ; d_ptr->needSortChildren = 1; @@ -3143,7 +3239,8 @@ void QGraphicsItem::setZValue(qreal z) d_ptr->scene->d_func()->invalidateSortCache(); } - itemChange(ItemZValueHasChanged, newZVariant); + if (notify) + itemChange(ItemZValueHasChanged, newZ); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 737ea80..7c87176 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -129,6 +129,7 @@ public: ItemZValueHasChanged, ItemOpacityChange, ItemOpacityHasChanged + // NB! Don't forget to increase d_ptr->itemChangesEnabled when adding a new entry. }; enum CacheMode { @@ -165,6 +166,10 @@ public: void setFlag(GraphicsItemFlag flag, bool enabled = true); void setFlags(GraphicsItemFlags flags); + bool itemChangeEnabled(GraphicsItemChange change) const; + void setItemChangeEnabled(GraphicsItemChange change, bool enabled); + void setItemChangesEnabled(bool enabled); + CacheMode cacheMode() const; void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize()); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index b0b940b..2752056 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -147,6 +147,7 @@ public: dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), + itemChangesEnabled(0xffff), globalStackingOrder(-1), q_ptr(0) { @@ -396,7 +397,8 @@ public: quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; - quint32 padding : 18; // feel free to use + quint32 itemChangesEnabled : 16; + quint32 padding : 3; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8641fe2..96800a3 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -666,8 +666,10 @@ void QGraphicsScenePrivate::_q_polishItems() const QVariant booleanTrueVariant(true); foreach (QGraphicsItem *item, unpolishedItems) { if (!item->d_ptr->explicitlyHidden) { - item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); - item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); + if (item->itemChangeEnabled(QGraphicsItem::ItemVisibleChange)) { + item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); + item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); + } } if (item->isWidget()) { QEvent event(QEvent::Polish); @@ -2950,9 +2952,12 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. - const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue(this))); - QGraphicsScene *targetScene = qVariantValue(newSceneVariant); + QGraphicsScene *targetScene = this; + bool notify = item->itemChangeEnabled(QGraphicsItem::ItemSceneChange); + if (notify) { + targetScene = qVariantValue(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue(this))); + } if (targetScene != this) { if (targetScene && item->scene() != targetScene) targetScene->addItem(item); @@ -3063,7 +3068,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); + if (notify) + item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue(targetScene)); } /*! @@ -3327,9 +3333,12 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Notify the item that it's scene is changing to 0, allowing the item to // react. - const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue(0))); - QGraphicsScene *targetScene = qVariantValue(newSceneVariant); + QGraphicsScene *targetScene = 0; + bool notify = item->itemChangeEnabled(QGraphicsItem::ItemSceneChange); + if (notify) { + targetScene = qVariantValue(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue(0))); + } if (targetScene != 0 && targetScene != this) { targetScene->addItem(item); return; @@ -3425,7 +3434,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); + if (notify) + item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue(targetScene)); } /*! -- cgit v0.12 From b6b0469e2d3aba2a163fab8c4b2fda4ab775b7f7 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 3 Jun 2009 17:06:24 +0200 Subject: Add BSP tree support to the recursive drawing algorithm. The code looks ugly and needs to be refactored, but at least this reintroduces the BSP so the chip demo works fine again. --- src/gui/graphicsview/qgraphicsscene.cpp | 41 +++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 96800a3..7a6c21c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5167,22 +5167,49 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } // Find and sort children. - QList &children = item ? item->d_ptr->children : (topLevelItems ? *topLevelItems : this->topLevelItems); + QList tmp; + QList *children = 0; + if (item) { + children = &item->d_ptr->children; + } else if (topLevelItems) { + children = topLevelItems; + } else if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) { + children = &this->topLevelItems; + } else { + tmp = estimateItemsInRect(viewTransform.inverted().mapRect(exposedRegion->boundingRect())); + + QList tli; + for (int i = 0; i < tmp.size(); ++i) { + QGraphicsItem *it = tmp.at(i)->topLevelItem(); + if (!it->d_ptr->itemDiscovered) { + tli << it; + it->d_ptr->itemDiscovered = 1; + } + } + for (int i = 0; i < tli.size(); ++i) + tli.at(i)->d_ptr->itemDiscovered = 0; + + tmp = tli; + children = &tmp; + } + if (!dontDrawChildren) { if (item && item->d_ptr->needSortChildren) { item->d_ptr->needSortChildren = 0; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + qStableSort(children->begin(), children->end(), qt_notclosestLeaf); } else if (!item && needSortTopLevelItems) { needSortTopLevelItems = false; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + qStableSort(children->begin(), children->end(), qt_notclosestLeaf); + } else if (!item && children == &tmp) { + qStableSort(children->begin(), children->end(), qt_notclosestLeaf); } } // Draw children behind int i = 0; if (!dontDrawChildren) { - for (i = 0; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); + for (i = 0; i < children->size(); ++i) { + QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) @@ -5213,8 +5240,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw children in front if (!dontDrawChildren) { - for (; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); + for (; i < children->size(); ++i) { + QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, -- cgit v0.12 From 5127105efd8f76721d7d9acf9681fd18e73760d8 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 4 Jun 2009 15:16:40 +0200 Subject: Fix clipping bug, move code to avoid unintentional shadowing. The children variable tested for clipping was the wrong variable. This broke when the code was moved down as part of a previous cleanup change. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7a6c21c..a137b06 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5152,20 +5152,6 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } } - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); - bool dontDrawItem = !item || viewBoundingRect.isEmpty(); - bool dontDrawChildren = item && dontDrawItem && childClip; - childClip &= !dontDrawChildren & !children.isEmpty(); - if (item && item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) - dontDrawItem = true; - - // Clip children. - if (childClip) { - painter->save(); - painter->setWorldTransform(transformTmp); - painter->setClipPath(item->shape(), Qt::IntersectClip); - } - // Find and sort children. QList tmp; QList *children = 0; @@ -5192,6 +5178,20 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * tmp = tli; children = &tmp; } + + bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); + bool dontDrawItem = !item || viewBoundingRect.isEmpty(); + bool dontDrawChildren = item && dontDrawItem && childClip; + childClip &= !dontDrawChildren & !children->isEmpty(); + if (item && item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) + dontDrawItem = true; + + // Clip children. + if (childClip) { + painter->save(); + painter->setWorldTransform(transformTmp); + painter->setClipPath(item->shape(), Qt::IntersectClip); + } if (!dontDrawChildren) { if (item && item->d_ptr->needSortChildren) { -- cgit v0.12 From 2e8a236108f5b78c4d61a254f4097ccf271f90cb Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 4 Jun 2009 15:35:53 +0200 Subject: Ensure we can find and draw items whose size is (0x0). This removes a microoptimization we did to avoid processing items whose size was (0x0). Turns out an autotest started failing if we did this - we have to find and draw such items because they are commonly used to draw points (e.g., plot graphs). Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 61 +++++++++++++++------------------ 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a137b06..bb26bb6 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -297,13 +297,9 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) static inline void _q_adjustRect(QRectF *rect) { Q_ASSERT(rect); - bool nullWidth = !rect->width(); - bool nullHeight = !rect->height(); - if (nullWidth && nullHeight) - return; - if (nullWidth) + if (!rect->width()) rect->adjust(-0.00001, 0, 0.00001, 0); - else if (nullHeight) + if (!rect->height()) rect->adjust(0, -0.00001, 0, 0.00001); } @@ -1413,33 +1409,26 @@ void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF r if (item) { item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + // ### This does not take the clip into account. QRectF brect = item->boundingRect(); - if (!brect.size().isNull()) { - // ### This does not take the clip into account. - _q_adjustRect(&brect); - - keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)); - else - keep = rect.intersects(transform.mapRect(brect)); - - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = item->collidesWithPath(transform.inverted().map(rectPath)); - } + _q_adjustRect(&brect); + + keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)); + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = item->collidesWithPath(transform.inverted().map(rectPath)); } } bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); bool dontProcessItem = !item || !keep; bool dontProcessChildren = item && dontProcessItem && childClip; - childClip &= !dontProcessChildren & !children.isEmpty(); - - // Clip. - if (childClip) - rect &= transform.map(item->shape()).controlPointRect(); // Find and sort children. QList &children = item ? item->d_ptr->children : const_cast(this)->topLevelItems; @@ -1453,6 +1442,12 @@ void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF r } } + childClip &= !dontProcessChildren & !children.isEmpty(); + + // Clip. + if (childClip) + rect &= transform.map(item->shape()).controlPointRect(); + // Process children behind int i = 0; if (!dontProcessChildren) { @@ -5142,14 +5137,12 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } QRectF brect = item->boundingRect(); - if (!brect.size().isNull()) { - // ### This does not take the clip into account. - _q_adjustRect(&brect); - viewBoundingRect = transformTmp.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); - item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); - if (exposedRegion) - viewBoundingRect &= exposedRegion->boundingRect(); - } + // ### This does not take the clip into account. + _q_adjustRect(&brect); + viewBoundingRect = transformTmp.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); + item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); + if (exposedRegion) + viewBoundingRect &= exposedRegion->boundingRect(); } // Find and sort children. -- cgit v0.12 From ba48a3fdf39a3db7a3d13ac15031c810454c6e25 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 4 Jun 2009 15:59:25 +0200 Subject: Fix bug in QGraphicsItem::effectiveOpacity() caused by typo. See change 72842b2d, the patch misplaces 'p' and 'parent'. This fixes the tst_QGraphicsItem::opacity autotests. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem_p.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 2752056..9be9310 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -296,10 +296,11 @@ public: // parent propagates to me, then combine my local opacity with my parent's // effective opacity into my effective opacity. if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity) - || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { break; + } - o *= parent->d_ptr->opacity; + o *= p->d_ptr->opacity; p = p->d_ptr->parent; myFlags = parentFlags; } -- cgit v0.12 From 32c00c1d30eb275f44ba9d0bff4d6b6b05e9a5ba Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 4 Jun 2009 16:49:10 +0200 Subject: Fix rendering of items that ignore parent opacity. Test if the children ignore the parent's opacity if the current item's opacity is 0.0. If any of the children do ignore the parent then we must continue. Further optimizations are possible: if the item itself is transparent, then don't visit children that don't ignore parent opacity. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bb26bb6..c46ed68 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5101,6 +5101,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * { // Calculate opacity. qreal opacity; + bool invisibleButChildIgnoresParentOpacity = false; if (item) { if (!item->d_ptr->visible) return; @@ -5112,8 +5113,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } else { opacity = item->d_ptr->opacity; } - if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) - return; + if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { + invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity(); + if (!invisibleButChildIgnoresParentOpacity) + return; + } } else { opacity = parentOpacity; } @@ -5176,7 +5180,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * bool dontDrawItem = !item || viewBoundingRect.isEmpty(); bool dontDrawChildren = item && dontDrawItem && childClip; childClip &= !dontDrawChildren & !children->isEmpty(); - if (item && item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) + if (item && (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) || invisibleButChildIgnoresParentOpacity) dontDrawItem = true; // Clip children. @@ -5201,6 +5205,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw children behind int i = 0; if (!dontDrawChildren) { + // ### Don't visit children that don't ignore parent opacity if this + // item is invisible. for (i = 0; i < children->size(); ++i) { QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) @@ -5233,6 +5239,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw children in front if (!dontDrawChildren) { + // ### Don't visit children that don't ignore parent opacity if this + // item is invisible. for (; i < children->size(); ++i) { QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) -- cgit v0.12 From 9eb253eed0ae75d1d32b5e738ead89434fc69837 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 4 Jun 2009 17:07:58 +0200 Subject: Fix stacking order bug, ensure the dirty sort bits are set correctly. The code marked the item's own stacking order as dirty when changing its own Z value, the right thing is however to set the _parent's_ bit. Also added missing code for when the ItemStacksBehindParent flag was toggled. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2eb5150..47a9ae2 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1442,6 +1442,14 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->updateAncestorFlag(ItemIgnoresTransformations); } + if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) { + // Ensure child item sorting is up to date when toggling this flag. + if (d_ptr->parent) + d_ptr->parent->d_ptr->needSortChildren = 1; + else if (d_ptr->scene) + d_ptr->scene->d_func()->needSortTopLevelItems = 1; + } + if (d_ptr->scene) { d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, @@ -3230,7 +3238,10 @@ void QGraphicsItem::setZValue(qreal z) return; } d_ptr->z = newZ; - d_ptr->needSortChildren = 1; + if (d_ptr->parent) + d_ptr->parent->d_ptr->needSortChildren = 1; + else if (d_ptr->scene) + d_ptr->scene->d_func()->needSortTopLevelItems = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); -- cgit v0.12 From a47b632971068001d56471a9cb78ad983c4a9fee Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 4 Jun 2009 17:12:42 +0200 Subject: Ensure this test goes via QGraphicsScene::drawItems(). Enable QGraphicsView::IndirectPainting to make sure it detects which items are drawn. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 9cfd897..427ecf3 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -5874,6 +5874,7 @@ void tst_QGraphicsItem::nestedClipping() l3->setData(0, "l3"); QGraphicsView view(&scene); + view.setOptimizationFlag(QGraphicsView::IndirectPainting); view.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); -- cgit v0.12 From 4f3a8e82fd6b328a06990517648f0d46c50ff41e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 4 Jun 2009 17:26:57 +0200 Subject: Ensure we pass the intersect mode when checking item collisions. This fixes one of two failures in tst_QGraphicsScene::items_QRectF_2. The other seems unrelated. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index c46ed68..6a79dde 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1422,7 +1422,7 @@ void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF r if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { QPainterPath rectPath; rectPath.addRect(rect); - keep = item->collidesWithPath(transform.inverted().map(rectPath)); + keep = item->collidesWithPath(transform.inverted().map(rectPath), mode); } } -- cgit v0.12 From 98f197d1a11c3dd13959967534b1dba7eea479ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 11:56:40 +0200 Subject: Avoid falling in the else case when there are no views. Partially fixes tst_QGraphicsScene::update failure. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6a79dde..df3153f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -601,7 +601,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() // the optimization that items send updates directly to the views, but it // needs to happen in order to keep compatibility with the behavior from // Qt 4.4 and backward. - if (!views.isEmpty() && (connectedSignals & changedSignalMask)) { + if (connectedSignals & changedSignalMask) { for (int i = 0; i < views.size(); ++i) { QGraphicsView *view = views.at(i); if (!view->d_func()->connectedToScene) { -- cgit v0.12 From ad92e095ea34dda9d099fae30340a8fbb4c5380a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 17:31:47 +0200 Subject: Compatibility fix for QGraphicsScene::sceneRectChanged()/sceneRect(). We have to keep the growingItemsBoundingRect up-to-date if there's no scene rect. The only difference now is that sceneRectChanged will not be emitted before entering the event-loop, but the documentation only states it'll be emitted when the scene rect changes, so we consider it harmless. Makes tst_QGraphicsView::sceneRect_growing and tst_QGrahicsScene::sceneRect happy. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 4 ++- src/gui/graphicsview/qgraphicsscene.cpp | 33 +++++++++++++++++------- src/gui/graphicsview/qgraphicsscene_p.h | 5 +++- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 2 ++ 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 47a9ae2..807ee06 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5977,6 +5977,7 @@ void QGraphicsItem::removeFromIndex() void QGraphicsItem::prepareGeometryChange() { if (d_ptr->scene) { + d_ptr->geometryChanged = 1; d_ptr->paintedViewBoundingRectsNeedRepaint = 1; d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 9be9310..d884b16 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -148,6 +148,7 @@ public: paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), itemChangesEnabled(0xffff), + geometryChanged(0), globalStackingOrder(-1), q_ptr(0) { @@ -399,7 +400,8 @@ public: quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; quint32 itemChangesEnabled : 16; - quint32 padding : 3; // feel free to use + quint32 geometryChanged : 1; + quint32 padding : 2; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index df3153f..c738f80 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; /*! \class QGraphicsScene @@ -682,7 +681,11 @@ void QGraphicsScenePrivate::_q_processDirtyItems() if (updateAll) return; + const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); + if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) + emit q_func()->sceneRectChanged(growingItemsBoundingRect); + for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); } @@ -808,13 +811,13 @@ void QGraphicsScenePrivate::purgeRemovedItems() Starts or restarts the timer used for reindexing unindexed items. */ -void QGraphicsScenePrivate::startIndexTimer() +void QGraphicsScenePrivate::startIndexTimer(int interval) { Q_Q(QGraphicsScene); if (indexTimerId) { restartIndexTimer = true; } else { - indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + indexTimerId = q->startTimer(interval); } } @@ -2982,7 +2985,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // a temporary list and schedule an indexing for later. d->unindexedItems << item; item->d_func()->index = -1; - d->startIndexTimer(); + d->startIndexTimer(0); // Add to list of toplevels if this item is a toplevel. if (!item->d_ptr->parent) @@ -5315,16 +5318,27 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // Process item. if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); - if (useCompatUpdate && !item->d_ptr->itemIsUntransformable() - && qFuzzyIsNull(item->boundingRegionGranularity())) { + const bool untransformableItem = item->d_ptr->itemIsUntransformable(); + const QRectF itemBoundingRect = item->boundingRect(); + + if (item->d_ptr->geometryChanged) { + // Update growingItemsBoundingRect. + if (!hasSceneRect) { + QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect); + _q_adjustRect(&itemSceneBoundingRect); + growingItemsBoundingRect |= itemSceneBoundingRect; + } + item->d_ptr->geometryChanged = 0; + } + + if (useCompatUpdate && !untransformableItem && qFuzzyIsNull(item->boundingRegionGranularity())) { // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. - q->update(item->sceneBoundingRect()); + q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect)); } else { QRectF dirtyRect; bool uninitializedDirtyRect = true; - const bool untransformableItem = item->d_ptr->itemIsUntransformable(); for (int j = 0; j < views.size(); ++j) { QGraphicsView *view = views.at(j); @@ -5349,7 +5363,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool continue; if (uninitializedDirtyRect) { - dirtyRect = adjustedItemBoundingRect(item); + dirtyRect = itemBoundingRect; + _q_adjustRect(&dirtyRect); if (!item->d_ptr->fullUpdatePending) { _q_adjustRect(&item->d_ptr->needsRepaint); dirtyRect &= item->d_ptr->needsRepaint; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f4964f2..fd7decf 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -71,6 +71,8 @@ #include #include +static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; + QT_BEGIN_NAMESPACE class QGraphicsView; @@ -138,7 +140,7 @@ public: int indexTimerId; bool restartIndexTimer; - void startIndexTimer(); + void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); bool stickyFocus; bool hasFocus; @@ -270,6 +272,7 @@ public: Q_ASSERT(item); item->d_ptr->dirty = 0; item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; + item->d_ptr->geometryChanged = 0; item->d_ptr->dirtyChildren = 0; item->d_ptr->needsRepaint = QRectF(); item->d_ptr->allChildrenDirty = 0; diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 23d7a94..9f93ae0 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -274,7 +274,9 @@ void tst_QGraphicsScene::sceneRect() QCOMPARE(scene.sceneRect(), QRectF()); QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10)); + qApp->processEvents(); item->setPos(-5, -5); + qApp->processEvents(); QCOMPARE(scene.itemAt(0, 0), item); QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); -- cgit v0.12 From ed0b10aff5d0afb7e8165dbf9b14f30cfd73e3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 18:06:24 +0200 Subject: Make sure we reset the updateAll variable correctly. Makes tst_QGraphicsScene::update happy. --- src/gui/graphicsview/qgraphicsscene.cpp | 1 + tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index c738f80..4578bd4 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -610,6 +610,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() } } } else { + updateAll = false; for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); return; diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 9f93ae0..8bb9122 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -2715,6 +2715,7 @@ void tst_QGraphicsScene::update() QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100); scene.addItem(rect); + qApp->processEvents(); rect->setPos(-100, -100); // This function forces indexing -- cgit v0.12 From 9def469f9f83087fab9cb65c0200f2e6059519ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 19:32:19 +0200 Subject: Compatibility fix for QGraphicsScene::changed signal. Makes tst_QGraphicsScene::changedSignal and tst_QGraphicsItem::setMatrix happy. --- src/gui/graphicsview/qgraphicsitem.cpp | 17 ++++++++++++++--- src/gui/graphicsview/qgraphicsscene.cpp | 8 ++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 807ee06..a2d885b 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5979,10 +5979,21 @@ void QGraphicsItem::prepareGeometryChange() if (d_ptr->scene) { d_ptr->geometryChanged = 1; d_ptr->paintedViewBoundingRectsNeedRepaint = 1; - d_ptr->scene->d_func()->markDirty(this, QRectF(), - /*invalidateChildren=*/true, - /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); + QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); + scenePrivate->markDirty(this, QRectF(), + /*invalidateChildren=*/true, + /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); + + // For compatibility reasons, we have to update the item's old geometry + // if someone is connected to the changed signal or the scene has no views. + // Note that this has to be done *after* markDirty to ensure that + // _q_processDirtyItems is called before _q_emitUpdated. + if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask) + || scenePrivate->views.isEmpty()) { + d_ptr->scene->update(sceneTransform().mapRect(boundingRect())); + } + scenePrivate->removeFromIndex(this); } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4578bd4..c7a41d6 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -682,6 +682,7 @@ void QGraphicsScenePrivate::_q_processDirtyItems() if (updateAll) return; + const bool wasPendingSceneUpdate = calledEmitUpdated; const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) @@ -689,6 +690,13 @@ void QGraphicsScenePrivate::_q_processDirtyItems() for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); + + if (!wasPendingSceneUpdate && calledEmitUpdated) { + // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive + // and we cannot wait for the control to reach the eventloop before the + // changed signal is emitted, so we emit it now. + _q_emitUpdated(); + } } /*! -- cgit v0.12 From f1ada923f7bbe8724d9a9d6a6b391a92c514c440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 19:51:41 +0200 Subject: Discard updates outside the bounding rect. Makes tst_QGraphicsItem::cacheMode happy. --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a2d885b..80ad19d 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4168,7 +4168,7 @@ void QGraphicsItem::update(const QRectF &rect) } if (d_ptr->scene) - d_ptr->scene->d_func()->markDirty(this); + d_ptr->scene->d_func()->markDirty(this, rect); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index c7a41d6..e5c65d1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5381,6 +5381,9 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool uninitializedDirtyRect = false; } + if (dirtyRect.isEmpty()) + continue; // Discard updates outside the bounding rect. + QTransform deviceTransform = item->d_ptr->sceneTransform; if (view->isTransformed()) { if (!untransformableItem) -- cgit v0.12 From 4af92dcf716ee3c2fc4673aadd07fde19b7bffed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 19:57:04 +0200 Subject: Make sure the dirty state of an item is reset when removed from the scene. Makes tst_QGraphicsItem::paint happy. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e5c65d1..eaf00a0 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -758,6 +758,7 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) cachedItemsUnderMouse.removeAll(item); unpolishedItems.removeAll(item); pendingUpdateItems.removeAll(item); + resetDirtyItem(item); //We remove all references of item from the sceneEventFilter arrays QMultiMap::iterator iterator = sceneEventFilters.begin(); @@ -3408,6 +3409,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->pendingUpdateItems.removeAll(item); d->cachedItemsUnderMouse.removeAll(item); d->unpolishedItems.removeAll(item); + d->resetDirtyItem(item); //We remove all references of item from the sceneEventFilter arrays QMultiMap::iterator iterator = d->sceneEventFilters.begin(); -- cgit v0.12 From 9aa44bff88f377f056eafe5d9f24c88d81f477e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 20:58:34 +0200 Subject: Removes odd artifact in the chip demo. Calling repaint() instead of update() is bad when having multiple views (which GV perfectly supports). The result is that e.g. when moving a chip in the chip demo, there's a visible lag between each view. It can also be a performance killer on QWS, where the surface is locked for each repaint(). Instead of calling repaint() we call update() as before, but we also make sure the updates are processed immediately. --- src/gui/graphicsview/qgraphicsscene.cpp | 9 +++++++++ src/gui/graphicsview/qgraphicsview.cpp | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index eaf00a0..4b54c08 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -697,6 +697,15 @@ void QGraphicsScenePrivate::_q_processDirtyItems() // changed signal is emitted, so we emit it now. _q_emitUpdated(); } + + // Immediately dispatch all pending update requests on the views. + for (int i = 0; i < views.size(); ++i) { + QWidget *viewport = views.at(i)->d_func()->viewport; + if (qt_widget_private(viewport)->paintOnScreen()) + QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); + else + QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); + } } /*! diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index c91e0d1..87b5e3f 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -814,11 +814,11 @@ void QGraphicsViewPrivate::processPendingUpdates() if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - viewport->repaint(dirtyBoundingRect); + viewport->update(dirtyBoundingRect); else - viewport->repaint(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); + viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); } else { - viewport->repaint(dirtyRegion); // Already adjusted in updateRect/Region. + viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. } dirtyBoundingRect = QRect(); -- cgit v0.12 From 5ab06593a1ed4c050d19f734737a50078b0fbb52 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 5 Jun 2009 09:00:21 +0200 Subject: Fix tst_QGraphicsView::acceptMousePressEvent (by entering event loop). This is necessary after we made the sceneRect grow lazily when it's not assigned. --- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 8e490ad..718c8d6 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -2525,6 +2525,8 @@ void tst_QGraphicsView::acceptMousePressEvent() scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable); + qApp->processEvents(); // ensure scene rect is updated + QApplication::sendEvent(view.viewport(), &event); QVERIFY(view.accepted); } -- cgit v0.12 From 1c0599289a3da43b0a7cdb38eebe05d45f69ad9c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 5 Jun 2009 10:11:05 +0200 Subject: Fix tst_QGraphicsView::cursor2() - sorting bug when using BSP tree. Make sure we don't claim that we have sorted all toplevel items when we are using the BSP tree, as when painting we have only actually sorted a subset of the elements. --- src/gui/graphicsview/qgraphicsscene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4b54c08..6c78ca9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5217,11 +5217,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (item && item->d_ptr->needSortChildren) { item->d_ptr->needSortChildren = 0; qStableSort(children->begin(), children->end(), qt_notclosestLeaf); + } else if (!item && children == &tmp) { + qStableSort(children->begin(), children->end(), qt_notclosestLeaf); } else if (!item && needSortTopLevelItems) { needSortTopLevelItems = false; qStableSort(children->begin(), children->end(), qt_notclosestLeaf); - } else if (!item && children == &tmp) { - qStableSort(children->begin(), children->end(), qt_notclosestLeaf); } } -- cgit v0.12 From a10f1c955f9cbf54909ce2264279efa9d0423ecd Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 5 Jun 2009 10:23:37 +0200 Subject: Fix tst_QGraphicsScene::itemIndexMethod(), typo in estimateItemsInRect() Don't skip all indexed items that aren't transparent ;-). --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6c78ca9..49ffb32 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -422,7 +422,7 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & if (QGraphicsItem *item = indexedItems.at(i)) { if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - if (item->d_ptr->visible && item->d_ptr->isFullyTransparent()) + if (item->d_ptr->visible && !item->d_ptr->isFullyTransparent()) itemsInRect << item; } } -- cgit v0.12 From b7b0f7250dcf07a4da5d80ccc48accb156f25092 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 5 Jun 2009 10:41:22 +0200 Subject: Fix tst_QGraphicsScene::items_QRectF_2(), an intersection bug. The recursive items function didn't contain the special case check for when the source and target rectangle are identical. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 49ffb32..8958e1b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1437,7 +1437,7 @@ void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF r keep = true; if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)); + keep = rect.contains(transform.mapRect(brect)) && rect != brect; else keep = rect.intersects(transform.mapRect(brect)); -- cgit v0.12 From f31b4a7163cee11c306e9f4fcaab094d9c38cb68 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 5 Jun 2009 11:02:46 +0200 Subject: Fix interaction with QGraphicsWidgets that are a window. Use itemCollidesWithPath, the helper function. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8958e1b..de9d865 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1444,7 +1444,7 @@ void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF r if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { QPainterPath rectPath; rectPath.addRect(rect); - keep = item->collidesWithPath(transform.inverted().map(rectPath), mode); + keep = itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); } } -- cgit v0.12 From e83cc0aca3bab0d37c4d0679319017f4cfeacfe0 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 5 Jun 2009 12:54:04 +0200 Subject: Fix warning. --- src/gui/graphicsview/qgraphicsscene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index de9d865..7bfc032 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5202,8 +5202,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); bool dontDrawItem = !item || viewBoundingRect.isEmpty(); bool dontDrawChildren = item && dontDrawItem && childClip; - childClip &= !dontDrawChildren & !children->isEmpty(); - if (item && (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) || invisibleButChildIgnoresParentOpacity) + childClip &= !dontDrawChildren && !children->isEmpty(); + if (item && ((item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) || invisibleButChildIgnoresParentOpacity)) dontDrawItem = true; // Clip children. -- cgit v0.12 From 9cafd6bcf6f91c027904c998a0dd536feac8d4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 8 Jun 2009 10:55:48 +0200 Subject: Child items leave traces when moving an ancestor item. The problem was that we only marked the painted view bounding rect of the moved item as dirty. We also have to mark its children. --- src/gui/graphicsview/qgraphicsscene.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7bfc032..caf9309 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5336,6 +5336,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool } // Process item. + bool wasDirtyParentViewBoundingRects = false; if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); const bool untransformableItem = item->d_ptr->itemIsUntransformable(); @@ -5376,8 +5377,10 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool break; } - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { + wasDirtyParentViewBoundingRects = true; viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + } if (!item->d_ptr->dirty) continue; @@ -5422,6 +5425,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; + if (wasDirtyParentViewBoundingRects) + child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1; if (allChildrenDirty) { child->d_ptr->dirty = 1; -- cgit v0.12 From 0095e40b2efc0c43c0d908bb5b9828619bc087e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 8 Jun 2009 13:09:14 +0200 Subject: QGraphicsItem discard updates when it shouldn't. Once a _q_processDirtyItems call is queued, it means we at least have one item that is marked as dirty and we must reset it when the _q_processDirtyItems slot is called. The problem however, was that we didn't reset the item's dirty state if a full scene update occurred in between, i.e. item->update(); scene.update(); We don't have to calculate the item's dirty rect if a full scene update occurs in between, but we still have to reset its state. Auto-test included. --- src/gui/graphicsview/qgraphicsscene.cpp | 13 ++++++------ src/gui/graphicsview/qgraphicsview.cpp | 1 + tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 28 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index caf9309..ad392b0 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -679,19 +679,19 @@ void QGraphicsScenePrivate::_q_processDirtyItems() { processDirtyItemsEmitted = false; - if (updateAll) - return; - const bool wasPendingSceneUpdate = calledEmitUpdated; const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) emit q_func()->sceneRectChanged(growingItemsBoundingRect); + if (wasPendingSceneUpdate) + return; + for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); - if (!wasPendingSceneUpdate && calledEmitUpdated) { + if (calledEmitUpdated) { // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive // and we cannot wait for the control to reach the eventloop before the // changed signal is emitted, so we emit it now. @@ -5322,7 +5322,6 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren) { - Q_ASSERT(!item || item->d_ptr->dirty || item->d_ptr->dirtyChildren); Q_Q(QGraphicsScene); // Calculate the full scene transform for this item. @@ -5438,13 +5437,15 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool continue; } - if (dirtyAncestorContainsChildren) { + if (dirtyAncestorContainsChildren || updateAll) { // No need to process this child's dirty rect, hence reset the dirty state. // However, we have to continue the recursion because it might have a dirty // view bounding rect that needs repaint. We also have to reset the dirty // state of its descendants. child->d_ptr->dirty = 0; child->d_ptr->fullUpdatePending = 0; + if (updateAll) + child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; } processDirtyItemsRecursive(child, dirtyAncestorContainsChildren); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 87b5e3f..a9fc563 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2496,6 +2496,7 @@ void QGraphicsView::updateScene(const QList &rects) for (int i = 0; i < dirtyRects.size(); ++i) dirtyViewportRects += dirtyRects.at(i); d->dirtyRegion = QRegion(); + d->dirtyBoundingRect = QRect(); bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate; bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 427ecf3..5b297f6 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -219,6 +219,7 @@ private slots: void updateCachedItemAfterMove(); void deviceTransform_data(); void deviceTransform(); + void update(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -6427,5 +6428,32 @@ void tst_QGraphicsItem::deviceTransform() QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3); } +void tst_QGraphicsItem::update() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(100); + + EventTester *item = new EventTester; + scene.addItem(item); + QTest::qWait(100); // Make sure all pending updates are processed. + item->repaints = 0; + + item->update(); // Item marked as dirty + scene.update(); // Entire scene marked as dirty + qApp->processEvents(); + QCOMPARE(item->repaints, 1); + + // Make sure the dirty state from the previous update is reset so that + // the item don't think it is already dirty and discards this update. + item->update(); + qApp->processEvents(); + QCOMPARE(item->repaints, 2); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 9ed567ca68d51552f89887aa5a300a5f6a6d8ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 8 Jun 2009 13:55:16 +0200 Subject: A partial QGraphicsItem update causes a full update to be discarded. E.g. item->update(QRectF(0, 0, 5, 5)); item->update(); The problem was that we discarded all update requests whenever the item was already marked as dirty. The dirty bit only means it has pending updates (which might be a full update). However, we have a separate bit for full updates (fullUpdatePending) so we have to check against that bit instead. Makes tst_QGraphicsProxyWidget::paintEvent happy. Another auto-test included. --- src/gui/graphicsview/qgraphicsitem.cpp | 4 ++-- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 31 +++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 80ad19d..2a062ab 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3907,7 +3907,7 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. return (!visible && !ignoreVisibleBit) - || (!ignoreDirtyBit && dirty) + || (!ignoreDirtyBit && fullUpdatePending) || !scene || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect) || (!ignoreClipping && (childrenClippedToShape() && isClippedAway())) @@ -4163,7 +4163,7 @@ void QGraphicsItem::update(const QRectF &rect) } } // Only invalidate cache; item is already dirty. - if (d_ptr->dirty) + if (d_ptr->fullUpdatePending) return; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 5b297f6..41593b5 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -6428,10 +6428,25 @@ void tst_QGraphicsItem::deviceTransform() QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3); } +class MyGraphicsView : public QGraphicsView +{ +public: + int repaints; + QRegion paintedRegion; + MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {} + void paintEvent(QPaintEvent *e) + { + paintedRegion += e->region(); + ++repaints; + QGraphicsView::paintEvent(e); + } + void reset() { repaints = 0; paintedRegion = QRegion(); } +}; + void tst_QGraphicsItem::update() { QGraphicsScene scene; - QGraphicsView view(&scene); + MyGraphicsView view(&scene); view.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); @@ -6453,6 +6468,20 @@ void tst_QGraphicsItem::update() item->update(); qApp->processEvents(); QCOMPARE(item->repaints, 2); + + // Make sure a partial update doesn't cause a full update to be discarded. + view.reset(); + item->repaints = 0; + item->update(QRectF(0, 0, 5, 5)); + item->update(); + qApp->processEvents(); + QCOMPARE(item->repaints, 1); + QCOMPARE(view.repaints, 1); + const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform()) + .mapRect(item->boundingRect()).toRect(); + const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); + // The entire item's bounding rect (adjusted for antialiasing) should have been painted. + QCOMPARE(view.paintedRegion, expectedRegion); } QTEST_MAIN(tst_QGraphicsItem) -- cgit v0.12 From 56f23d4ccfc27f737d30e92ae5b3ecde6e8b0bbf Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 20 May 2009 16:38:47 +0200 Subject: Add (back) properties to QGraphicsItem to change the transformations component This reapply commit 8ad5020940f10d4ecc5c5e8b3b9656531cb84ef3 and its dependent change that has been reverted while rebasing the recursivepaint branch. With the new properties it is possible to easily animate transformations Reviewed-by: Andreas Documentation still need to be reviewed. --- src/gui/graphicsview/qgraphicsitem.cpp | 512 ++++++++++++++++++++----- src/gui/graphicsview/qgraphicsitem.h | 37 +- src/gui/graphicsview/qgraphicsitem_p.h | 56 ++- src/gui/graphicsview/qgraphicsscene.cpp | 10 +- src/gui/graphicsview/qgraphicsview.cpp | 2 +- src/gui/graphicsview/qgraphicswidget.h | 9 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 199 ++++++++++ 7 files changed, 716 insertions(+), 109 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2a062ab..d962554 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -133,12 +133,8 @@ \section1 Transformation QGraphicsItem supports affine transformations in addition to its base - position, pos(). To change the item's transformation, you can either pass - a transformation matrix to setTransform(), or set the different transformation - properties (transformOrigin, x/y/zRotation, x/yScale, horizontal/verticalShear). - Note that setting the transformation matrix conflicts with using the properties. - Setting the properties will overwrite the transformation set with setTransform, - and using setTransform will reset the properties. + position, pos(). To change the item's transformation, you can pass + a transformation matrix to setTransform() Item transformations accumulate from parent to child, so if both a parent and child item are rotated 90 degrees, the child's total transformation will be 180 degrees. @@ -152,19 +148,18 @@ and scenePos(), which returns its position in scene coordinates. To reset an item's matrix, call resetTransform(). + Another way to apply transformation to an item is to use the , or set the + different transformation properties (transformOrigin, x/y/zRotation, x/yScale, + horizontal/verticalShear). Those properties come in addition to the base transformation + The order you set the transformation properties does not affect the resulting transformation The resulting transformation is always computed in the following order \code - [Origin] [RotateX] [RotateY] [RotateZ] [Shear] [Scale] [-Origin] + [Origin] [Base] [RotateX] [RotateY] [RotateZ] [Shear] [Scale] [-Origin] \endcode - So the transformation is equivalent to the following code - - \code - QTransform().translate(xOrigin, yOrigin).rotate(xRotation, Qt::XAxis).rotate(yRotation, Qt::YAxis).rotate(zRotation, Qt::ZAxis) - .shear(horizontalShear, verticalShear).scale(xScale, yScale).translate(-xOrigin, -yOrigin); - \endcode + Where [Base] is the stransformation set by setTransform \section1 Painting @@ -788,8 +783,8 @@ void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransf if (itemIsUntransformable() && viewTransform) { *x = q_ptr->deviceTransform(*viewTransform); } else { - if (transform) - *x *= *transform; + if (transformData) + *x *= transformData->computedFullTransform(); if (!pos.isNull()) *x *= QTransform::fromTranslate(pos.x(), pos.y()); } @@ -811,8 +806,8 @@ void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTran *x = q_ptr->deviceTransform(*viewTransform); } else { x->translate(pos.x(), pos.y()); - if (transform) - *x = *transform * *x; + if (transformData) + *x = transformData->computedFullTransform() * *x; } } @@ -975,16 +970,9 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec QGraphicsItem *child = children.at(i); QGraphicsItemPrivate *childd = child->d_ptr; bool hasPos = !childd->pos.isNull(); - if (hasPos || childd->transform) { + if (hasPos || childd->transformData) { // COMBINE - QTransform matrix; - if (childd->transform) - matrix = *childd->transform; - if (hasPos) { - const QPointF &p = childd->pos; - matrix *= QTransform::fromTranslate(p.x(), p.y()); - } - matrix *= *x; + QTransform matrix = childd->transformToParent() * *x; *rect |= matrix.mapRect(child->boundingRect()); if (!childd->children.isEmpty()) childd->childrenBoundingRectHelper(&matrix, rect); @@ -1136,8 +1124,7 @@ QGraphicsItem::~QGraphicsItem() if (d_ptr->scene) d_ptr->scene->d_func()->_q_removeItemLater(this); - if (d_ptr->transform) - delete d_ptr->transform; + delete d_ptr->transformData; delete d_ptr; @@ -2747,12 +2734,364 @@ QMatrix QGraphicsItem::matrix() const */ QTransform QGraphicsItem::transform() const { - if (!d_ptr->transform) + if (!d_ptr->transformData) return QTransform(); - return *d_ptr->transform; + return d_ptr->transformData->transform; +} + +/*! + \since 4.6 + + Returns the rotation around the X axis. + + The default is 0 + + \warning The value doesn't take in account any rotation set with the setTransform() method. + + \sa setXRotation(), {Transformations} +*/ +qreal QGraphicsItem::xRotation() const +{ + if (!d_ptr->transformData) + return 0; + return d_ptr->transformData->xRotation; } /*! + \since 4.6 + + Sets the rotation around the X axis to \a angle degrees. + + \warning The value doesn't take in account any rotation set with the setTransform() method. + + \sa xRotation(), setTransformOrigin(), {Transformations} +*/ +void QGraphicsItem::setXRotation(qreal angle) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->xRotation = angle; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + Returns the rotation around the Y axis. + + The default is 0 + + \warning The value doesn't take in account any rotation set with the setTransform() method. + + \sa setYRotation(), {Transformations} +*/ +qreal QGraphicsItem::yRotation() const +{ + if (!d_ptr->transformData) + return 0; + return d_ptr->transformData->yRotation; +} + +/*! + \since 4.6 + + Sets the rotation around the Y axis to \a angle degrees. + + \warning The value doesn't take in account any rotation set with the setTransform() method. + + \sa yRotation(), setTransformOrigin() {Transformations} +*/ +void QGraphicsItem::setYRotation(qreal angle) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->yRotation = angle; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + Returns the rotation around the Z axis. + + The default is 0 + + \warning The value doesn't take in account any rotation set with the setTransform() method. + + \sa setZRotation(), {Transformations} +*/ +qreal QGraphicsItem::zRotation() const +{ + if (!d_ptr->transformData) + return 0; + return d_ptr->transformData->zRotation; +} + +/*! + \since 4.6 + + Sets the rotation around the Z axis to \a angle degrees. + + \warning The value doesn't take in account any rotation set with the setTransform() method. + + \sa zRotation(), setTransformOrigin(), {Transformations} +*/ +void QGraphicsItem::setZRotation(qreal angle) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->zRotation = angle; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + This convenience function set the rotation angles around the 3 axes + to \a x, \a y and \a z. + + \sa setXRotation(), setYRotation(), setZRotation(), {Transformations} +*/ +void QGraphicsItem::setRotation(qreal x, qreal y, qreal z) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->xRotation = x; + d_ptr->transformData->yRotation = y; + d_ptr->transformData->zRotation = z; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + Returns the scale factor on the X axis. + + The default is 1 + + \warning The value doesn't take in account any scaling set with the setTransform() method. + + \sa setXScale(), {Transformations} +*/ +qreal QGraphicsItem::xScale() const +{ + if (!d_ptr->transformData) + return 1; + return d_ptr->transformData->xScale; +} + +/*! + \since 4.6 + + Sets the scale factor on the X axis to \a factor. + + \warning The value doesn't take in account any scaling set with the setTransform() method. + + \sa xScale(), setTransformOrigin(), {Transformations} +*/ +void QGraphicsItem::setXScale(qreal factor) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->xScale = factor; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + Returns the scale factor on the Y axis. + + The default is 1 + + \warning The value doesn't take in account any scaling set with the setTransform() method. + + \sa setYScale(), {Transformations} +*/ +qreal QGraphicsItem::yScale() const +{ + if (!d_ptr->transformData) + return 1; + return d_ptr->transformData->yScale; +} + +/*! + \since 4.6 + + Sets the scale factor on the Y axis to \a factor. + + \warning The value doesn't take in account any scaling set with the setTransform() method. + + \sa yScale(), setTransformOrigin(), {Transformations} +*/ +void QGraphicsItem::setYScale(qreal factor) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->yScale = factor; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + This convenience function set the scaling factors on X and Y axis to \a sx and \a sy. + + \warning The value doesn't take in account any scaling set with the setTransform() method. + + \sa setXScale(), setYScale(), {Transformations} +*/ +void QGraphicsItem::setScale(qreal sx, qreal sy) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->xScale = sx; + d_ptr->transformData->yScale = sy; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + Returns the horizontal shear. + + The default is 0 + + \warning The value doesn't take in account any shearing set with the setTransform() method. + + \sa setHorizontalShear(), {Transformations} +*/ +qreal QGraphicsItem::horizontalShear() const +{ + if (!d_ptr->transformData) + return 0; + return d_ptr->transformData->horizontalShear; +} + +/*! + \since 4.6 + + Sets the horizontal shear to \a shear. + + \warning The value doesn't take in account any shearing set with the setTransform() method. + + \sa horizontalShear(), {Transformations} +*/ +void QGraphicsItem::setHorizontalShear(qreal shear) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->horizontalShear = shear; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + Returns the vertical shear. + + The default is 0 + + \warning The value doesn't take in account any shearing set with the setTransform() method. + + \sa setHorizontalShear(), {Transformations} +*/ +qreal QGraphicsItem::verticalShear() const +{ + if (!d_ptr->transformData) + return 0; + return d_ptr->transformData->verticalShear; +} + +/*! + \since 4.6 + + Sets the vertical shear to \a shear. + + \warning The value doesn't take in account any shearing set with the setTransform() method. + + \sa verticalShear(), {Transformations} +*/ +void QGraphicsItem::setVerticalShear(qreal shear) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->verticalShear = shear; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + This convenience function sets the horizontal shear to \a sh and the vertical shear to \a sv. + + \warning The value doesn't take in account any shearing set with the setTransform() method. + + \sa setHorizontalShear(), setVerticalShear() +*/ +void QGraphicsItem::setShear(qreal sh, qreal sv) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->horizontalShear = sh; + d_ptr->transformData->verticalShear = sv; + d_ptr->dirtySceneTransform = 1; +} + +/*! + \since 4.6 + + Returns the origin point using for transformation in item coordinate. + + The default is QPointF(0,0). + + \sa setTransformOrigin(), {Transformations} +*/ +QPointF QGraphicsItem::transformOrigin() const +{ + if (!d_ptr->transformData) + return QPointF(0,0); + return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin); +} + +/*! + \since 4.6 + + Sets the origin for transformation in item coordinate + + \sa transformOrigin(), {Transformations} +*/ +void QGraphicsItem::setTransformOrigin(const QPointF &origin) +{ + prepareGeometryChange(); + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; + d_ptr->transformData->xOrigin = origin.x(); + d_ptr->transformData->yOrigin = origin.y(); + d_ptr->dirtySceneTransform = 1; +} + +/*! + \fn inline void setTransformOrigin(qreal x, qreal y) + + \since 4.6 + \overload + + \sa setTransformOrigin(), {Transformations} +*/ + + +/*! \obsolete Use sceneTransform() instead. @@ -2778,9 +3117,9 @@ QMatrix QGraphicsItem::sceneMatrix() const \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 4 Unlike transform(), which returns only an item's local transformation, this - function includes the item's (and any parents') position. + function includes the item's (and any parents') position, and all the transfomation properties. - \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System} + \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations} */ QTransform QGraphicsItem::sceneTransform() const { @@ -2848,7 +3187,8 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c // COMBINE QTransform matrix; matrix.translate(mappedPoint.x(), mappedPoint.y()); - matrix = untransformedAncestor->transform() * matrix; + if (untransformedAncestor->d_ptr->transformData) + matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform() * matrix; // Then transform and translate all children. for (int i = 0; i < parents.size(); ++i) { @@ -2904,7 +3244,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co // This is other's parent if (otherParent == this) { const QPointF &otherPos = other->d_ptr->pos; - if (other->d_ptr->transform) { + if (other->d_ptr->transformData) { QTransform otherToParent; other->d_ptr->combineTransformFromParent(&otherToParent); return otherToParent.inverted(ok); @@ -2919,7 +3259,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co // COMBINE const QPointF &itemPos = d_ptr->pos; const QPointF &otherPos = other->d_ptr->pos; - if (!d_ptr->transform && !other->d_ptr->transform) { + if (!d_ptr->transformData && !other->d_ptr->transformData) { QPointF delta = itemPos - otherPos; if (ok) *ok = true; @@ -2987,11 +3327,11 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co */ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) { - if (!d_ptr->transform) - d_ptr->transform = new QTransform; + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - QTransform newTransform(combine ? QTransform(matrix) * *d_ptr->transform : QTransform(matrix)); - if (*d_ptr->transform == newTransform) + QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix)); + if (d_ptr->transformData->transform == newTransform) return; // Notify the item that the transformation matrix is changing. @@ -2999,13 +3339,13 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) if (notify) { newTransform = QTransform(qVariantValue(itemChange(ItemMatrixChange, qVariantFromValue(newTransform.toAffine())))); - if (*d_ptr->transform == newTransform) + if (d_ptr->transformData->transform == newTransform) return; } // Update and set the new transformation. prepareGeometryChange(); - *d_ptr->transform = newTransform; + d_ptr->transformData->transform = newTransform; d_ptr->dirtySceneTransform = 1; // Send post-notification. @@ -3028,31 +3368,30 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) to map an item coordiate to a scene coordinate, or mapFromScene() to map from scene coordinates to item coordinates. - \warning using this function conflicts with using the transformation properties. - If you set a transformation, getting the properties will return default values. + \warning using this function doesnt affect the value of the transformation properties - \sa transform(), setRotation(), setScale(), setShear(), setTransformOrigin() {The Graphics View Coordinate System} + \sa transform(), setRotation(), setScale(), setShear(), setTransformOrigin(), {The Graphics View Coordinate System}, {Transformations} */ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) { - if (!d_ptr->transform) - d_ptr->transform = new QTransform; + if (!d_ptr->transformData) + d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - QTransform newTransform(combine ? matrix * *d_ptr->transform : matrix); - if (*d_ptr->transform == newTransform) + QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix); + if (d_ptr->transformData->transform == newTransform) return; // Notify the item that the transformation matrix is changing. bool notify = itemChangeEnabled(ItemTransformChange); if (notify) { newTransform = qVariantValue(itemChange(ItemTransformChange, qVariantFromValue(newTransform))); - if (*d_ptr->transform == newTransform) + if (d_ptr->transformData->transform == newTransform) return; } // Update and set the new transformation. prepareGeometryChange(); - *d_ptr->transform = newTransform; + d_ptr->transformData->transform = newTransform; d_ptr->dirtySceneTransform = 1; // Send post-notification. @@ -3096,8 +3435,7 @@ void QGraphicsItem::resetTransform() \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 6 - \warning using this function conflicts with using the transformation properties. - Getting those properties after using this function will return default values. + \warning using this functionhas no effect on the zRotation value \sa setTransform(), transform(), scale(), shear(), translate() */ @@ -3118,8 +3456,7 @@ void QGraphicsItem::rotate(qreal angle) \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7 - \warning using this function conflicts with using the transformation properties. - Getting those properties after using this function will return default values. + \warning using this function has no effect on the xScale or yScale value \sa setTransform(), transform() */ @@ -3134,8 +3471,7 @@ void QGraphicsItem::scale(qreal sx, qreal sy) Shears the current item transformation by (\a sh, \a sv). - \warning using this function conflicts with using the transformation properties. - Getting those properties after using this function will return default values. + \warning using this function has no effect on the horizontalShear or verticalShear value \sa setTransform(), transform() */ @@ -3154,9 +3490,6 @@ void QGraphicsItem::shear(qreal sh, qreal sv) setPos() instead; this function changes the item's translation, which is conceptually separate from its position. - \warning using this function conflicts with using the transformation properties. - Getting those properties after using this function will return default values. - \sa setTransform(), transform() */ void QGraphicsItem::translate(qreal dx, qreal dy) @@ -3330,7 +3663,7 @@ QRectF QGraphicsItem::sceneBoundingRect() const const QGraphicsItemPrivate *itemd; do { itemd = parentItem->d_ptr; - if (itemd->transform) + if (itemd->transformData) break; offset += itemd->pos; } while ((parentItem = itemd->parent)); @@ -4030,18 +4363,10 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n // Find closest clip ancestor and transform. Q_Q(QGraphicsItem); // COMBINE - QTransform thisToParentTransform = transform - ? *transform * QTransform::fromTranslate(newPos.x(), newPos.y()) - : QTransform::fromTranslate(newPos.x(), newPos.y()); + QTransform thisToParentTransform = transformToParent(); QGraphicsItem *clipParent = parent; while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) { - // COMBINE - if (clipParent->d_ptr->transform) - thisToParentTransform *= *clipParent->d_ptr->transform; - if (!clipParent->d_ptr->pos.isNull()) { - thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(), - clipParent->d_ptr->pos.y()); - } + thisToParentTransform *= clipParent->d_ptr->transformToParent(); clipParent = clipParent->d_ptr->parent; } @@ -4428,9 +4753,9 @@ QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point QPointF QGraphicsItem::mapToParent(const QPointF &point) const { // COMBINE - if (!d_ptr->transform) + if (!d_ptr->transformData) return point + d_ptr->pos; - return d_ptr->transform->map(point) + d_ptr->pos; + return d_ptr->transformToParent().map(point); } /*! @@ -4496,9 +4821,9 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const { // COMBINE - if (!d_ptr->transform) + if (!d_ptr->transformData) return rect.translated(d_ptr->pos); - return d_ptr->transform->map(rect).translated(d_ptr->pos); + return d_ptr->transformToParent().map(rect); } /*! @@ -4566,8 +4891,9 @@ QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rec QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const { // COMBINE - QRectF r = !d_ptr->transform ? rect : d_ptr->transform->mapRect(rect); - return r.translated(d_ptr->pos); + if (!d_ptr->transformData) + return rect.translated(d_ptr->pos); + return d_ptr->transformToParent().mapRect(rect); } /*! @@ -4639,8 +4965,9 @@ QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &r QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const { // COMBINE - QRectF r = rect.translated(-d_ptr->pos); - return d_ptr->transform ? d_ptr->transform->inverted().mapRect(r) : r; + if (!d_ptr->transformData) + return rect.translated(-d_ptr->pos); + return d_ptr->transformToParent().inverted().mapRect(rect); } /*! @@ -4700,9 +5027,9 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &p QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const { // COMBINE - if (!d_ptr->transform) + if (!d_ptr->transformData) return polygon.translated(d_ptr->pos); - return d_ptr->transform->map(polygon).translated(d_ptr->pos); + return d_ptr->transformToParent().map(polygon); } /*! @@ -4745,9 +5072,9 @@ QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterP QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const { // COMBINE - if (!d_ptr->transform) + if (!d_ptr->transformData) return path.translated(d_ptr->pos); - return d_ptr->transform->map(path).translated(d_ptr->pos); + return d_ptr->transformToParent().map(path); } /*! @@ -4797,8 +5124,8 @@ QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &poi QPointF QGraphicsItem::mapFromParent(const QPointF &point) const { // COMBINE - if (d_ptr->transform) - return d_ptr->transform->inverted().map(point - d_ptr->pos); + if (d_ptr->transformData) + return d_ptr->transformToParent().inverted().map(point); return point - d_ptr->pos; } @@ -4866,8 +5193,9 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &re QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const { // COMBINE - QRectF r = rect.translated(-d_ptr->pos); - return d_ptr->transform ? d_ptr->transform->inverted().map(r) : r; + if (!d_ptr->transformData) + return rect.translated(-d_ptr->pos); + return d_ptr->transformToParent().inverted().map(rect); } /*! @@ -4923,9 +5251,9 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPolygonF QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const { // COMBINE - QPolygonF p = polygon; - p.translate(-d_ptr->pos); - return d_ptr->transform ? d_ptr->transform->inverted().map(p) : p; + if (!d_ptr->transformData) + return polygon.translated(-d_ptr->pos); + return d_ptr->transformToParent().inverted().map(polygon); } /*! @@ -4966,9 +5294,9 @@ QPainterPath QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPainte QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const { // COMBINE - QPainterPath p(path); - p.translate(-d_ptr->pos); - return d_ptr->transform ? d_ptr->transform->inverted().map(p) : p; + if (!d_ptr->transformData) + return path.translated(-d_ptr->pos); + return d_ptr->transformToParent().inverted().map(path); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 7c87176..67b57e0 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -248,10 +248,39 @@ public: void setTransform(const QTransform &matrix, bool combine = false); void resetTransform(); - void rotate(qreal angle); - void scale(qreal sx, qreal sy); - void shear(qreal sh, qreal sv); - void translate(qreal dx, qreal dy); + void rotate(qreal angle); // ### obsolete + void scale(qreal sx, qreal sy); // ### obsolete + void shear(qreal sh, qreal sv); // ### obsolete + void translate(qreal dx, qreal dy); // ### obsolete + + qreal xRotation() const; + void setXRotation(qreal angle); + + qreal yRotation() const; + void setYRotation(qreal angle); + + qreal zRotation() const; + void setZRotation(qreal angle); + void setRotation(qreal x, qreal y, qreal z); + + qreal xScale() const; + void setXScale(qreal factor); + + qreal yScale() const; + void setYScale(qreal factor); + void setScale(qreal sx, qreal sy); + + qreal horizontalShear() const; + void setHorizontalShear(qreal shear); + + qreal verticalShear() const; + void setVerticalShear(qreal shear); + void setShear(qreal sh, qreal sv); + + QPointF transformOrigin() const; + void setTransformOrigin(const QPointF &origin); + inline void setTransformOrigin(qreal x, qreal y) + { setTransformOrigin(QPointF(x,y)); } virtual void advance(int phase); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index d884b16..62ef36a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -115,7 +115,7 @@ public: opacity(1.), scene(0), parent(0), - transform(0), + transformData(0), index(-1), depth(0), acceptedMouseButtons(0x1f), @@ -147,8 +147,8 @@ public: dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), - itemChangesEnabled(0xffff), geometryChanged(0), + itemChangesEnabled(0xffff), globalStackingOrder(-1), q_ptr(0) { @@ -352,6 +352,8 @@ public: || (childrenCombineOpacity() && isFullyTransparent()); } + inline QTransform transformToParent() const; + QPainterPath cachedClipPath; QRectF childrenBoundingRect; QRectF needsRepaint; @@ -362,7 +364,8 @@ public: QGraphicsScene *scene; QGraphicsItem *parent; QList children; - QTransform *transform; + class TransformData; + TransformData *transformData; QTransform sceneTransform; int index; int depth; @@ -399,16 +402,57 @@ public: quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; - quint32 itemChangesEnabled : 16; quint32 geometryChanged : 1; - quint32 padding : 2; // feel free to use + quint32 unused : 2; // feel free to use + quint32 itemChangesEnabled : 16; // Optional stacking order int globalStackingOrder; - QGraphicsItem *q_ptr; }; +struct QGraphicsItemPrivate::TransformData { + QTransform transform; + qreal xScale; + qreal yScale; + qreal xRotation; + qreal yRotation; + qreal zRotation; + qreal horizontalShear; + qreal verticalShear; + qreal xOrigin; + qreal yOrigin; + + TransformData() : + xScale(1.0), yScale(1.0), xRotation(0.0), yRotation(0.0), zRotation(0.0), + horizontalShear(0.0), verticalShear(0.0), xOrigin(0.0), yOrigin(0.0) + {} + + QTransform computedFullTransform() const + { + QTransform x; + x.translate(xOrigin, yOrigin); + x = transform * x; + x.rotate(xRotation, Qt::XAxis); + x.rotate(yRotation, Qt::YAxis); + x.rotate(zRotation, Qt::ZAxis); + x.shear(horizontalShear, verticalShear); + x.scale(xScale, yScale); + x.translate(-xOrigin, -yOrigin); + return x; + } +}; + +/* + return the full transform of the item to the parent. This include the position and all the transform data +*/ +inline QTransform QGraphicsItemPrivate::transformToParent() const +{ + QTransform matrix; + combineTransformToParent(&matrix); + return matrix; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ad392b0..1014550 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1737,7 +1737,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) + if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) continue; // Skip invisible items and all their children. @@ -1777,7 +1777,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) + if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) continue; // Skip invisible items and all their children. @@ -1813,7 +1813,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { // Recurse into children. - if (!item->d_ptr->transform || item->d_ptr->transform->type() <= QTransform::TxScale) { + if (!item->d_ptr->transformData || item->d_ptr->transformData->computedFullTransform().type() <= QTransform::TxScale) { // Rect childItems_helper(items, item, item->mapRectFromParent(rect), mode); } else { @@ -1843,7 +1843,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) + if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) continue; // Skip invisible items. @@ -1902,7 +1902,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); - if (item->d_ptr->transform && !item->d_ptr->transform->isInvertible()) + if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) continue; // Skip invisible items. diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a9fc563..166bcb9 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -752,7 +752,7 @@ QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRect const QGraphicsItemPrivate *itemd; do { itemd = parentItem->d_ptr; - if (itemd->transform) + if (itemd->transformData) break; offset += itemd->pos; } while ((parentItem = itemd->parent)); diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index 34f1c5f..a5c9068 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -81,7 +81,14 @@ class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, publi Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) Q_PROPERTY(QPointF pos READ pos WRITE setPos) Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry) - + Q_PROPERTY(QPointF transformOrigin READ transformOrigin WRITE setTransformOrigin) + Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation) + Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation) + Q_PROPERTY(qreal zRotation READ zRotation WRITE setZRotation) + Q_PROPERTY(qreal xScale READ xScale WRITE setXScale) + Q_PROPERTY(qreal yScale READ yScale WRITE setYScale) + Q_PROPERTY(qreal horizontalShear READ horizontalShear WRITE setHorizontalShear) + Q_PROPERTY(qreal verticalShear READ verticalShear WRITE setVerticalShear) public: QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); ~QGraphicsWidget(); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 41593b5..82c173b 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -220,6 +220,8 @@ private slots: void deviceTransform_data(); void deviceTransform(); void update(); + void setTransformProperties_data(); + void setTransformProperties(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -6484,5 +6486,202 @@ void tst_QGraphicsItem::update() QCOMPARE(view.paintedRegion, expectedRegion); } +void tst_QGraphicsItem::setTransformProperties_data() +{ + QTest::addColumn("origin"); + QTest::addColumn("rotationX"); + QTest::addColumn("rotationY"); + QTest::addColumn("rotationZ"); + QTest::addColumn("scaleX"); + QTest::addColumn("scaleY"); + QTest::addColumn("shearX"); + QTest::addColumn("shearY"); + + QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) + << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + + QTest::newRow("rotationZ") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(42.2) + << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + + QTest::newRow("rotationXY") << QPointF() << qreal(12.5) << qreal(53.6) << qreal(0.0) + << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + + QTest::newRow("rotationXYZ") << QPointF() << qreal(-25) << qreal(12) << qreal(556) + << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + + QTest::newRow("rotationXYZ dicentred") << QPointF(-53, 25.2) + << qreal(-2578.2) << qreal(4565.2) << qreal(56) + << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + + QTest::newRow("Scale") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) + << qreal(6) << qreal(0.5) << qreal(0.0) << qreal(0.0); + + QTest::newRow("Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) + << qreal(1.0) << qreal(1.0) << qreal(2.2) << qreal(0.5); + + QTest::newRow("Scale and Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) + << qreal(5.2) << qreal(2.1) << qreal(5.2) << qreal(5.5); + + QTest::newRow("Everything") << QPointF() << qreal(41) << qreal(-23) << qreal(0.56) + << qreal(8.2) << qreal(-0.2) << qreal(-12) << qreal(-0.8); + + QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196) << qreal(-1260) + << qreal(4) << qreal(2) << qreal(2.56) << qreal(0.8); +} + +/** + * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare + */ +#define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity()) + +void tst_QGraphicsItem::setTransformProperties() +{ + QFETCH(QPointF,origin); + QFETCH(qreal,rotationX); + QFETCH(qreal,rotationY); + QFETCH(qreal,rotationZ); + QFETCH(qreal,scaleX); + QFETCH(qreal,scaleY); + QFETCH(qreal,shearX); + QFETCH(qreal,shearY); + + QTransform result; + result.translate(origin.x(), origin.y()); + result.rotate(rotationX, Qt::XAxis); + result.rotate(rotationY, Qt::YAxis); + result.rotate(rotationZ, Qt::ZAxis); + result.shear(shearX, shearY); + result.scale(scaleX, scaleY); + result.translate(-origin.x(), -origin.y()); + + QGraphicsScene scene; + QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); + scene.addItem(item); + + item->setRotation(rotationX, rotationY, rotationZ); + item->setScale(scaleX, scaleY); + item->setShear(shearX, shearY); + item->setTransformOrigin(origin); + + QCOMPARE(item->xRotation(), rotationX); + QCOMPARE(item->yRotation(), rotationY); + QCOMPARE(item->zRotation(), rotationZ); + QCOMPARE(item->xScale(), scaleX); + QCOMPARE(item->yScale(), scaleY); + QCOMPARE(item->horizontalShear(), shearX); + QCOMPARE(item->verticalShear(), shearY); + QCOMPARE(item->transformOrigin(), origin); + + QCOMPARE(QTransform(), item->transform()); + QCOMPARE(result, item->sceneTransform()); + + //----------------------------------------------------------------- + //Change the rotation Z + item->setZRotation(45); + QTransform result2; + result2.translate(origin.x(), origin.y()); + result2.rotate(rotationX, Qt::XAxis); + result2.rotate(rotationY, Qt::YAxis); + result2.rotate(45, Qt::ZAxis); + result2.shear(shearX, shearY); + result2.scale(scaleX, scaleY); + result2.translate(-origin.x(), -origin.y()); + + QCOMPARE(item->xRotation(), rotationX); + QCOMPARE(item->yRotation(), rotationY); + QCOMPARE(item->zRotation(), 45.0); + QCOMPARE(item->xScale(), scaleX); + QCOMPARE(item->yScale(), scaleY); + QCOMPARE(item->horizontalShear(), shearX); + QCOMPARE(item->verticalShear(), shearY); + QCOMPARE(item->transformOrigin(), origin); + + QCOMPARE(QTransform(), item->transform()); + QCOMPARE(result2, item->sceneTransform()); + + //----------------------------------------------------------------- + // calling setTransform() and setPos shoukld change the sceneTransform + item->setTransform(result); + item->setPos(100, -150.5); + + QCOMPARE(item->xRotation(), rotationX); + QCOMPARE(item->yRotation(), rotationY); + QCOMPARE(item->zRotation(), 45.0); + QCOMPARE(item->xScale(), scaleX); + QCOMPARE(item->yScale(), scaleY); + QCOMPARE(item->horizontalShear(), shearX); + QCOMPARE(item->verticalShear(), shearY); + QCOMPARE(item->transformOrigin(), origin); + QCOMPARE(result, item->transform()); + + QTransform result3; + + result3.translate(origin.x(), origin.y()); + result3 = result * result3; + result3.rotate(rotationX, Qt::XAxis); + result3.rotate(rotationY, Qt::YAxis); + result3.rotate(45, Qt::ZAxis); + result3.shear(shearX, shearY); + result3.scale(scaleX, scaleY); + result3.translate(-origin.x(), -origin.y()); + + result3 *= QTransform::fromTranslate(100, -150.5); //the pos; + + QCOMPARE(result3, item->sceneTransform()); + + //----------------------------------------------------- + // setting the propertiees should be the same as setting a transform + {//with center origin on the matrix + QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); + scene.addItem(item1); + QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); + scene.addItem(item2); + + item1->setPos(12.3, -5); + item2->setPos(12.3, -5); + item1->setRotation(rotationX, rotationY, rotationZ); + item1->setScale(scaleX, scaleY); + item1->setShear(shearX, shearY); + item1->setTransformOrigin(origin); + + item2->setTransform(result); + + QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform()); + + QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform()); + QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform()); + } + + {//with center origin on the item + QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); + scene.addItem(item1); + QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); + scene.addItem(item2); + + item1->setPos(12.3, -5); + item2->setPos(12.3, -5); + item1->setTransformOrigin(origin); + item2->setTransformOrigin(origin); + + item1->setRotation(rotationX, rotationY, rotationZ); + item1->setScale(scaleX, scaleY); + item1->setShear(shearX, shearY); + + QTransform tr; + tr.rotate(rotationX, Qt::XAxis); + tr.rotate(rotationY, Qt::YAxis); + tr.rotate(rotationZ, Qt::ZAxis); + tr.shear(shearX, shearY); + tr.scale(scaleX, scaleY); + + item2->setTransform(tr); + + QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform()); + + QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform()); + QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform()); + } +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 9ba5a561b017ec028d675627df2eda5b13e3a6fc Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Mon, 8 Jun 2009 14:49:44 +0200 Subject: Fix two regressions in Plasma. The painter state proctection was not properly pass to drawItemHelper. The second is a double conversion to deviceTransform in createStyleOption of QGraphicsItem. Since the recursive drawing already give a transform in device mode we don't need to convert it two times. Reviewed-by:andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 6 +-- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 53 ++++++++++++++++++++++ tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 36 +++++++++++++++ 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index d962554..7f22c80 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1016,14 +1016,12 @@ void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, con return; // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect). - - const QTransform itemToViewportTransform = q->deviceTransform(worldTransform); - option->matrix = itemToViewportTransform.toAffine(); //### discards perspective + option->matrix = worldTransform.toAffine(); //### discards perspective if (!allItems) { // Determine the item's exposed area option->exposedRect = QRectF(); - const QTransform reverseMap = itemToViewportTransform.inverted(); + const QTransform reverseMap = worldTransform.inverted(); const QVector exposedRects(exposedRegion.rects()); for (int i = 0; i < exposedRects.size(); ++i) { option->exposedRect |= reverseMap.mapRect(exposedRects.at(i)); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 1014550..28d65da 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5254,7 +5254,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - drawItemHelper(item, painter, &styleOptionTmp, widget, false); + drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); if (savePainter) painter->restore(); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 82c173b..7a789c5 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -222,6 +223,7 @@ private slots: void update(); void setTransformProperties_data(); void setTransformProperties(); + void itemUsesExtendedStyleOption(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -6449,6 +6451,7 @@ void tst_QGraphicsItem::update() { QGraphicsScene scene; MyGraphicsView view(&scene); + view.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); @@ -6683,5 +6686,55 @@ void tst_QGraphicsItem::setTransformProperties() } } +class MyStyleOptionTester : public QGraphicsRectItem +{ +public: + MyStyleOptionTester(const QRectF &rect) + : QGraphicsRectItem(rect), startTrack(false) + {} + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) + { + if (startTrack) { + //Doesn't use the extended style option so the exposed rect is the boundingRect + if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) { + QCOMPARE(option->exposedRect, boundingRect()); + } else { + QVERIFY(option->exposedRect != QRect()); + QVERIFY(option->exposedRect != boundingRect()); + } + } + QGraphicsRectItem::paint(painter, option, widget); + } + bool startTrack; +}; + +void tst_QGraphicsItem::itemUsesExtendedStyleOption() +{ + QGraphicsScene scene(0, 0, 300, 300); + QGraphicsPixmapItem item; + item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); + QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption)); + item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); + QCOMPARE(item.flags(), 0); + + //We now test the content of the style option + MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100)); + scene.addItem(rect); + rect->setPos(200, 200); + QGraphicsView view(&scene); + QTest::qWait(500); + rect->startTrack = true; + rect->update(10, 10, 10, 10); + QTest::qWait(125); + rect->startTrack = false; + rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); + QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption)); + QTest::qWait(125); + rect->startTrack = true; + rect->update(10, 10, 10, 10); + QTest::qWait(125); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 56d42c3..00f3155 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -155,6 +155,7 @@ private slots: void windowFlags_data(); void windowFlags(); void shortcutsDeletion(); + void painterStateProtectionOnWindowFrame(); // Task fixes void task236127_bspTreeIndexFails(); @@ -2282,6 +2283,41 @@ void tst_QGraphicsWidget::shortcutsDeletion() delete widget; } +class MessUpPainterWidget : public QGraphicsWidget +{ +public: + MessUpPainterWidget(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0) + : QGraphicsWidget(parent, wFlags) + {} + + void paintWindowFrame(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + QCOMPARE(painter->opacity(), 1.0); + painter->setOpacity(0.0); + QGraphicsWidget::paintWindowFrame(painter, option, widget); + } + void paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + QCOMPARE(painter->opacity(), 1.0); + painter->drawRect(0, 0, 100, 100); + QGraphicsWidget::paint(painter, option, widget); + } + +}; + +void tst_QGraphicsWidget::painterStateProtectionOnWindowFrame() +{ + MessUpPainterWidget *widget = new MessUpPainterWidget(0, Qt::Window); + QGraphicsScene scene(0, 0, 300, 300); + QGraphicsView view(&scene); + scene.addItem(widget); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(500); +} + class ProxyStyle : public QCommonStyle { public: -- cgit v0.12 From e8e1cdaea063dc3613b38315ca401ef55340fcbb Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 8 Jun 2009 17:14:10 +0200 Subject: Revert "Add QGraphicsItem::itemChangeEnabled()." This reverts commit 0fc58ca3220083b9e10f88aab2e39824c2764db3. Conflicts: src/gui/graphicsview/qgraphicsitem.cpp src/gui/graphicsview/qgraphicsitem_p.h --- src/gui/graphicsview/qgraphicsitem.cpp | 240 ++++++++++---------------------- src/gui/graphicsview/qgraphicsitem.h | 5 - src/gui/graphicsview/qgraphicsitem_p.h | 4 +- src/gui/graphicsview/qgraphicsscene.cpp | 30 ++-- 4 files changed, 81 insertions(+), 198 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7f22c80..6679bd5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -39,6 +39,8 @@ ** ****************************************************************************/ +#define QGRAPHICSITEM_NO_ITEMCHANGE + /*! \class QGraphicsItem \brief The QGraphicsItem class is the base class for all graphical @@ -844,13 +846,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de if (newParent == parent) return; - bool notify = q->itemChangeEnabled(QGraphicsItem::ItemParentChange); - if (notify) { - newParent = qVariantValue(q->itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue(newParent))); - if (newParent == parent) - return; - } + const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange, + qVariantFromValue(newParent))); + newParent = qVariantValue(newParentVariant); + if (newParent == parent) + return; if (QGraphicsWidget *w = isWidget ? static_cast(q) : q->parentWidget()) { // Update the child focus chain; when reparenting a widget that has a @@ -950,8 +950,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de dirtySceneTransform = 1; // Deliver post-change notification - if (notify) - q->itemChange(QGraphicsItem::ItemParentHasChanged, qVariantFromValue(newParent)); + q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); } /*! @@ -1379,14 +1378,9 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) // Notify change and check for adjustment. if (quint32(d_ptr->flags) == quint32(flags)) return; - - // Notify - bool notify = itemChangeEnabled(ItemFlagsChange); - if (notify) { - flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); - if (quint32(d_ptr->flags) == quint32(flags)) - return; - } + flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); + if (quint32(d_ptr->flags) == quint32(flags)) + return; // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); @@ -1442,78 +1436,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) } // Notify change. - if (notify) - itemChange(ItemFlagsHaveChanged, quint32(flags)); -} - -static const int itemChangeBits[] = { - /* ItemPositionChange */ 1 << 1, - /* ItemMatrixChange */ 1 << 2, - /* ItemVisibleChange */ 1 << 3, - /* ItemEnabledChange */ 1 << 4, - /* ItemSelectedChange */ 1 << 5, - /* ItemParentChange */ 1 << 6, - /* ItemChildAddedChange */ 1 << 7, - /* ItemChildRemovedChange */ 1 << 8, - /* ItemTransformChange */ 1 << 9, - /* ItemPositionHasChanged */ 1 << 1, - /* ItemTransformHasChanged */ 1 << 9, - /* ItemSceneChange */ 1 << 10, - /* ItemVisibleHasChanged */ 1 << 3, - /* ItemEnabledHasChanged */ 1 << 4, - /* ItemSelectedHasChanged */ 1 << 5, - /* ItemParentHasChanged */ 1 << 6, - /* ItemSceneHasChanged */ 1 << 10, - /* ItemCursorChange */ 1 << 11, - /* ItemCursorHasChanged */ 1 << 11, - /* ItemToolTipChange */ 1 << 12, - /* ItemToolTipHasChanged */ 1 << 12, - /* ItemFlagsChange */ 1 << 13, - /* ItemFlagsHaveChanged */ 1 << 13, - /* ItemZValueChange */ 1 << 14, - /* ItemZValueHasChanged */ 1 << 14, - /* ItemOpacityChange */ 1 << 15, - /* ItemOpacityHasChanged */ 1 << 15 -}; - -/*! - Returns true if \a change is enabled (i.e., QGraphicsItem will call - itemChange() whenever the respective change occurs); otherwise returns - false. - - \sa setItemChangeEnabled(), setItemChangesEnabled(), itemChange() -*/ -bool QGraphicsItem::itemChangeEnabled(GraphicsItemChange change) const -{ - return d_ptr->itemChangesEnabled & itemChangeBits[change]; -} - -/*! - If \a enabled is true, notifications for \a change are enabled; otherwise - they are disabled. By default, QGraphicsItem sends notifications for all - changes by calling itemChange(). - - \sa itemChangeEnabled(), setItemChangesEnabled(), itemChange() -*/ -void QGraphicsItem::setItemChangeEnabled(GraphicsItemChange change, bool enabled) -{ - if (enabled) { - d_ptr->itemChangesEnabled |= itemChangeBits[change]; - } else { - d_ptr->itemChangesEnabled &= itemChangeBits[change]; - } -} - -/*! - If \a enabled is true, all item change notifications are enabled; - otherwise, they are disabled. You can toggle individual notifications by - calling setItemChangeEnabled(). - - \sa itemChangeEnabled(), itemChange() -*/ -void QGraphicsItem::setItemChangesEnabled(bool enabled) -{ - d_ptr->itemChangesEnabled = enabled ? 0xffff : 0; + itemChange(ItemFlagsHaveChanged, quint32(flags)); } /*! @@ -1602,13 +1525,9 @@ QString QGraphicsItem::toolTip() const */ void QGraphicsItem::setToolTip(const QString &toolTip) { - bool notify = itemChangeEnabled(ItemToolTipChange); - QVariant toolTipVariant = toolTip; - if (notify) - toolTipVariant = itemChange(ItemToolTipChange, toolTipVariant); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant); - if (notify) - itemChange(ItemToolTipHasChanged, toolTipVariant); + const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip)); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString()); + itemChange(ItemToolTipHasChanged, toolTipVariant); } #endif // QT_NO_TOOLTIP @@ -1650,11 +1569,8 @@ QCursor QGraphicsItem::cursor() const */ void QGraphicsItem::setCursor(const QCursor &cursor) { - bool notify = itemChangeEnabled(ItemCursorChange); - QVariant cursorVariant = qVariantFromValue(cursor); - if (notify) - cursorVariant = itemChange(ItemCursorChange, cursorVariant); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, cursorVariant); + const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue(cursor))); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue(cursorVariant)); d_ptr->hasCursor = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; @@ -1673,8 +1589,7 @@ void QGraphicsItem::setCursor(const QCursor &cursor) } } } - if (notify) - itemChange(ItemCursorHasChanged, cursorVariant); + itemChange(ItemCursorHasChanged, cursorVariant); } /*! @@ -1771,12 +1686,10 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo if (parent && newVisible && !parent->d_ptr->visible) return; - // Notify - bool notify = q->itemChangeEnabled(QGraphicsItem::ItemVisibleChange); - if (notify) - newVisible = q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, quint32(newVisible)).toBool(); - // Modify the property. + const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, + quint32(newVisible))); + newVisible = newVisibleVariant.toBool(); if (visible == quint32(newVisible)) return; visible = newVisible; @@ -1843,8 +1756,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Deliver post-change notification. - if (notify) - q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisible); + q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant); } /*! @@ -1950,10 +1862,9 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Modify the property. - bool notify = q_ptr->itemChangeEnabled(QGraphicsItem::ItemEnabledChange); - if (notify) - newEnabled = q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, quint32(newEnabled)).toBool(); - enabled = newEnabled; + const QVariant newEnabledVariant(q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, + quint32(newEnabled))); + enabled = newEnabledVariant.toBool(); // Schedule redraw. if (update && scene) @@ -1965,8 +1876,7 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Deliver post-change notification. - if (notify) - q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabled); + q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant); } /*! @@ -2053,13 +1963,10 @@ void QGraphicsItem::setSelected(bool selected) selected = false; if (d_ptr->selected == selected) return; - bool notify = itemChangeEnabled(ItemSelectedChange); - bool newSelected = selected; - if (notify) { - newSelected = itemChange(ItemSelectedChange, quint32(selected)).toBool(); - if (d_ptr->selected == newSelected) - return; - } + const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected))); + bool newSelected = newSelectedVariant.toBool(); + if (d_ptr->selected == newSelected) + return; d_ptr->selected = newSelected; if (d_ptr->scene) { @@ -2076,8 +1983,7 @@ void QGraphicsItem::setSelected(bool selected) } // Deliver post-change notification. - if (notify) - itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelected); + itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant); } /*! @@ -2143,12 +2049,13 @@ qreal QGraphicsItem::effectiveOpacity() const */ void QGraphicsItem::setOpacity(qreal opacity) { + // Notify change. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE + const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity))); + qreal newOpacity = newOpacityVariant.toDouble(); +#else qreal newOpacity = opacity; - - // Notify - bool notify = itemChangeEnabled(ItemOpacityChange); - if (notify) - newOpacity = itemChange(ItemOpacityChange, double(newOpacity)).toDouble(); +#endif // Normalize. newOpacity = qBound(0.0, newOpacity, 1.0); @@ -2159,9 +2066,10 @@ void QGraphicsItem::setOpacity(qreal opacity) d_ptr->opacity = newOpacity; - // Notify - if (notify) - itemChange(ItemOpacityHasChanged, newOpacity); + // Notify change. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE + itemChange(ItemOpacityHasChanged, newOpacity); +#endif // Update. if (d_ptr->scene) @@ -2610,15 +2518,15 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) if (this->pos == pos) return; + // Notify the item that the position is changing. +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE + const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos)); + QPointF newPos = newPosVariant.toPointF(); + if (newPos == this->pos) + return; +#else QPointF newPos = pos; - - // Notify - bool notify = q->itemChangeEnabled(QGraphicsItem::ItemPositionChange); - if (notify) { - newPos = q->itemChange(QGraphicsItem::ItemPositionChange, pos).toPointF(); - if (newPos == this->pos) - return; - } +#endif // Update and repositition. inSetPosHelper = 1; @@ -2629,9 +2537,9 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) dirtySceneTransform = 1; // Send post-notification. - if (notify) - q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPos); - +#ifndef QGRAPHICSITEM_NO_ITEMCHANGE + q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); +#endif inSetPosHelper = 0; } @@ -3333,13 +3241,11 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) return; // Notify the item that the transformation matrix is changing. - bool notify = itemChangeEnabled(ItemMatrixChange); - if (notify) { - newTransform = QTransform(qVariantValue(itemChange(ItemMatrixChange, - qVariantFromValue(newTransform.toAffine())))); - if (d_ptr->transformData->transform == newTransform) - return; - } + const QVariant newTransformVariant(itemChange(ItemTransformChange, + qVariantFromValue(newTransform))); + newTransform = qVariantValue(newTransformVariant); + if (d_ptr->transformData->transform == newTransform) + return; // Update and set the new transformation. prepareGeometryChange(); @@ -3347,8 +3253,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->dirtySceneTransform = 1; // Send post-notification. - if (notify) - itemChange(ItemTransformHasChanged, qVariantFromValue(newTransform)); + itemChange(ItemTransformHasChanged, newTransformVariant); } /*! @@ -3380,12 +3285,12 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) return; // Notify the item that the transformation matrix is changing. - bool notify = itemChangeEnabled(ItemTransformChange); - if (notify) { - newTransform = qVariantValue(itemChange(ItemTransformChange, qVariantFromValue(newTransform))); - if (d_ptr->transformData->transform == newTransform) - return; - } + // Notify the item that the transformation matrix is changing. + const QVariant newTransformVariant(itemChange(ItemTransformChange, + qVariantFromValue(newTransform))); + newTransform = qVariantValue(newTransformVariant); + if (d_ptr->transformData->transform == newTransform) + return; // Update and set the new transformation. prepareGeometryChange(); @@ -3393,8 +3298,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) d_ptr->dirtySceneTransform = 1; // Send post-notification. - if (notify) - itemChange(ItemTransformHasChanged, qVariantFromValue(newTransform)); + itemChange(ItemTransformHasChanged, newTransformVariant); } /*! @@ -3561,13 +3465,10 @@ qreal QGraphicsItem::zValue() const */ void QGraphicsItem::setZValue(qreal z) { - bool notify = itemChangeEnabled(ItemZValueChange); - qreal newZ = z; - if (notify) { - newZ = itemChange(ItemZValueChange, double(z)).toDouble(); - if (newZ == d_ptr->z) - return; - } + const QVariant newZVariant(itemChange(ItemZValueChange, double(z))); + qreal newZ = qreal(newZVariant.toDouble()); + if (newZ == d_ptr->z) + return; d_ptr->z = newZ; if (d_ptr->parent) d_ptr->parent->d_ptr->needSortChildren = 1; @@ -3581,8 +3482,7 @@ void QGraphicsItem::setZValue(qreal z) d_ptr->scene->d_func()->invalidateSortCache(); } - if (notify) - itemChange(ItemZValueHasChanged, newZ); + itemChange(ItemZValueHasChanged, newZVariant); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 67b57e0..7e33c83 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -129,7 +129,6 @@ public: ItemZValueHasChanged, ItemOpacityChange, ItemOpacityHasChanged - // NB! Don't forget to increase d_ptr->itemChangesEnabled when adding a new entry. }; enum CacheMode { @@ -166,10 +165,6 @@ public: void setFlag(GraphicsItemFlag flag, bool enabled = true); void setFlags(GraphicsItemFlags flags); - bool itemChangeEnabled(GraphicsItemChange change) const; - void setItemChangeEnabled(GraphicsItemChange change, bool enabled); - void setItemChangesEnabled(bool enabled); - CacheMode cacheMode() const; void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize()); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 62ef36a..13fee8f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -148,7 +148,6 @@ public: paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), geometryChanged(0), - itemChangesEnabled(0xffff), globalStackingOrder(-1), q_ptr(0) { @@ -403,8 +402,7 @@ public: quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; quint32 geometryChanged : 1; - quint32 unused : 2; // feel free to use - quint32 itemChangesEnabled : 16; + quint32 unused : 17; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 28d65da..54fead1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -662,10 +662,8 @@ void QGraphicsScenePrivate::_q_polishItems() const QVariant booleanTrueVariant(true); foreach (QGraphicsItem *item, unpolishedItems) { if (!item->d_ptr->explicitlyHidden) { - if (item->itemChangeEnabled(QGraphicsItem::ItemVisibleChange)) { - item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); - item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); - } + item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); + item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); } if (item->isWidget()) { QEvent event(QEvent::Polish); @@ -2969,12 +2967,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. - QGraphicsScene *targetScene = this; - bool notify = item->itemChangeEnabled(QGraphicsItem::ItemSceneChange); - if (notify) { - targetScene = qVariantValue(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue(this))); - } + const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue(this))); + QGraphicsScene *targetScene = qVariantValue(newSceneVariant); if (targetScene != this) { if (targetScene && item->scene() != targetScene) targetScene->addItem(item); @@ -3085,8 +3080,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - if (notify) - item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue(targetScene)); + item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); } /*! @@ -3350,12 +3344,9 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Notify the item that it's scene is changing to 0, allowing the item to // react. - QGraphicsScene *targetScene = 0; - bool notify = item->itemChangeEnabled(QGraphicsItem::ItemSceneChange); - if (notify) { - targetScene = qVariantValue(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue(0))); - } + const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue(0))); + QGraphicsScene *targetScene = qVariantValue(newSceneVariant); if (targetScene != 0 && targetScene != this) { targetScene->addItem(item); return; @@ -3452,8 +3443,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - if (notify) - item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue(targetScene)); + item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); } /*! -- cgit v0.12 From c07239ac97dfce35a6b277c82ec5445e01eb2249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 8 Jun 2009 14:15:22 +0200 Subject: Add another auto-test ensuring updates outside the brect are discared. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 7a789c5..35a7bb9 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -6487,6 +6487,14 @@ void tst_QGraphicsItem::update() const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // The entire item's bounding rect (adjusted for antialiasing) should have been painted. QCOMPARE(view.paintedRegion, expectedRegion); + + // Make sure update requests outside the bounding rect are discarded. + view.reset(); + item->repaints = 0; + item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20) + qApp->processEvents(); + QCOMPARE(item->repaints, 0); + QCOMPARE(view.repaints, 0); } void tst_QGraphicsItem::setTransformProperties_data() -- cgit v0.12 From 8a5a52e95a8ec81ce4bc3bb0599cfab510c8400a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 8 Jun 2009 17:33:11 +0200 Subject: Auto-test to ensure moved items don't leave traces. See also: 1c9032f29d4500b33622d7510b6361c99d9af296 --- src/gui/graphicsview/qgraphicsscene.cpp | 3 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 78 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 54fead1..7038c3d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5156,8 +5156,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QRectF brect = item->boundingRect(); // ### This does not take the clip into account. _q_adjustRect(&brect); - viewBoundingRect = transformTmp.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); + viewBoundingRect = transformTmp.mapRect(brect).toRect(); item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); + viewBoundingRect.adjust(-1, -1, 1, 1); if (exposedRegion) viewBoundingRect &= exposedRegion->boundingRect(); } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 35a7bb9..c6f9824 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -224,6 +224,7 @@ private slots: void setTransformProperties_data(); void setTransformProperties(); void itemUsesExtendedStyleOption(); + void moveItem(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -6744,5 +6745,82 @@ void tst_QGraphicsItem::itemUsesExtendedStyleOption() QTest::qWait(125); } +// Make sure we update moved items correctly. +void tst_QGraphicsItem::moveItem() +{ + QGraphicsScene scene; + scene.setSceneRect(-50, -50, 200, 200); + + MyGraphicsView view(&scene); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(100); + + EventTester *parent = new EventTester; + EventTester *child = new EventTester(parent); + EventTester *grandChild = new EventTester(child); + +#define RESET_COUNTERS \ + parent->repaints = 0; \ + child->repaints = 0; \ + grandChild->repaints = 0; \ + view.reset(); + + scene.addItem(parent); + QTest::qWait(100); + + RESET_COUNTERS + + // Item's boundingRect: (-10, -10, 20, 20). + QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform()) + .mapRect(parent->boundingRect()).toRect() + .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing. + + parent->setPos(20, 20); + qApp->processEvents(); + QCOMPARE(parent->repaints, 1); + QCOMPARE(view.repaints, 1); + QRegion expectedParentRegion = parentDeviceBoundingRect; // old position + parentDeviceBoundingRect.translate(20, 20); + expectedParentRegion += parentDeviceBoundingRect; // new position + QCOMPARE(view.paintedRegion, expectedParentRegion); + + RESET_COUNTERS + + child->setPos(20, 20); + qApp->processEvents(); + QCOMPARE(parent->repaints, 1); + QCOMPARE(child->repaints, 1); + QCOMPARE(view.repaints, 1); + const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20); + QCOMPARE(view.paintedRegion, expectedChildRegion); + + RESET_COUNTERS + + grandChild->setPos(20, 20); + qApp->processEvents(); + QCOMPARE(parent->repaints, 1); + QCOMPARE(child->repaints, 1); + QCOMPARE(grandChild->repaints, 1); + QCOMPARE(view.repaints, 1); + const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40); + QCOMPARE(view.paintedRegion, expectedGrandChildRegion); + + RESET_COUNTERS + + parent->translate(20, 20); + qApp->processEvents(); + QCOMPARE(parent->repaints, 1); + QCOMPARE(child->repaints, 1); + QCOMPARE(grandChild->repaints, 1); + QCOMPARE(view.repaints, 1); + expectedParentRegion.translate(20, 20); + expectedParentRegion += expectedChildRegion.translated(20, 20); + expectedParentRegion += expectedGrandChildRegion.translated(20, 20); + QCOMPARE(view.paintedRegion, expectedParentRegion); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 50ddb3451007a94d87c064216603a3e3e6e8b9c6 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 8 Jun 2009 18:58:57 +0200 Subject: Add ItemSendsGeometryChanges, replacing itemChangeEnabled(). This flag toggles whether we should send notifications for setPos, setMatrix, and setTransform. It's off by default. Docs have been updated. All autotests pass. This change also cleans up a bit so that we both have readable code, and keeping the optimized path for when we need to send the notifications. By enabling this flag by default we are going to trigger regressions in end-user code. Reviewed-by: bnilsen --- examples/graphicsview/elasticnodes/node.cpp | 1 + src/gui/graphicsview/qgraphicsitem.cpp | 161 ++++++++++++++----------- src/gui/graphicsview/qgraphicsitem.h | 3 +- src/gui/graphicsview/qgraphicsitem_p.h | 5 +- src/gui/graphicsview/qgraphicswidget.cpp | 3 + src/gui/graphicsview/qgraphicswidget_p.cpp | 2 + tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 58 ++++++++- 7 files changed, 158 insertions(+), 75 deletions(-) diff --git a/examples/graphicsview/elasticnodes/node.cpp b/examples/graphicsview/elasticnodes/node.cpp index 6942fa0..53fe994 100644 --- a/examples/graphicsview/elasticnodes/node.cpp +++ b/examples/graphicsview/elasticnodes/node.cpp @@ -52,6 +52,7 @@ Node::Node(GraphWidget *graphWidget) : graph(graphWidget) { setFlag(ItemIsMovable); + setFlag(ItemSendsGeometryChanges); setCacheMode(DeviceCoordinateCache); setZValue(1); } diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 6679bd5..3138faa 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -#define QGRAPHICSITEM_NO_ITEMCHANGE - /*! \class QGraphicsItem \brief The QGraphicsItem class is the base class for all graphical @@ -310,7 +308,14 @@ \value ItemHasNoContents The item does not paint anything (i.e., calling paint() on the item has no effect). You should set this flag on items that do not need to be painted to ensure that Graphics View avoids unnecessary - painting preparations. + painting preparations. This flag was introduced in Qt 4.6. + + \value ItemSendsGeometryChanges The item enables itemChange() + notifications for ItemPositionChange, ItemPositionHasChanged, + ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For + performance reasons, these notifications are disabled by default. You must + enable this flag to receive notifications for position and transform + changes. This flag was introduced in Qt 4.6. */ /*! @@ -349,33 +354,36 @@ changing. This value is obsolete; you can use ItemTransformChange instead. \value ItemPositionChange The item's position changes. This notification - is only sent when the item's local position changes, relative to its - parent, has changed (i.e., as a result of calling setPos() or - moveBy()). The value argument is the new position (i.e., a QPointF). You - can call pos() to get the original position. Do not call setPos() or - moveBy() in itemChange() as this notification is delivered; instead, you - can return the new, adjusted position from itemChange(). After this - notification, QGraphicsItem immediately sends the ItemPositionHasChanged - notification if the position changed. + is sent if the ItemSendsGeometryChanges flag is enabled, and when the + item's local position changes, relative to its parent (i.e., as a result + of calling setPos() or moveBy()). The value argument is the new position + (i.e., a QPointF). You can call pos() to get the original position. Do + not call setPos() or moveBy() in itemChange() as this notification is + delivered; instead, you can return the new, adjusted position from + itemChange(). After this notification, QGraphicsItem immediately sends the + ItemPositionHasChanged notification if the position changed. \value ItemPositionHasChanged The item's position has changed. This - notification is only sent after the item's local position, relative to its - parent, has changed. The value argument is the new position (the same as - pos()), and QGraphicsItem ignores the return value for this notification - (i.e., a read-only notification). + notification is sent if the ItemSendsGeometryChanges flag is enabled, and + after the item's local position, relative to its parent, has changed. The + value argument is the new position (the same as pos()), and QGraphicsItem + ignores the return value for this notification (i.e., a read-only + notification). \value ItemTransformChange The item's transformation matrix changes. This - notification is only sent when the item's local transformation matrix - changes (i.e., as a result of calling setTransform(). The value - argument is the new matrix (i.e., a QTransform); to get the old matrix, - call transform(). Do not call setTransform() or set any of the transformation - properties in itemChange() as this notification is delivered; - instead, you can return the new matrix from itemChange(). - This notification is not sent if you change the transformation properties. + notification is send if the ItemSendsGeometryChanges flag is enabled, and + when the item's local transformation matrix changes (i.e., as a result of + calling setTransform(). The value argument is the new matrix (i.e., a + QTransform); to get the old matrix, call transform(). Do not call + setTransform() or set any of the transformation properties in itemChange() + as this notification is delivered; instead, you can return the new matrix + from itemChange(). This notification is not sent if you change the + transformation properties. \value ItemTransformHasChanged The item's transformation matrix has - changed either because setTransform is called, or one of the transformation - properties is changed. This notification is only sent after the item's local + changed either because setTransform is called, or one of the + transformation properties is changed. This notification is sent if the + ItemSendsGeometryChanges flag is enabled, and after the item's local transformation matrix has changed. The value argument is the new matrix (same as transform()), and QGraphicsItem ignores the return value for this notification (i.e., a read-only notification). @@ -1369,7 +1377,9 @@ static void _q_qgraphicsItemSetFlag(QGraphicsItem *item, QGraphicsItem::Graphics item was selected, and \a flags does not enabled ItemIsSelectable, the item is automatically unselected. - By default, no flags are enabled. + By default, no flags are enabled. (QGraphicsWidget enables the + ItemSendsGeometryChanges flag by default in order to track position + changes.) \sa flags(), setFlag() */ @@ -2050,12 +2060,8 @@ qreal QGraphicsItem::effectiveOpacity() const void QGraphicsItem::setOpacity(qreal opacity) { // Notify change. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity))); qreal newOpacity = newOpacityVariant.toDouble(); -#else - qreal newOpacity = opacity; -#endif // Normalize. newOpacity = qBound(0.0, newOpacity, 1.0); @@ -2067,9 +2073,7 @@ void QGraphicsItem::setOpacity(qreal opacity) d_ptr->opacity = newOpacity; // Notify change. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - itemChange(ItemOpacityHasChanged, newOpacity); -#endif + itemChange(ItemOpacityHasChanged, newOpacityVariant); // Update. if (d_ptr->scene) @@ -2508,42 +2512,33 @@ QPointF QGraphicsItem::scenePos() const /*! \internal - Sets the position \a pos and notifies the change. If \a update is true, - the item is also updated; otherwise it is not updated before and after the - change. + Sets the position \a pos. */ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) { Q_Q(QGraphicsItem); - if (this->pos == pos) - return; - - // Notify the item that the position is changing. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos)); - QPointF newPos = newPosVariant.toPointF(); - if (newPos == this->pos) - return; -#else - QPointF newPos = pos; -#endif - - // Update and repositition. inSetPosHelper = 1; - updateCachedClipPathFromSetPosHelper(newPos); + updateCachedClipPathFromSetPosHelper(pos); if (scene) q->prepareGeometryChange(); - this->pos = newPos; + this->pos = pos; dirtySceneTransform = 1; - - // Send post-notification. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); -#endif inSetPosHelper = 0; } /*! + \internal + + Sets the transform \a transform. +*/ +void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform) +{ + q_ptr->prepareGeometryChange(); + transformData->transform = transform; + dirtySceneTransform = 1; +} + +/*! Sets the position of the item to \a pos, which is in parent coordinates. For items with no parent, \a pos is in scene coordinates. @@ -2555,7 +2550,26 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) */ void QGraphicsItem::setPos(const QPointF &pos) { - d_ptr->setPosHelper(pos); + if (d_ptr->pos == pos) + return; + + // Update and repositition. + if (!(d_ptr->flags & ItemSendsGeometryChanges)) { + d_ptr->setPosHelper(pos); + return; + } + + // Notify the item that the position is changing. + const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue(pos))); + QPointF newPos = newPosVariant.toPointF(); + if (newPos == d_ptr->pos) + return; + + // Update and repositition. + d_ptr->setPosHelper(newPos); + + // Send post-notification. + itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); } /*! @@ -3240,20 +3254,23 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) if (d_ptr->transformData->transform == newTransform) return; + // Update and set the new transformation. + if (!(d_ptr->flags & ItemSendsGeometryChanges)) { + d_ptr->setTransformHelper(newTransform); + return; + } + // Notify the item that the transformation matrix is changing. - const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue(newTransform))); - newTransform = qVariantValue(newTransformVariant); + const QVariant newMatrixVariant = qVariantFromValue(newTransform.toAffine()); + newTransform = QTransform(qVariantValue(itemChange(ItemMatrixChange, newMatrixVariant))); if (d_ptr->transformData->transform == newTransform) return; // Update and set the new transformation. - prepareGeometryChange(); - d_ptr->transformData->transform = newTransform; - d_ptr->dirtySceneTransform = 1; - + d_ptr->setTransformHelper(newTransform); + // Send post-notification. - itemChange(ItemTransformHasChanged, newTransformVariant); + itemChange(ItemTransformHasChanged, qVariantFromValue(newTransform)); } /*! @@ -3284,7 +3301,12 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) if (d_ptr->transformData->transform == newTransform) return; - // Notify the item that the transformation matrix is changing. + // Update and set the new transformation. + if (!(d_ptr->flags & ItemSendsGeometryChanges)) { + d_ptr->setTransformHelper(newTransform); + return; + } + // Notify the item that the transformation matrix is changing. const QVariant newTransformVariant(itemChange(ItemTransformChange, qVariantFromValue(newTransform))); @@ -3293,9 +3315,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) return; // Update and set the new transformation. - prepareGeometryChange(); - d_ptr->transformData->transform = newTransform; - d_ptr->dirtySceneTransform = 1; + d_ptr->setTransformHelper(newTransform); // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); @@ -9514,6 +9534,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemHasNoContents: str = "ItemHasNoContents"; break; + case QGraphicsItem::ItemSendsGeometryChanges: + str = "ItemSendsGeometryChanges"; + break; } debug << str; return debug; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 7e33c83..cff4f1f 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -96,7 +96,8 @@ public: ItemDoesntPropagateOpacityToChildren = 0x80, ItemStacksBehindParent = 0x100, ItemUsesExtendedStyleOption = 0x200, - ItemHasNoContents = 0x400 + ItemHasNoContents = 0x400, + ItemSendsGeometryChanges = 0x800 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 13fee8f..e2a37a1 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -175,6 +175,7 @@ public: static bool movableAncestorIsSelected(const QGraphicsItem *item); void setPosHelper(const QPointF &pos); + void setTransformHelper(const QTransform &transform); void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, @@ -397,12 +398,12 @@ public: quint32 fullUpdatePending : 1; // New 32 bits - quint32 flags : 11; + quint32 flags : 12; quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; quint32 geometryChanged : 1; - quint32 unused : 17; // feel free to use + quint32 unused : 16; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 3296aee..7314167 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -1057,6 +1057,9 @@ void QGraphicsWidget::updateGeometry() ItemParentChange both to deliver \l ParentChange events, and for managing the focus chain. + QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in + order to track position changes. + \sa propertyChange() */ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value) diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index a435758..557b883 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -77,7 +77,9 @@ void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFl resolveLayoutDirection(); q->unsetWindowFrameMargins(); q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); + q->setFlag(QGraphicsItem::ItemSendsGeometryChanges); } + qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const { Q_Q(const QGraphicsWidget); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index c6f9824..d6ecbba 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -224,6 +224,7 @@ private slots: void setTransformProperties_data(); void setTransformProperties(); void itemUsesExtendedStyleOption(); + void itemSendsGeometryChanges(); void moveItem(); // task specific tests below me @@ -3730,8 +3731,20 @@ void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem() class ItemChangeTester : public QGraphicsRectItem { public: - ItemChangeTester(){} - ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent) {} + ItemChangeTester() + { setFlag(ItemSendsGeometryChanges); clear(); } + ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent) + { setFlag(ItemSendsGeometryChanges); clear(); } + + void clear() + { + itemChangeReturnValue = QVariant(); + itemSceneChangeTargetScene = 0; + changes.clear(); + values.clear(); + oldValues.clear(); + } + QVariant itemChangeReturnValue; QGraphicsScene *itemSceneChangeTargetScene; @@ -3932,7 +3945,8 @@ void tst_QGraphicsItem::itemChange() QCOMPARE(tester.changes.size(), changeCount); QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange); QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged); - QCOMPARE(tester.values.at(tester.values.size() - 2), qVariantFromValue(QGraphicsItem::ItemIsSelectable)); + QVariant expectedFlags = qVariantFromValue(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges); + QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags); QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue(QGraphicsItem::ItemIsSelectable)); } { @@ -6745,6 +6759,44 @@ void tst_QGraphicsItem::itemUsesExtendedStyleOption() QTest::qWait(125); } +void tst_QGraphicsItem::itemSendsGeometryChanges() +{ + ItemChangeTester item; + item.setFlags(0); + item.clear(); + + QTransform x = QTransform().rotate(45); + QPointF pos(10, 10); + qreal o(0.5); + item.setTransform(x); + item.setPos(pos); + QCOMPARE(item.transform(), x); + QCOMPARE(item.pos(), pos); + QCOMPARE(item.changes.size(), 0); + + item.setOpacity(o); + QCOMPARE(item.changes.size(), 2); // opacity + + item.setFlag(QGraphicsItem::ItemSendsGeometryChanges); + QCOMPARE(item.changes.size(), 4); // flags + item.setTransform(QTransform()); + item.setPos(QPointF()); + QCOMPARE(item.changes.size(), 8); // transform + pos + QCOMPARE(item.transform(), QTransform()); + QCOMPARE(item.pos(), QPointF()); + QCOMPARE(item.opacity(), o); + + QCOMPARE(item.changes, QList() + << QGraphicsItem::ItemOpacityChange + << QGraphicsItem::ItemOpacityHasChanged + << QGraphicsItem::ItemFlagsChange + << QGraphicsItem::ItemFlagsHaveChanged + << QGraphicsItem::ItemTransformChange + << QGraphicsItem::ItemTransformHasChanged + << QGraphicsItem::ItemPositionChange + << QGraphicsItem::ItemPositionHasChanged); +} + // Make sure we update moved items correctly. void tst_QGraphicsItem::moveItem() { -- cgit v0.12 From e8be9f499547125490d61fb07b6aa023e38cd410 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 8 Jun 2009 19:06:40 +0200 Subject: Update change log with behavior changes in Graphics View. --- dist/changes-4.6.0 | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0 index bedf58a..ba58bcf 100644 --- a/dist/changes-4.6.0 +++ b/dist/changes-4.6.0 @@ -40,17 +40,30 @@ information about a particular change. reasons for this is that Qt Software focuses on OpenGL for desktop hardware accelerated rendering. - - QStyleOptionGraphicsItem::exposedRect and QStyleOptionGraphicsItem::matrix - does no longer contain fine-grained values when passed in drawItems()/paint() - unless the QGraphicsItem::ItemUsesExtendedStyleOptions flag is enabled. - By default, exposedRect is initialized to the item's bounding rect - and the matrix is untransformed. - - - QStyleOptionGraphicsItem::levelOfDetails is obsoleted and its value - is always initialized to 1. For a more fine-grained value use - QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &). - - When mixing OpenGL and QPainter calls you need to first call syncState() on the paint engine, for example "painter->paintEngine()->syncState()". This is to ensure that the engine flushes any pending drawing and sets up the GL modelview/projection matrices properly. + + - Graphics View has undergone heavy optimization work, and as a result of + this work, the following behavior changes were introduced. + + a) QStyleOptionGraphicsItem::exposedRect now contains the item's bounding + rectangle, and QStyleOptionGraphicsItem::matrix is uninitialized by + default. You can enable an exact exposed rectangle and a correct matrix + by enabling the flag QGraphicsItem::ItemUsesExtendedStyleOptions. + + b) QStyleOptionGraphicsItem::levelOfDetails is obsoleted and its value is + always initialized to 1. Instead you can call + QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &) + to determine the level of detail. + + c) QGraphicsView no longer calls QGraphicsView::drawItems(), and in turn + QGraphicsScene::drawItems(), by default. You can get the old behavior + back by enabling QGraphicsView::IndirectPainting. + + d) QGraphicsItem no longer calls itemChange() for position and + transformation changes. If you want to receive notifications for changes + to the item's position and transformation, you can set the flag + QGraphicsItem::ItemSendsGeometryChanges (which is enabled by default by + QGraphicsWidget and QGraphicsProxyWidget). -- cgit v0.12 From e2e039954b2212a9cee0b7f72e383621f8bc6c8f Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 8 Jun 2009 19:26:59 +0200 Subject: Revert 7aee2a7054d1ca280f6dfc9c46b3fe2ce403ccb3, fix render bugs. This change introduced an unexpected interdependency for scenes with items that enable ItemStacksBehindParent, and that contain children that are transformed. There's a manual test for this, called clippingAndTransformations, which shows this problem. The bug has been fixed and this change also includes an autotest that covers exactly this problem. --- src/gui/graphicsview/qgraphicsscene.cpp | 15 +++--- src/gui/graphicsview/qgraphicsscene_p.h | 1 - tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 72 ++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7038c3d..7963ea1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5138,9 +5138,10 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Calculate the full transform for this item. QRect viewBoundingRect; bool wasDirtyParentSceneTransform = false; + QTransform transform; if (item) { if (item->d_ptr->itemIsUntransformable()) { - transformTmp = item->deviceTransform(viewTransform); + transform = item->deviceTransform(viewTransform); } else { if (item->d_ptr->dirtySceneTransform) { item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform @@ -5149,14 +5150,14 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * item->d_ptr->dirtySceneTransform = 0; wasDirtyParentSceneTransform = true; } - transformTmp = item->d_ptr->sceneTransform; - transformTmp *= viewTransform; + transform = item->d_ptr->sceneTransform; + transform *= viewTransform; } QRectF brect = item->boundingRect(); // ### This does not take the clip into account. _q_adjustRect(&brect); - viewBoundingRect = transformTmp.mapRect(brect).toRect(); + viewBoundingRect = transform.mapRect(brect).toRect(); item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); viewBoundingRect.adjust(-1, -1, 1, 1); if (exposedRegion) @@ -5200,7 +5201,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Clip children. if (childClip) { painter->save(); - painter->setWorldTransform(transformTmp); + painter->setWorldTransform(transform); painter->setClipPath(item->shape(), Qt::IntersectClip); } @@ -5234,14 +5235,14 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Draw item if (!dontDrawItem) { - item->d_ptr->initStyleOption(&styleOptionTmp, transformTmp, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); + item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); bool savePainter = clipsToShape || !(optimizationFlags & QGraphicsView::DontSavePainterState); if (savePainter) painter->save(); if (!childClip) - painter->setWorldTransform(transformTmp); + painter->setWorldTransform(transform); if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index fd7decf..000e2ba 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -290,7 +290,6 @@ public: void updatePalette(const QPalette &palette); QStyleOptionGraphicsItem styleOptionTmp; - QTransform transformTmp; }; QT_END_NAMESPACE diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index d6ecbba..621f2bf 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -236,6 +236,9 @@ private slots: void task240400_clickOnTextItem(); void task243707_addChildBeforeParent(); void task197802_childrenVisibility(); + +private: + QList paintedItems; }; void tst_QGraphicsItem::init() @@ -5793,19 +5796,36 @@ void tst_QGraphicsItem::opacity2() QCOMPARE(grandChild->repaints, 0); } +class StacksBehindParentHelper : public QGraphicsRectItem +{ +public: + StacksBehindParentHelper(QList *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0) + : QGraphicsRectItem(rect, parent), paintedItems(paintedItems) + { } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + QGraphicsRectItem::paint(painter, option, widget); + paintedItems->append(this); + } + +private: + QList *paintedItems; +}; + void tst_QGraphicsItem::itemStacksBehindParent() { - QGraphicsRectItem *parent1 = new QGraphicsRectItem(QRectF(0, 0, 100, 50)); - QGraphicsRectItem *child11 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent1); - QGraphicsRectItem *grandChild111 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child11); - QGraphicsRectItem *child12 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent1); - QGraphicsRectItem *grandChild121 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child12); + StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50)); + StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1); + StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11); + StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1); + StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12); - QGraphicsRectItem *parent2 = new QGraphicsRectItem(QRectF(0, 0, 100, 50)); - QGraphicsRectItem *child21 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent2); - QGraphicsRectItem *grandChild211 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child21); - QGraphicsRectItem *child22 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent2); - QGraphicsRectItem *grandChild221 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child22); + StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50)); + StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2); + StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21); + StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2); + StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22); parent1->setData(0, "parent1"); child11->setData(0, "child11"); @@ -5827,25 +5847,57 @@ void tst_QGraphicsItem::itemStacksBehindParent() scene.addItem(parent1); scene.addItem(parent2); + paintedItems.clear(); + + QGraphicsView view(&scene); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(250); + QCOMPARE(scene.items(0, 0, 100, 100), (QList() << grandChild111 << child11 << grandChild121 << child12 << parent1 << grandChild211 << child21 << grandChild221 << child22 << parent2)); + QCOMPARE(paintedItems, QList() + << parent2 << child22 << grandChild221 + << child21 << grandChild211 + << parent1 << child12 << grandChild121 + << child11 << grandChild111); child11->setFlag(QGraphicsItem::ItemStacksBehindParent); + scene.update(); + paintedItems.clear(); + QTest::qWait(250); + QCOMPARE(scene.items(0, 0, 100, 100), (QList() << grandChild121 << child12 << parent1 << grandChild111 << child11 << grandChild211 << child21 << grandChild221 << child22 << parent2)); + QCOMPARE(paintedItems, QList() + << parent2 << child22 << grandChild221 + << child21 << grandChild211 + << child11 << grandChild111 + << parent1 << child12 << grandChild121); child12->setFlag(QGraphicsItem::ItemStacksBehindParent); + paintedItems.clear(); + scene.update(); + QTest::qWait(250); + QCOMPARE(scene.items(0, 0, 100, 100), (QList() << parent1 << grandChild111 << child11 << grandChild121 << child12 << grandChild211 << child21 << grandChild221 << child22 << parent2)); + QCOMPARE(paintedItems, QList() + << parent2 << child22 << grandChild221 + << child21 << grandChild211 + << child12 << grandChild121 + << child11 << grandChild111 << parent1); } class ClippingAndTransformsScene : public QGraphicsScene -- cgit v0.12 From f84782506770f99e9633649483e4dd067e3abcd5 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 8 Jun 2009 19:50:14 +0200 Subject: Fix QGraphicsView::render() regression, ensure the right device is passed. If we pass the viewport widget as the widget pointer when rendering to an arbitrary painter (e.g., onto a pixmap), we confuse the rendering functions to thinking that it's the viewport's region we should render into. So instead, when drawItems() is passed a painter that's different from the view, we pass 0 for the widget. --- src/gui/graphicsview/qgraphicsview.cpp | 6 ++- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 57 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 166bcb9..e685f9b 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3526,8 +3526,10 @@ void QGraphicsView::drawItems(QPainter *painter, int numItems, const QStyleOptionGraphicsItem options[]) { Q_D(QGraphicsView); - if (d->scene) - d->scene->drawItems(painter, numItems, items, options, viewport()); + if (d->scene) { + QWidget *widget = painter->device() == viewport() ? viewport() : 0; + d->scene->drawItems(painter, numItems, items, options, widget); + } } /*! diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 718c8d6..5167682 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -191,6 +191,7 @@ private slots: void centerOnDirtyItem(); void mouseTracking(); void mouseTracking2(); + void render(); // task specific tests below me void task172231_untransformableItems(); @@ -3203,6 +3204,62 @@ void tst_QGraphicsView::mouseTracking2() QCOMPARE(spy.count(), 1); } +class RenderTester : public QGraphicsRectItem +{ +public: + RenderTester(const QRectF &rect) + : QGraphicsRectItem(rect), paints(0) + { } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget) + { + QGraphicsRectItem::paint(painter, option, widget); + ++paints; + } + + int paints; +}; + +void tst_QGraphicsView::render() +{ + // ### This test can be much more thorough - see QGraphicsScene::render. + QGraphicsScene scene; + RenderTester *r1 = new RenderTester(QRectF(0, 0, 50, 50)); + RenderTester *r2 = new RenderTester(QRectF(50, 50, 50, 50)); + RenderTester *r3 = new RenderTester(QRectF(0, 50, 50, 50)); + RenderTester *r4 = new RenderTester(QRectF(50, 0, 50, 50)); + scene.addItem(r1); + scene.addItem(r2); + scene.addItem(r3); + scene.addItem(r4); + + QGraphicsView view(&scene); + view.setFrameStyle(0); + view.resize(200, 200); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(200); + + QCOMPARE(r1->paints, 1); + QCOMPARE(r2->paints, 1); + QCOMPARE(r3->paints, 1); + QCOMPARE(r4->paints, 1); + + QPixmap pix(200, 200); + pix.fill(Qt::transparent); + QPainter painter(&pix); + view.render(&painter); + painter.end(); + + QCOMPARE(r1->paints, 2); + QCOMPARE(r2->paints, 2); + QCOMPARE(r3->paints, 2); + QCOMPARE(r4->paints, 2); +} + void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged() { QGraphicsView view; -- cgit v0.12 From 31fa814955cd2b0983b42543e133f24e9830c67f Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 8 Jun 2009 19:54:51 +0200 Subject: Fix moving regression for ItemIgnoresTransformations items. Removes a piece of code in 775ec8e96c9219981ff220ca5f3d24f0501d17b5 that was submitted by accident. The code in mouseMoveEvent is now identical to that in master. --- src/gui/graphicsview/qgraphicsitem.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3138faa..5ba87ee 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5940,13 +5940,21 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) if ((item->flags() & ItemIsMovable) && !QGraphicsItemPrivate::movableAncestorIsSelected(item)) { QPointF currentParentPos; QPointF buttonDownParentPos; - if (item->d_ptr->itemIsUntransformable()) { + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations) { // Items whose ancestors ignore transformations need to // map screen coordinates to local coordinates, then map // those to the parent. QTransform viewToItemTransform = (item->deviceTransform(view->viewportTransform())).inverted(); currentParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->screenPos())))); buttonDownParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton))))); + } else if (item->flags() & ItemIgnoresTransformations) { + // Root items that ignore transformations need to + // calculate their diff by mapping viewport coordinates + // directly to parent coordinates. + QTransform viewToParentTransform = (item->transform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y())) + * (item->sceneTransform() * view->viewportTransform()).inverted(); + currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos()))); + buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton)))); } else { // All other items simply map from the scene. currentParentPos = item->mapToParent(item->mapFromScene(event->scenePos())); -- cgit v0.12 From e4d6cfb1be4a3ff71013362f1f827e3920524934 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 9 Jun 2009 09:05:17 +0200 Subject: Ensure we use the correct static paintedItems list. Fixes the zValue autotest, which regressed when the member list was added. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 621f2bf..af34fe5 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -1798,15 +1798,15 @@ void tst_QGraphicsItem::setMatrix() QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state) } -static QList paintedItems; +static QList _paintedItems; class PainterItem : public QGraphicsItem { protected: QRectF boundingRect() const { return QRectF(-10, -10, 20, 20); } - void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) - { paintedItems << this; } + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); } }; void tst_QGraphicsItem::zValue() @@ -1838,10 +1838,10 @@ void tst_QGraphicsItem::zValue() QApplication::sendPostedEvents(); //glib workaround #endif - QVERIFY(!paintedItems.isEmpty()); - QVERIFY((paintedItems.size() % 4) == 0); + QVERIFY(!_paintedItems.isEmpty()); + QVERIFY((_paintedItems.size() % 4) == 0); for (int i = 0; i < 3; ++i) - QVERIFY(paintedItems.at(i)->zValue() < paintedItems.at(i + 1)->zValue()); + QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue()); } void tst_QGraphicsItem::shape() -- cgit v0.12 From 03428c4d2905cc73866f1d046b5cc1bedf1c38b3 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 9 Jun 2009 09:05:57 +0200 Subject: Remove one unnecessary argument from the recursive draw function. We don't have to pass optimization flags; we already have a member variable we can test for painter state protection. --- src/gui/graphicsview/qgraphicsscene.cpp | 14 +++++--------- src/gui/graphicsview/qgraphicsscene_p.h | 2 +- src/gui/graphicsview/qgraphicsview.cpp | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7963ea1..e43c9cd 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5108,7 +5108,6 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, QRegion *exposedRegion, QWidget *widget, - QGraphicsView::OptimizationFlags optimizationFlags, QList *topLevelItems, qreal parentOpacity) { @@ -5229,7 +5228,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, - optimizationFlags, 0, opacity); + 0, opacity); } } @@ -5238,7 +5237,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape); - bool savePainter = clipsToShape || !(optimizationFlags & QGraphicsView::DontSavePainterState); + bool savePainter = clipsToShape || painterStateProtection; if (savePainter) painter->save(); if (!childClip) @@ -5261,7 +5260,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, - widget, optimizationFlags, 0, opacity); + widget, 0, opacity); } } else if (wasDirtyParentSceneTransform) { item->d_ptr->invalidateChildrenSceneTransform(); @@ -5487,11 +5486,8 @@ void QGraphicsScene::drawItems(QPainter *painter, // Determine view, expose and flags. QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; QRegion *expose = 0; - QGraphicsView::OptimizationFlags flags; - if (view) { + if (view) expose = &view->d_func()->exposedRegion; - flags = view->optimizationFlags(); - } // Find all toplevels, they are already sorted. QList topLevelItems; @@ -5500,7 +5496,7 @@ void QGraphicsScene::drawItems(QPainter *painter, if (!item->d_ptr->itemDiscovered) { topLevelItems << item; item->d_ptr->itemDiscovered = 1; - d->drawSubtreeRecursive(item, painter, viewTransform, expose, widget, flags); + d->drawSubtreeRecursive(item, painter, viewTransform, expose, widget); } } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 000e2ba..42c4d8c 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -261,7 +261,7 @@ public: bool painterStateProtection); void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform, - QRegion *exposedRegion, QWidget *widget, QGraphicsView::OptimizationFlags optimizationFlags, + QRegion *exposedRegion, QWidget *widget, QList *topLevelItems = 0, qreal parentOpacity = qreal(1.0)); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index e685f9b..4891e81 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3303,7 +3303,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Items if (!(d->optimizationFlags & IndirectPainting)) { d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion, - viewport(), d->optimizationFlags, 0); + viewport(), 0); } else { // Find all exposed items bool allItems = false; -- cgit v0.12 From 662d1db6ee1a78c298acc11e7528e73c0415fc75 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 9 Jun 2009 10:32:20 +0200 Subject: doc: Corrected the rich text page wrt smallcaps. Task-number: 254912 --- doc/src/richtext.qdoc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/src/richtext.qdoc b/doc/src/richtext.qdoc index fbd8adb..6ea82f8 100644 --- a/doc/src/richtext.qdoc +++ b/doc/src/richtext.qdoc @@ -1058,8 +1058,11 @@ Ideas for other sections: \o Specifies where an image or a text will be placed in another element. Note that the \c float property is only supported for tables and images. \row \o \c text-transform - \o [ uppercase | lowercase | smallcaps ] + \o [ uppercase | lowercase ] \o Select the transformation that will be performed on the text prior to displaying it. + \row \o \c font-variant + \o small-caps + \o Perform the smallcaps transformation on the text prior to displaying it. \row \o \c word-spacing \o px \o Specifies an alternate spacing between each word. -- cgit v0.12 From 29496148abe8506fbf50c99e9a210095c5115a14 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 9 Jun 2009 10:42:46 +0200 Subject: Compile fix for !QFX_RENDER_OPENGL Some QFX_RENDER_OPENGL guards were missing and getPen had to be replaced with d->pen in some places Reviewed-by: Kai Koehne --- src/declarative/canvas/qsimplecanvasitem.h | 2 ++ src/declarative/fx/qfximage.cpp | 2 ++ src/declarative/fx/qfxrect.cpp | 6 +++--- src/declarative/fx/qfxrect_p.h | 7 +++++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h index e62c56d..dce3007 100644 --- a/src/declarative/canvas/qsimplecanvasitem.h +++ b/src/declarative/canvas/qsimplecanvasitem.h @@ -45,7 +45,9 @@ #include #include #include +#if defined(QFX_RENDER_OPENGL) #include +#endif #include #include diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index c5e7e89..224c25e 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -127,10 +127,12 @@ QFxImage::~QFxImage() Q_D(QFxImage); if (d->sciReply) d->sciReply->deleteLater(); +#if defined(QFX_RENDER_OPENGL) if (d->tex) { d->tex->release(); d->tex = 0; } +#endif } /*! diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index eacc85e..f55357f 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -497,7 +497,7 @@ void QFxRect::generateRoundedRect() QPainter p(&(d->rectImage)); p.setRenderHint(QPainter::Antialiasing); if (d->pen && d->pen->isValid()) { - QPen pn(QColor(getPen()->color()), getPen()->width()); + QPen pn(QColor(d->pen->color()), d->pen->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); @@ -517,7 +517,7 @@ void QFxRect::generateBorderedRect() QPainter p(&(d->rectImage)); p.setRenderHint(QPainter::Antialiasing); if (d->pen && d->pen->isValid()) { - QPen pn(QColor(getPen()->color()), getPen()->width()); + QPen pn(QColor(d->pen->color()), d->pen->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); @@ -604,7 +604,7 @@ void QFxRect::drawRect(QPainter &p) QPainter::RenderHints oldHints = p.renderHints(); p.setRenderHint(QPainter::Antialiasing); if (d->pen && d->pen->isValid()) { - QPen pn(QColor(getPen()->color()), getPen()->width()); + QPen pn(QColor(d->pen->color()), d->pen->width()); p.setPen(pn); } else { p.setPen(Qt::NoPen); diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h index d68eb4e..f662fac 100644 --- a/src/declarative/fx/qfxrect_p.h +++ b/src/declarative/fx/qfxrect_p.h @@ -68,8 +68,11 @@ class QFxRectPrivate : public QFxItemPrivate Q_DECLARE_PUBLIC(QFxRect) public: - QFxRectPrivate() - : rectTexture(0), gradient(0), pen(0), radius(0) + QFxRectPrivate() : +#if defined(QFX_RENDER_OPENGL) + rectTexture(0), +#endif //QFX_RENDER_OPENGL + gradient(0), pen(0), radius(0) { } -- cgit v0.12 From 91ceb21d1d5f6447a47853b6625fb51d2f21cf16 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 9 Jun 2009 10:51:26 +0200 Subject: small refactoring to reduce memory usage of static data --- src/corelib/codecs/qisciicodec.cpp | 2 +- src/corelib/tools/qlocale.cpp | 2 +- src/corelib/tools/qlocale_data_p.h | 10 +++++----- src/corelib/xml/qxmlstream.cpp | 7 +++---- util/local_database/qlocalexml2cpp.py | 6 +++--- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/corelib/codecs/qisciicodec.cpp b/src/corelib/codecs/qisciicodec.cpp index dd2bc8d..de1e477 100644 --- a/src/corelib/codecs/qisciicodec.cpp +++ b/src/corelib/codecs/qisciicodec.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE struct Codecs { - const char *name; + const char name[10]; ushort base; }; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 00132d7..4898e10 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -772,7 +772,7 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const Instead it can return a "Windows code". This maps windows codes to ISO country names. */ struct WindowsToISOListElt { - int windows_code; + ushort windows_code; char iso_name[6]; }; diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h index 37f59a4..e0eecf3 100644 --- a/src/corelib/tools/qlocale_data_p.h +++ b/src/corelib/tools/qlocale_data_p.h @@ -60,8 +60,8 @@ QT_BEGIN_NAMESPACE */ struct CountryLanguage { - quint32 languageId; - quint32 countryId; + quint16 languageId; + quint16 countryId; }; static const CountryLanguage ImperialMeasurementSystems[] = { { 31, 225 }, @@ -83,7 +83,7 @@ static const int ImperialMeasurementSystemsCount = */ -static const uint locale_index[] = { +static const quint16 locale_index[] = { 0, // unused 0, // C 0, // Abkhazian @@ -2313,7 +2313,7 @@ static const char language_name_list[] = "Chewa\0" ; -static const uint language_name_index[] = { +static const quint16 language_name_index[] = { 0, // Unused 8, // C 10, // Abkhazian @@ -2727,7 +2727,7 @@ static const char country_name_list[] = "SerbiaAndMontenegro\0" ; -static const uint country_name_index[] = { +static const quint16 country_name_index[] = { 0, // AnyCountry 8, // Afghanistan 20, // Albania diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 5e1fec3..fddcecf 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -629,7 +629,7 @@ while () { $sizes[$i++] = $counter; $counter += length 1 + $_; } -print " \"\\0\";\n\nstatic const int QXmlStreamReader_tokenTypeString_indices[] = {\n "; +print " \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n "; for ($j = 0; $j < $i; ++$j) { printf "$sizes[$j], "; } @@ -660,10 +660,9 @@ static const char QXmlStreamReader_tokenTypeString_string[] = "Comment\0" "DTD\0" "EntityReference\0" - "ProcessingInstruction\0" - "\0"; + "ProcessingInstruction\0"; -static const int QXmlStreamReader_tokenTypeString_indices[] = { +static const short QXmlStreamReader_tokenTypeString_indices[] = { 0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0 }; diff --git a/util/local_database/qlocalexml2cpp.py b/util/local_database/qlocalexml2cpp.py index af6da33..d625cfd 100755 --- a/util/local_database/qlocalexml2cpp.py +++ b/util/local_database/qlocalexml2cpp.py @@ -318,7 +318,7 @@ def main(): print # Locale index - print "static const uint locale_index[] = {" + print "static const quint16 locale_index[] = {" print " 0, // unused" index = 0 for key in language_map.keys(): @@ -454,7 +454,7 @@ def main(): print # Language name index - print "static const uint language_name_index[] = {" + print "static const quint16 language_name_index[] = {" print " 0, // Unused" index = 8 for key in language_map.keys(): @@ -477,7 +477,7 @@ def main(): print # Country name index - print "static const uint country_name_index[] = {" + print "static const quint16 country_name_index[] = {" print " 0, // AnyCountry" index = 8 for key in country_map.keys(): -- cgit v0.12 From b1658783099b75097f02bef85c4ea2a469826d37 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 4 Jun 2009 19:49:41 +0200 Subject: make bic test works in shadow build --- tests/auto/bic/bic.pro | 6 ++++++ tests/auto/bic/tst_bic.cpp | 33 +++++++++++++++++---------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/tests/auto/bic/bic.pro b/tests/auto/bic/bic.pro index a168d77..82711c9 100644 --- a/tests/auto/bic/bic.pro +++ b/tests/auto/bic/bic.pro @@ -2,3 +2,9 @@ load(qttest_p4) SOURCES += tst_bic.cpp qbic.cpp QT = core +wince*:{ + DEFINES += SRCDIR=\\\"\\\" +} else { + DEFINES += SRCDIR=\\\"$$PWD/\\\" +} + diff --git a/tests/auto/bic/tst_bic.cpp b/tests/auto/bic/tst_bic.cpp index 181c275..8bc8d4f 100644 --- a/tests/auto/bic/tst_bic.cpp +++ b/tests/auto/bic/tst_bic.cpp @@ -165,30 +165,30 @@ void tst_Bic::sizesAndVTables_data() #if defined Q_OS_LINUX && defined Q_WS_X11 # if defined(__powerpc__) && !defined(__powerpc64__) - archFileName400 = "data/%1.4.0.0.linux-gcc-ppc32.txt"; - archFileName410 = "data/%1.4.1.0.linux-gcc-ppc32.txt"; - archFileName420 = "data/%1.4.2.0.linux-gcc-ppc32.txt"; + archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-ppc32.txt"; + archFileName410 = SRCDIR "data/%1.4.1.0.linux-gcc-ppc32.txt"; + archFileName420 = SRCDIR "data/%1.4.2.0.linux-gcc-ppc32.txt"; # elif defined(__amd64__) - archFileName400 = "data/%1.4.0.0.linux-gcc-amd64.txt"; + archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-amd64.txt"; # elif defined(__i386__) - archFileName400 = "data/%1.4.0.0.linux-gcc-ia32.txt"; - archFileName410 = "data/%1.4.1.0.linux-gcc-ia32.txt"; - archFileName420 = "data/%1.4.2.0.linux-gcc-ia32.txt"; - archFileName430 = "data/%1.4.3.0.linux-gcc-ia32.txt"; + archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-ia32.txt"; + archFileName410 = SRCDIR "data/%1.4.1.0.linux-gcc-ia32.txt"; + archFileName420 = SRCDIR "data/%1.4.2.0.linux-gcc-ia32.txt"; + archFileName430 = SRCDIR "data/%1.4.3.0.linux-gcc-ia32.txt"; # endif #elif defined Q_OS_AIX if (sizeof(void*) == 4) - archFileName400 = "data/%1.4.0.0.aix-gcc-power32.txt"; + archFileName400 = SRCDIR "data/%1.4.0.0.aix-gcc-power32.txt"; #elif defined Q_OS_MAC && defined(__powerpc__) - archFileName400 = "data/%1.4.0.0.macx-gcc-ppc32.txt"; - archFileName410 = "data/%1.4.1.0.macx-gcc-ppc32.txt"; - archFileName420 = "data/%1.4.2.0.macx-gcc-ppc32.txt"; + archFileName400 = SRCDIR "data/%1.4.0.0.macx-gcc-ppc32.txt"; + archFileName410 = SRCDIR "data/%1.4.1.0.macx-gcc-ppc32.txt"; + archFileName420 = SRCDIR "data/%1.4.2.0.macx-gcc-ppc32.txt"; #elif defined Q_OS_MAC && defined(__i386__) - archFileName410 = "data/%1.4.1.0.macx-gcc-ia32.txt"; - archFileName420 = "data/%1.4.2.0.macx-gcc-ia32.txt"; + archFileName410 = SRCDIR "data/%1.4.1.0.macx-gcc-ia32.txt"; + archFileName420 = SRCDIR "data/%1.4.2.0.macx-gcc-ia32.txt"; #elif defined Q_OS_WIN && defined Q_CC_GNU - archFileName410 = "data/%1.4.1.0.win32-gcc-ia32.txt"; - archFileName420 = "data/%1.4.2.0.win32-gcc-ia32.txt"; + archFileName410 = SRCDIR "data/%1.4.1.0.win32-gcc-ia32.txt"; + archFileName420 = SRCDIR "data/%1.4.2.0.win32-gcc-ia32.txt"; #endif if (archFileName400.isEmpty() && archFileName410.isEmpty() @@ -293,6 +293,7 @@ void tst_Bic::sizesAndVTables() bool isFailed = false; + qDebug() << oldLib.arg(libName); if (oldLib.isEmpty() || !QFile::exists(oldLib.arg(libName))) QSKIP("No platform spec found for this platform/version.", SkipSingle); -- cgit v0.12 From c5a9996213a535ad6b1e183ed258913082213073 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 9 Jun 2009 11:10:46 +0200 Subject: Fix focus frame on combobox on non-Windows styles State_KeyboardFocusChange only makes sens on Windows. Follow the logic on the combobox as in PE_FrameFocusRect in the QWindowsStyle Task-number: 255482 Reviewed-by: jbache --- src/gui/styles/qcleanlooksstyle.cpp | 3 ++- src/gui/styles/qgtkstyle.cpp | 2 +- src/gui/styles/qplastiquestyle.cpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index b33dfc1..805cd05 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -3305,7 +3305,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp } } // Draw the focus rect - if ((focus && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) { + if (focus && !comboBox->editable + && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) { QStyleOptionFocusRect focus; focus.rect = subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget) .adjusted(0, 2, option->direction == Qt::RightToLeft ? 1 : -1, -2); diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index 1fe4627..ab81d97 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -1426,7 +1426,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom QGtk::gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL); int xt = interiorFocus ? gtkToggleButton->style->xthickness : 0; int yt = interiorFocus ? gtkToggleButton->style->ythickness : 0; - if ((focus && (option->state & State_KeyboardFocusChange))) + if (focus && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) gtkCachedPainter.paintFocus(gtkToggleButton, "button", option->rect.adjusted(xt, yt, -xt, -yt), option->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL, diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index 01c0e44..0a56213 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -4568,7 +4568,8 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt } // Draw the focus rect - if (((option->state & State_HasFocus) && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) { + if ((option->state & State_HasFocus) && !comboBox->editable + && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) { QStyleOptionFocusRect focus; focus.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget) .adjusted(-2, 0, 2, 0); -- cgit v0.12 From 9b88c6f485016b53d394a88106a048495cf79294 Mon Sep 17 00:00:00 2001 From: Leonardo Sobral Cunha Date: Tue, 9 Jun 2009 11:58:45 +0200 Subject: Fix QImageReader autotest compilation --- tests/auto/qimagereader/qimagereader.qrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qimagereader/qimagereader.qrc b/tests/auto/qimagereader/qimagereader.qrc index 3c674ad..c6b963b 100644 --- a/tests/auto/qimagereader/qimagereader.qrc +++ b/tests/auto/qimagereader/qimagereader.qrc @@ -30,7 +30,7 @@ images/image.pgm images/image.png images/image.ppm - images/image.tif + images/image_100dpi.tif images/kollada.png images/marble.xpm images/namedcolors.xpm -- cgit v0.12 From d826a08add652314bb22bee44e0d43bbd672f272 Mon Sep 17 00:00:00 2001 From: Leonardo Sobral Cunha Date: Tue, 9 Jun 2009 12:02:59 +0200 Subject: Fix floating point exception in QImageReader::setScaledSize(QSize(0, 0)) Avoid a division by 0 when doing QImageReader::setScaledSize(QSize(0, 0)) for jpeg formats. Reviewed-by: thierry Task-number: 255627 --- src/plugins/imageformats/jpeg/qjpeghandler.cpp | 3 ++- tests/auto/qimagereader/tst_qimagereader.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index 6d0bc1f..088ef97 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -781,7 +781,8 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage, #ifndef QT_NO_IMAGE_SMOOTHSCALE // If high quality not required, shrink image during decompression - if (scaledSize.isValid() && quality < HIGH_QUALITY_THRESHOLD && !params.contains(QLatin1String("GetHeaderInformation")) ) { + if (scaledSize.isValid() && !scaledSize.isEmpty() && quality < HIGH_QUALITY_THRESHOLD + && !params.contains(QLatin1String("GetHeaderInformation")) ) { cinfo.scale_denom = qMin(cinfo.image_width / scaledSize.width(), cinfo.image_width / scaledSize.height()); if (cinfo.scale_denom < 2) { diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index f5313eb..0b32f0a 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -156,6 +156,9 @@ private slots: void pixelCompareWithBaseline_data(); void pixelCompareWithBaseline(); + + void task255627_setNullScaledSize_data(); + void task255627_setNullScaledSize(); }; static const QLatin1String prefix(SRCDIR "/images/"); @@ -333,6 +336,29 @@ void tst_QImageReader::setScaledSize() QCOMPARE(image.size(), newSize); } +void tst_QImageReader::task255627_setNullScaledSize_data() +{ + setScaledSize_data(); +} + +void tst_QImageReader::task255627_setNullScaledSize() +{ + QFETCH(QString, fileName); + QFETCH(QByteArray, format); + + if (!format.isEmpty() && !QImageReader::supportedImageFormats().contains(format)) + QSKIP("Qt does not support reading the \"" + format + "\" format", SkipSingle); + + QImageReader reader(prefix + fileName); + + // set a null size + reader.setScaledSize(QSize(0, 0)); + reader.setQuality(0); + QImage image = reader.read(); + QVERIFY(image.isNull()); + QCOMPARE(image.size(), QSize(0, 0)); +} + void tst_QImageReader::setClipRect_data() { QTest::addColumn("fileName"); -- cgit v0.12 From 2de2018a33ea45b32963378bb4f7ef24cd181485 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 9 Jun 2009 12:32:05 +0200 Subject: WinCE doesn't have time() function, use QTime --- examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp index d360de9..2368608 100644 --- a/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp +++ b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp @@ -42,13 +42,12 @@ #include "random_ai_plugin.h" #include +#include #include -#include - QState *RandomAiPlugin::create(QState *parentState, QObject *tank) { - qsrand(uint(time(NULL))); + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); QState *topLevel = new QState(parentState); -- cgit v0.12 From d6f171c9baa61858aea0db36fd8b1bd3219ffd0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 5 Jun 2009 11:47:32 +0200 Subject: Improved clipping in GL2 paint engine. Use the stencil method to draw clip paths and regions to the Z-buffer instead of using glClear / glScissor. Using different depth values for the various clip parts also makes restore() very cheap when only IntersectClip is used. As an additional bonus this patch gives antialiased clip in the GL 2 paint engine. Task-number: 254658 Reviewed-by: Trond --- src/gui/painting/qpaintengineex.cpp | 80 ++++- src/gui/painting/qpaintengineex_p.h | 32 +- src/gui/painting/qpainter.h | 1 + .../gl2paintengineex/qglengineshadermanager.cpp | 3 +- .../gl2paintengineex/qglengineshadersource_p.h | 14 + .../gl2paintengineex/qpaintengineex_opengl2.cpp | 374 ++++++++++++--------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 25 +- 7 files changed, 343 insertions(+), 186 deletions(-) diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 28f9220..3cf5ff9 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -138,6 +138,76 @@ QPaintEngineExPrivate::~QPaintEngineExPrivate() } +void QPaintEngineExPrivate::replayClipOperations() +{ + Q_Q(QPaintEngineEx); + + QPainter *p = q->painter(); + if (!p || !p->d_ptr) + return; + + QPainterPrivate *pp = p->d_ptr; + QList clipInfo = pp->state->clipInfo; + + QTransform transform = q->state()->matrix; + + QTransform redirection; + redirection.translate(-q->state()->redirection_offset.x(), -q->state()->redirection_offset.y()); + + for (int i = 0; i < clipInfo.size(); ++i) { + const QPainterClipInfo &info = clipInfo.at(i); + + QTransform combined = info.matrix * redirection; + + if (combined != q->state()->matrix) { + q->state()->matrix = combined; + q->transformChanged(); + } + + switch (info.clipType) { + case QPainterClipInfo::RegionClip: + q->clip(info.region, info.operation); + break; + case QPainterClipInfo::PathClip: + q->clip(info.path, info.operation); + break; + case QPainterClipInfo::RectClip: + q->clip(info.rect, info.operation); + break; + case QPainterClipInfo::RectFClip: { + qreal right = info.rectf.x() + info.rectf.width(); + qreal bottom = info.rectf.y() + info.rectf.height(); + qreal pts[] = { info.rectf.x(), info.rectf.y(), + right, info.rectf.y(), + right, bottom, + info.rectf.x(), bottom }; + QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint); + q->clip(vp, info.operation); + break; + } + } + } + + if (transform != q->state()->matrix) { + q->state()->matrix = transform; + q->transformChanged(); + } +} + + +bool QPaintEngineExPrivate::hasClipOperations() const +{ + Q_Q(const QPaintEngineEx); + + QPainter *p = q->painter(); + if (!p || !p->d_ptr) + return false; + + QPainterPrivate *pp = p->d_ptr; + QList clipInfo = pp->state->clipInfo; + + return !clipInfo.isEmpty(); +} /******************************************************************************* * @@ -244,13 +314,18 @@ static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, q ((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement); } +QPaintEngineEx::QPaintEngineEx() + : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) +{ + extended = true; +} + QPaintEngineEx::QPaintEngineEx(QPaintEngineExPrivate &data) : QPaintEngine(data, AllFeatures) { extended = true; } - QPainterState *QPaintEngineEx::createState(QPainterState *orig) const { if (!orig) @@ -483,6 +558,9 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op) void QPaintEngineEx::clip(const QRegion ®ion, Qt::ClipOperation op) { + if (region.numRects() == 1) + clip(region.boundingRect(), op); + QVector rects = region.rects(); if (rects.size() <= 32) { qreal pts[2*32*4]; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 1c55242..3f64260 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -139,27 +139,13 @@ public: QDebug Q_GUI_EXPORT &operator<<(QDebug &, const QVectorPath &path); #endif -class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate -{ -public: - QPaintEngineExPrivate(); - ~QPaintEngineExPrivate(); - - QStroker stroker; - QDashStroker dasher; - StrokeHandler *strokeHandler; - QStrokerOps *activeStroker; - QPen strokerPen; -}; - class QPixmapFilter; class Q_GUI_EXPORT QPaintEngineEx : public QPaintEngine { Q_DECLARE_PRIVATE(QPaintEngineEx) public: - inline QPaintEngineEx() - : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) { extended = true; } + QPaintEngineEx(); virtual QPainterState *createState(QPainterState *orig) const; @@ -224,6 +210,22 @@ protected: QPaintEngineEx(QPaintEngineExPrivate &data); }; +class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate +{ + Q_DECLARE_PUBLIC(QPaintEngineEx) +public: + QPaintEngineExPrivate(); + ~QPaintEngineExPrivate(); + + void replayClipOperations(); + bool hasClipOperations() const; + + QStroker stroker; + QDashStroker dasher; + StrokeHandler *strokeHandler; + QStrokerOps *activeStroker; + QPen strokerPen; +}; inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { switch (mode) { diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index f3df7a3..78cd713 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -507,6 +507,7 @@ private: friend class QFontEngineXLFD; friend class QWSManager; friend class QPaintEngine; + friend class QPaintEngineExPrivate; friend class QOpenGLPaintEngine; friend class QX11PaintEngine; friend class QX11PaintEnginePrivate; diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index ea57fdf..5c541d0 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -157,6 +157,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) simpleShaderProg->addShader(compiledShaders[PositionOnlyVertexShader]); simpleShaderProg->addShader(compiledShaders[MainFragmentShader]); simpleShaderProg->addShader(compiledShaders[ShockingPinkSrcFragmentShader]); + simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); simpleShaderProg->link(); if (!simpleShaderProg->isLinked()) { qCritical() << "Errors linking simple shader:" @@ -444,7 +445,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() requiredProgram.program->addShader(requiredProgram.compositionFragShader); // We have to bind the vertex attribute names before the program is linked: - requiredProgram.program->bindAttributeLocation("inputVertex", QT_VERTEX_COORDS_ATTR); + requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); if (useTextureCoords) requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 920d0bc..70cc67e 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -84,16 +84,20 @@ static const char* const qglslMainWithTexCoordsVertexShader = "\ static const char* const qglslPositionOnlyVertexShader = "\ attribute highp vec4 vertexCoordsArray;\ uniform highp mat4 pmvMatrix;\ + uniform highp float depth;\ void setPosition(void)\ {\ gl_Position = pmvMatrix * vertexCoordsArray;\ + gl_Position.z = depth;\ }"; static const char* const qglslUntransformedPositionVertexShader = "\ attribute highp vec4 vertexCoordsArray;\ + uniform highp float depth;\ void setPosition(void)\ {\ gl_Position = vertexCoordsArray;\ + gl_Position.z = depth;\ }"; // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 @@ -104,9 +108,11 @@ static const char* const qglslPositionWithPatternBrushVertexShader = "\ uniform mediump vec2 invertedTextureSize; \ uniform mediump mat3 brushTransform; \ varying mediump vec2 patternTexCoords; \ + uniform highp float depth;\ void setPosition(void) { \ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ + gl_Position.z = depth;\ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ @@ -136,9 +142,11 @@ static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\ uniform highp vec3 linearData; \ uniform highp mat3 brushTransform; \ varying mediump float index ; \ + uniform highp float depth;\ void setPosition() { \ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ + gl_Position.z = depth;\ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ @@ -166,10 +174,12 @@ static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\ uniform mediump vec2 halfViewportSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 A; \ + uniform highp float depth;\ void setPosition(void)\ {\ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ + gl_Position.z = depth; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ @@ -205,10 +215,12 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ uniform highp vec2 fmp; \ varying highp float b; \ varying highp vec2 A; \ + uniform highp float depth;\ void setPosition(void) \ {\ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ + gl_Position.z = depth; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ @@ -242,9 +254,11 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\ uniform mediump vec2 invertedTextureSize; \ uniform mediump mat3 brushTransform; \ varying mediump vec2 brushTextureCoords; \ + uniform highp float depth;\ void setPosition(void) { \ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ + gl_Position.z = depth; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 868adcf..fae3045 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -183,8 +183,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) pex->transferMode(BrushDrawingMode); - glDisable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); glViewport(0, 0, oldWidth, oldHeight); @@ -217,7 +217,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); glViewport(0, 0, pex->width, pex->height); - pex->updateDepthClip(); + pex->updateDepthScissorTest(); } void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) @@ -297,6 +297,11 @@ void QGL2PaintEngineExPrivate::useSimpleShader() shaderManager->simpleProgram()->setUniformValue("pmvMatrix", pmvMatrix); simpleShaderMatrixUniformDirty = false; } + + if (simpleShaderDepthUniformDirty) { + shaderManager->simpleProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth); + simpleShaderDepthUniformDirty = false; + } } @@ -709,6 +714,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) if (path.shape() == QVectorPath::RectangleHint) { QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y()); prepareForDraw(currentBrush->isOpaque()); + composite(rect); } else if (path.shape() == QVectorPath::EllipseHint) { @@ -739,13 +745,13 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) { // qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()"); - if (stencilBuferDirty) { + if (stencilBufferDirty) { // Clear the stencil buffer to zeros glDisable(GL_STENCIL_TEST); glStencilMask(0xFFFF); // Enable writing to stencil buffer, otherwise glClear wont do anything. glClearStencil(0); // Clear to zero glClear(GL_STENCIL_BUFFER_BIT); - stencilBuferDirty = false; + stencilBufferDirty = false; } glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes @@ -843,6 +849,7 @@ void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) // The shader program has changed so mark all uniforms as dirty: brushUniformsDirty = true; shaderMatrixUniformDirty = true; + depthUniformDirty = true; } if (brushUniformsDirty && mode != ImageDrawingMode) @@ -853,6 +860,11 @@ void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) shaderMatrixUniformDirty = false; } + if (depthUniformDirty) { + shaderManager->currentProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth); + depthUniformDirty = false; + } + if (useGlobalOpacityUniform) shaderManager->currentProgram()->setUniformValue("globalOpacity", (GLfloat)q->state()->opacity); } @@ -1062,7 +1074,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte matrix.translate(p.x(), p.y()); ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) : QFontEngineGlyphCache::Raster_A8; @@ -1146,6 +1157,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) } d->ctx->d_ptr->active_engine = this; + d->last_created_state = 0; d->drawable.makeCurrent(); QSize sz = d->drawable.size(); @@ -1172,12 +1184,16 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->brushUniformsDirty = true; d->matrixDirty = true; d->compositionModeDirty = true; - d->stencilBuferDirty = true; + d->stencilBufferDirty = true; + d->simpleShaderDepthUniformDirty = true; + d->depthUniformDirty = true; d->use_system_clip = !systemClip().isEmpty(); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); + glDepthFunc(GL_LEQUAL); + glDepthMask(false); QGLPixmapData *source = d->drawable.copyOnBegin(); if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) { @@ -1201,7 +1217,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->drawTexture(QRectF(rect), QRectF(rect), rect.size(), true); } - updateClipRegion(QRegion(), Qt::NoClip); + d->systemStateChanged(); return true; } @@ -1245,260 +1261,296 @@ void QGL2PaintEngineEx::ensureActive() ctx->d_ptr->active_engine = this; glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); glViewport(0, 0, d->width, d->height); + setState(state()); - d->updateDepthClip(); } } +void QGL2PaintEngineExPrivate::updateDepthScissorTest() +{ + Q_Q(QGL2PaintEngineEx); + if (q->state()->depthTestEnabled) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); -/////////////////////////////////// State/Clipping stolen from QOpenGLPaintEngine ////////////////////////////////////////// + if (q->state()->scissorTestEnabled) + glEnable(GL_SCISSOR_TEST); + else + glDisable(GL_SCISSOR_TEST); +} void QGL2PaintEngineEx::clipEnabledChanged() { Q_D(QGL2PaintEngineEx); - d->updateDepthClip(); + d->simpleShaderDepthUniformDirty = true; + d->depthUniformDirty = true; + + if (painter()->hasClipping()) { + d->regenerateDepthClip(); + } else { + if (d->use_system_clip) { + state()->currentDepth = -0.5f; + } else { + glDisable(GL_DEPTH_TEST); + state()->depthTestEnabled = false; + } + } } -void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) +void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, float depth) { -// qDebug("QGL2PaintEngineEx::clip()"); - const qreal *points = path.points(); - const QPainterPath::ElementType *types = path.elements(); - if (!types && path.shape() == QVectorPath::RectangleHint) { - QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]); - updateClipRegion(QRegion(r.toRect()), op); - return; - } + transferMode(BrushDrawingMode); - QPainterPath p; - if (types) { - int id = 0; - for (int i=0; istate()->needsDepthBufferClear) { + glDepthMask(true); + glClearDepth(0.5); + glClear(GL_DEPTH_BUFFER_BIT); + q->state()->needsDepthBufferClear = false; + glDepthMask(false); } - if (path.hints() & QVectorPath::WindingFill) - p.setFillRule(Qt::WindingFill); - updateClipRegion(QRegion(p.toFillPolygon().toPolygon(), p.fillRule()), op); - return; + if (path.isEmpty()) + return; + + glDisable(GL_BLEND); + glDepthMask(false); + + vertexCoordinateArray.clear(); + vertexCoordinateArray.addPath(path, inverseScale); + + glDepthMask(GL_FALSE); + fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); + + // Stencil the clip onto the clip buffer + glColorMask(false, false, false, false); + glDepthMask(true); + + shaderManager->simpleProgram()->setUniformValue("depth", depth); + simpleShaderDepthUniformDirty = true; + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + + glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0 + + glEnable(GL_STENCIL_TEST); + composite(vertexCoordinateArray.boundingRect()); + glDisable(GL_STENCIL_TEST); + + glColorMask(true, true, true, true); + glDepthMask(false); + + cleanStencilBuffer(vertexCoordinateArray.boundingRect()); } -void QGL2PaintEngineEx::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op) +void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) { -// qDebug("QGL2PaintEngineEx::updateClipRegion()"); +// qDebug("QGL2PaintEngineEx::clip()"); Q_D(QGL2PaintEngineEx); - QRegion sysClip = systemClip(); - if (op == Qt::NoClip && !d->use_system_clip) { - state()->hasClipping = false; - state()->clipRegion = QRegion(); - d->updateDepthClip(); - return; - } + if (op == Qt::ReplaceClip && !d->hasClipOperations()) + op = Qt::IntersectClip; - bool isScreenClip = false; - if (!d->use_system_clip) { - QVector untransformedRects = clipRegion.rects(); + if (!path.isEmpty() && op == Qt::IntersectClip && (path.hints() & QVectorPath::RectangleHint)) { + const QPointF* const points = reinterpret_cast(path.points()); + QRectF rect(points[0], points[2]); - if (untransformedRects.size() == 1) { - QPainterPath path; - path.addRect(untransformedRects[0]); - //path = d->matrix.map(path); - path = state()->matrix.map(path); - -// if (path.contains(QRectF(QPointF(), d->drawable.size()))) -// isScreenClip = true; - if (path.contains(QRectF(0.0, 0.0, d->width, d->height))) - isScreenClip = true; + if (state()->matrix.type() <= QTransform::TxScale) { + rect = state()->matrix.mapRect(rect); + + if (d->use_system_clip && rect.contains(d->systemClip.boundingRect()) + || rect.contains(QRect(0, 0, d->width, d->height))) + return; } } -// QRegion region = isScreenClip ? QRegion() : clipRegion * d->matrix; - QRegion region = isScreenClip ? QRegion() : clipRegion * state()->matrix; switch (op) { case Qt::NoClip: - if (!d->use_system_clip) - break; - state()->clipRegion = sysClip; + if (d->use_system_clip) { + glEnable(GL_DEPTH_TEST); + state()->depthTestEnabled = true; + state()->currentDepth = -0.5; + } else { + glDisable(GL_DEPTH_TEST); + state()->depthTestEnabled = false; + } + state()->canRestoreClip = false; break; case Qt::IntersectClip: - if (isScreenClip) - return; - if (state()->hasClipping) { - state()->clipRegion &= region; - break; - } - // fall through + state()->maxDepth = (1.0f + state()->maxDepth) * 0.5; + d->writeClip(path, state()->maxDepth); + state()->currentDepth = 1.5 * state()->maxDepth - 0.5f; + state()->depthTestEnabled = true; + break; case Qt::ReplaceClip: - if (d->use_system_clip && !sysClip.isEmpty()) - state()->clipRegion = region & sysClip; - else - state()->clipRegion = region; + d->systemStateChanged(); + state()->maxDepth = 0.5f; + glDepthFunc(GL_ALWAYS); + d->writeClip(path, state()->maxDepth); + state()->currentDepth = 0.25f; + state()->canRestoreClip = false; + state()->depthTestEnabled = true; break; case Qt::UniteClip: - state()->clipRegion |= region; - if (d->use_system_clip && !sysClip.isEmpty()) - state()->clipRegion &= sysClip; - break; - default: + glDepthFunc(GL_ALWAYS); + d->writeClip(path, state()->maxDepth); + state()->canRestoreClip = false; + state()->depthTestEnabled = true; break; } - if (isScreenClip) { - state()->hasClipping = false; - state()->clipRegion = QRegion(); - } else { - state()->hasClipping = op != Qt::NoClip || d->use_system_clip; + glDepthFunc(GL_LEQUAL); + if (state()->depthTestEnabled) { + glEnable(GL_DEPTH_TEST); + d->simpleShaderDepthUniformDirty = true; + d->depthUniformDirty = true; } - - d->updateDepthClip(); } -void QGL2PaintEngineExPrivate::systemStateChanged() +void QGL2PaintEngineExPrivate::regenerateDepthClip() { - Q_Q(QGL2PaintEngineEx); - use_system_clip = !systemClip.isEmpty(); - - if (q->painter()->hasClipping()) - q->updateClipRegion(q->painter()->clipRegion(), Qt::ReplaceClip); - else - q->updateClipRegion(QRegion(), Qt::NoClip); + systemStateChanged(); + replayClipOperations(); } -void QGL2PaintEngineExPrivate::updateDepthClip() +void QGL2PaintEngineExPrivate::systemStateChanged() { -// qDebug("QGL2PaintEngineExPrivate::updateDepthClip()"); - Q_Q(QGL2PaintEngineEx); + use_system_clip = !systemClip.isEmpty(); - q->ensureActive(); glDisable(GL_DEPTH_TEST); + q->state()->depthTestEnabled = false; + q->state()->scissorTestEnabled = false; + q->state()->needsDepthBufferClear = true; + glDisable(GL_SCISSOR_TEST); - if (!q->state()->hasClipping) - return; + q->state()->currentDepth = -0.5f; + q->state()->maxDepth = 0.5f; - const QVector rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects(); - if (rects.size() == 1) { - QRect fastClip = rects.at(0); + if (use_system_clip) { + QRect bounds = systemClip.boundingRect(); + if (systemClip.numRects() == 1 + && bounds == QRect(0, 0, width, height)) + { + q->state()->needsDepthBufferClear = true; + } else { + glEnable(GL_SCISSOR_TEST); - glEnable(GL_SCISSOR_TEST); + const int left = bounds.left(); + const int width = bounds.width(); + const int bottom = height - (bounds.top() + bounds.height()); + const int height = bounds.height(); - const int left = fastClip.left(); - const int width = fastClip.width(); - const int bottom = height - (fastClip.bottom() + 1); - const int height = fastClip.height(); + glScissor(left, bottom, width, height); - glScissor(left, bottom, width, height); - return; - } + QTransform transform = q->state()->matrix; + q->state()->matrix = QTransform(); + q->transformChanged(); - glClearDepth(0x0); - glDepthMask(true); - glClear(GL_DEPTH_BUFFER_BIT); - glClearDepth(0x1); + q->state()->needsDepthBufferClear = false; - glEnable(GL_SCISSOR_TEST); - for (int i = 0; i < rects.size(); ++i) { - QRect rect = rects.at(i); + glDepthMask(true); - const int left = rect.left(); - const int width = rect.width(); - const int bottom = height - (rect.bottom() + 1); - const int height = rect.height(); + glClearDepth(0); + glClear(GL_DEPTH_BUFFER_BIT); - glScissor(left, bottom, width, height); + QPainterPath path; + path.addRegion(systemClip); - glClear(GL_DEPTH_BUFFER_BIT); - } - glDisable(GL_SCISSOR_TEST); + glDepthFunc(GL_ALWAYS); + writeClip(qtVectorPathForPath(path), 0.0f); + glDepthFunc(GL_LEQUAL); - glDepthMask(false); - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); -} + glEnable(GL_DEPTH_TEST); + q->state()->depthTestEnabled = true; + q->state()->scissorTestEnabled = true; + q->state()->matrix = transform; + q->transformChanged(); + } + q->state()->currentDepth = -0.5f; + simpleShaderDepthUniformDirty = true; + depthUniformDirty = true; + } +} void QGL2PaintEngineEx::setState(QPainterState *new_state) { -// qDebug("QGL2PaintEngineEx::setState()"); + // qDebug("QGL2PaintEngineEx::setState()"); Q_D(QGL2PaintEngineEx); QOpenGL2PaintEngineState *s = static_cast(new_state); - QOpenGL2PaintEngineState *old_state = state(); - const bool needsDepthClipUpdate = !old_state - || s->clipEnabled != old_state->clipEnabled - || (s->clipEnabled && s->clipRegion != old_state->clipRegion); QPaintEngineEx::setState(s); - if (needsDepthClipUpdate) - d->updateDepthClip(); + if (s == d->last_created_state) { + d->last_created_state = 0; + return; + } d->matrixDirty = true; d->compositionModeDirty = true; d->brushTextureDirty = true; d->brushUniformsDirty = true; + d->simpleShaderDepthUniformDirty = true; + d->depthUniformDirty = true; d->simpleShaderMatrixUniformDirty = true; d->shaderMatrixUniformDirty = true; + + if (old_state && old_state != s && old_state->canRestoreClip) { + d->updateDepthScissorTest(); + glDepthMask(false); + glDepthFunc(GL_LEQUAL); + s->maxDepth = old_state->maxDepth; + } else { + d->regenerateDepthClip(); + } } QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const { + Q_D(const QGL2PaintEngineEx); + QOpenGL2PaintEngineState *s; if (!orig) s = new QOpenGL2PaintEngineState(); else s = new QOpenGL2PaintEngineState(*static_cast(orig)); + d->last_created_state = s; return s; } QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other) : QPainterState(other) { - clipRegion = other.clipRegion; - hasClipping = other.hasClipping; + needsDepthBufferClear = other.needsDepthBufferClear; + depthTestEnabled = other.depthTestEnabled; + scissorTestEnabled = other.scissorTestEnabled; + currentDepth = other.currentDepth; + maxDepth = other.maxDepth; + canRestoreClip = other.canRestoreClip; } QOpenGL2PaintEngineState::QOpenGL2PaintEngineState() { - hasClipping = false; + needsDepthBufferClear = true; + depthTestEnabled = false; + scissorTestEnabled = false; + currentDepth = -0.5f; + maxDepth = 0.5f; + canRestoreClip = true; } QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 7213474..2cea8d6 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -77,8 +77,15 @@ public: QOpenGL2PaintEngineState(); ~QOpenGL2PaintEngineState(); - QRegion clipRegion; - bool hasClipping; + bool needsDepthBufferClear; + qreal depthBufferClearValue; + + bool depthTestEnabled; + bool scissorTestEnabled; + qreal currentDepth; + qreal maxDepth; + + bool canRestoreClip; }; @@ -116,7 +123,6 @@ public: Type type() const { return OpenGL; } - // State stuff is just for clipping and ripped off from QGLPaintEngine void setState(QPainterState *s); QPainterState *createState(QPainterState *orig) const; inline QOpenGL2PaintEngineState *state() { @@ -125,7 +131,6 @@ public: inline const QOpenGL2PaintEngineState *state() const { return static_cast(QPaintEngineEx::state()); } - void updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op); virtual void sync(); private: @@ -180,9 +185,10 @@ public: QGLDrawable drawable; int width, height; QGLContext *ctx; - EngineMode mode; + mutable QOpenGL2PaintEngineState *last_created_state; + // Dirty flags bool matrixDirty; // Implies matrix uniforms are also dirty bool compositionModeDirty; @@ -190,7 +196,9 @@ public: bool brushUniformsDirty; bool simpleShaderMatrixUniformDirty; bool shaderMatrixUniformDirty; - bool stencilBuferDirty; + bool stencilBufferDirty; + bool depthUniformDirty; + bool simpleShaderDepthUniformDirty; const QBrush* currentBrush; // May not be the state's brush! @@ -206,8 +214,9 @@ public: QGLEngineShaderManager* shaderManager; - // Clipping & state stuff stolen from QOpenGLPaintEngine: - void updateDepthClip(); + void writeClip(const QVectorPath &path, float depth); + void updateDepthScissorTest(); + void regenerateDepthClip(); void systemStateChanged(); uint use_system_clip : 1; }; -- cgit v0.12 From 73ea2f5766d2c0925af1bee7037610c2c75e89c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 9 Jun 2009 10:54:42 +0200 Subject: Resolved FBO extensions as well when resolving GL 2 extensions. The new GL 2 text drawing requries the FBO function pointers to be resolved. --- src/opengl/qglextensions.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp index 3c198fb..10ca613 100644 --- a/src/opengl/qglextensions.cpp +++ b/src/opengl/qglextensions.cpp @@ -337,6 +337,9 @@ bool qt_resolve_version_2_0_functions(QGLContext *ctx) if (!qt_resolve_version_1_3_functions(ctx)) gl2supported = false; + if (!qt_resolve_framebufferobject_extensions(ctx)) + gl2supported = false; + if (glStencilOpSeparate) return gl2supported; -- cgit v0.12 From 6495eb4953c5fca93d8cfe91c66b50ce82ce24cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 9 Jun 2009 13:02:47 +0200 Subject: Optimized stencil buffer clearing in GL 2 paint engine. Based on Zack's patch, 17e1bca1ce366395f8331e16aa96b7176ca1abac. Instead of manually clearing the stencil buffer after drawing we simply do the clearing and drawing in one go. Reviewed-by: Trond --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 50 ++++------------------ .../gl2paintengineex/qpaintengineex_opengl2_p.h | 1 - 2 files changed, 9 insertions(+), 42 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index fae3045..bdea187 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -732,12 +732,14 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) // Stencil the brush onto the dest buffer glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0 + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glEnable(GL_STENCIL_TEST); prepareForDraw(currentBrush->isOpaque()); composite(vertexCoordinateArray.boundingRect()); glDisable(GL_STENCIL_TEST); - cleanStencilBuffer(vertexCoordinateArray.boundingRect()); + glStencilMask(0); } } @@ -745,17 +747,17 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) { // qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()"); + glStencilMask(0xFFFF); // Enable stencil writes + if (stencilBufferDirty) { // Clear the stencil buffer to zeros glDisable(GL_STENCIL_TEST); - glStencilMask(0xFFFF); // Enable writing to stencil buffer, otherwise glClear wont do anything. glClearStencil(0); // Clear to zero glClear(GL_STENCIL_BUFFER_BIT); stencilBufferDirty = false; } glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes - glStencilMask(0xFFFF); // Enable stencil writes glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test // Setup the stencil op: @@ -765,7 +767,7 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve } else glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit - // No point in using a fancy gradiant shader for writing into the stencil buffer! + // No point in using a fancy gradient shader for writing into the stencil buffer! useSimpleShader(); glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d @@ -776,41 +778,6 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve // Enable color writes & disable stencil writes glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilMask(0); -} - -void QGL2PaintEngineExPrivate::cleanStencilBuffer(const QGLRect& area) -{ -// qDebug("QGL2PaintEngineExPrivate::cleanStencilBuffer()"); - useSimpleShader(); - - GLfloat rectVerts[] = { - area.left, area.top, - area.left, area.bottom, - area.right, area.bottom, - area.right, area.top - }; - - glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, rectVerts); - - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes - glStencilMask(0xFFFF); // Enable writing to stencil buffer - glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // Write 0's to stencil buffer - - glDisable(GL_BLEND); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - - // Enable color writes & disable stencil writes - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilMask(0); - glDisable(GL_STENCIL_TEST); } void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) @@ -1339,15 +1306,16 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, float depth) glDepthFunc(GL_ALWAYS); glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0 + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glEnable(GL_STENCIL_TEST); composite(vertexCoordinateArray.boundingRect()); glDisable(GL_STENCIL_TEST); + glStencilMask(0); + glColorMask(true, true, true, true); glDepthMask(false); - - cleanStencilBuffer(vertexCoordinateArray.boundingRect()); } void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 2cea8d6..db39ced 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -174,7 +174,6 @@ public: // ^ Composites the bounding rect onto dest buffer void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill); // ^ Calls drawVertexArrays to render into stencil buffer - void cleanStencilBuffer(const QGLRect& area); void prepareForDraw(bool srcPixelsAreOpaque); -- cgit v0.12 From 923cadc12b993a0b41200750f151d73662856482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 9 Jun 2009 13:23:08 +0200 Subject: Prevented pixmap FBOs from growing too big. If we're painting to very wide and then very tall pixmaps we don't want the FBO to grow to max_width * max_height, instead we should recreate the FBO if it grows too large compared to what's being painted. Reviewed-by: Trond --- src/opengl/qpixmapdata_gl.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 8d94c8b..98c406b 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -389,6 +389,11 @@ QPaintEngine* QGLPixmapData::paintEngine() const sz.setWidth(qMax(m_width, qRound(sz.width() * 1.5))); if (sz.height() < m_height) sz.setHeight(qMax(m_height, qRound(sz.height() * 1.5))); + + // wasting too much space? + if (sz.width() * sz.height() > m_width * m_height * 2.5) + sz = QSize(m_width, m_height); + delete textureBufferStack.at(currentTextureBuffer).fbo; textureBufferStack[currentTextureBuffer] = createTextureBuffer(sz, textureBufferStack.at(currentTextureBuffer).engine); -- cgit v0.12 From 7cd3e8233090f2937e38aff846a30635bcd14eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 9 Jun 2009 14:05:03 +0200 Subject: Removed background caching in embeddeddialogs demo. No point in caching a background that is already a pixmap. When maximizing the window this pixmap gets huge, and it doesn't help performance either. Reviewed-by: Trond --- demos/embeddeddialogs/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/demos/embeddeddialogs/main.cpp b/demos/embeddeddialogs/main.cpp index cfb31c4..c9b6ee1 100644 --- a/demos/embeddeddialogs/main.cpp +++ b/demos/embeddeddialogs/main.cpp @@ -76,7 +76,6 @@ int main(int argc, char *argv[]) view.scale(0.5, 0.5); view.setRenderHints(view.renderHints() | QPainter::Antialiasing | QPainter::SmoothPixmapTransform); view.setBackgroundBrush(QPixmap(":/No-Ones-Laughing-3.jpg")); - view.setCacheMode(QGraphicsView::CacheBackground); view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.show(); view.setWindowTitle("Embedded Dialogs Demo"); -- cgit v0.12 From 5039d39f3af42d23bba1f1c0ae10365ebcd82b4a Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 9 Jun 2009 12:17:03 +0200 Subject: small change to reduce static data size --- src/corelib/kernel/qvariant.cpp | 2 +- src/gui/text/qtexthtmlparser.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 2ff9818..e6f1c48 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1823,7 +1823,7 @@ QVariant::Type QVariant::nameToType(const char *name) #ifndef QT_NO_DATASTREAM enum { MapFromThreeCount = 35 }; -static const uint map_from_three[MapFromThreeCount] = +static const ushort map_from_three[MapFromThreeCount] = { QVariant::Invalid, QVariant::Map, diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index ee743dc..76c59c3 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -343,7 +343,7 @@ static QChar resolveEntity(const QString &entity) return e->code; } -static const uint windowsLatin1ExtendedCharacters[0xA0 - 0x80] = { +static const ushort windowsLatin1ExtendedCharacters[0xA0 - 0x80] = { 0x20ac, // 0x80 0x0081, // 0x81 direct mapping 0x201a, // 0x82 -- cgit v0.12 From b9f5e151b3c0bca74136720c5b42c9a93c8f25a8 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 9 Jun 2009 14:04:55 +0200 Subject: small improvement/refactor to cssparser --- src/gui/text/qcssparser.cpp | 42 +----------------------------- src/gui/text/qcssparser_p.h | 1 - tests/auto/qcssparser/tst_cssparser.cpp | 45 +++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 0494b72..a05e5a1 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -57,46 +57,6 @@ QT_BEGIN_NAMESPACE using namespace QCss; -const char *Scanner::tokenName(QCss::TokenType t) -{ - switch (t) { - case NONE: return "NONE"; - case S: return "S"; - case CDO: return "CDO"; - case CDC: return "CDC"; - case INCLUDES: return "INCLUDES"; - case DASHMATCH: return "DASHMATCH"; - case LBRACE: return "LBRACE"; - case PLUS: return "PLUS"; - case GREATER: return "GREATER"; - case COMMA: return "COMMA"; - case STRING: return "STRING"; - case INVALID: return "INVALID"; - case IDENT: return "IDENT"; - case HASH: return "HASH"; - case ATKEYWORD_SYM: return "ATKEYWORD_SYM"; - case EXCLAMATION_SYM: return "EXCLAMATION_SYM"; - case LENGTH: return "LENGTH"; - case PERCENTAGE: return "PERCENTAGE"; - case NUMBER: return "NUMBER"; - case FUNCTION: return "FUNCTION"; - case COLON: return "COLON"; - case SEMICOLON: return "SEMICOLON"; - case RBRACE: return "RBRACE"; - case SLASH: return "SLASH"; - case MINUS: return "MINUS"; - case DOT: return "DOT"; - case STAR: return "STAR"; - case LBRACKET: return "LBRACKET"; - case RBRACKET: return "RBRACKET"; - case EQUAL: return "EQUAL"; - case LPAREN: return "LPAREN"; - case RPAREN: return "RPAREN"; - case OR: return "OR"; - } - return ""; -} - struct QCssKnownValue { const char *name; @@ -279,7 +239,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = { }; //Map id to strings as they appears in the 'values' array above -static const int indexOfId[NumKnownValues] = { 0, 40, 47, 41, 48, 53, 34, 26, 68, 69, 25, 42, 5, 62, 46, +static const short indexOfId[NumKnownValues] = { 0, 40, 47, 41, 48, 53, 34, 26, 68, 69, 25, 42, 5, 62, 46, 29, 57, 58, 27, 50, 60, 6, 10, 38, 55, 19, 13, 17, 18, 20, 21, 49, 24, 45, 65, 36, 3, 2, 39, 61, 16, 11, 56, 14, 32, 63, 54, 64, 33, 67, 8, 28, 37, 12, 35, 59, 7, 9, 4, 66, 52, 22, 23, 30, 31, 1, 15, 0, 51, 44, 43 }; diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index 72bd637..81f306d 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -731,7 +731,6 @@ class Q_AUTOTEST_EXPORT Scanner public: static QString preprocess(const QString &input, bool *hasEscapeSequences = 0); static void scan(const QString &preprocessedInput, QVector *symbols); - static const char *tokenName(TokenType t); }; class Q_GUI_EXPORT Parser diff --git a/tests/auto/qcssparser/tst_cssparser.cpp b/tests/auto/qcssparser/tst_cssparser.cpp index b41a745..27258b7 100644 --- a/tests/auto/qcssparser/tst_cssparser.cpp +++ b/tests/auto/qcssparser/tst_cssparser.cpp @@ -114,11 +114,52 @@ void tst_CssParser::scanner_data() } } + +static char *tokenName(QCss::TokenType t) +{ + switch (t) { + case QCss::NONE: return "NONE"; + case QCss::S: return "S"; + case QCss::CDO: return "CDO"; + case QCss::CDC: return "CDC"; + case QCss::INCLUDES: return "INCLUDES"; + case QCss::DASHMATCH: return "DASHMATCH"; + case QCss::LBRACE: return "LBRACE"; + case QCss::PLUS: return "PLUS"; + case QCss::GREATER: return "GREATER"; + case QCss::COMMA: return "COMMA"; + case QCss::STRING: return "STRING"; + case QCss::INVALID: return "INVALID"; + case QCss::IDENT: return "IDENT"; + case QCss::HASH: return "HASH"; + case QCss::ATKEYWORD_SYM: return "ATKEYWORD_SYM"; + case QCss::EXCLAMATION_SYM: return "EXCLAMATION_SYM"; + case QCss::LENGTH: return "LENGTH"; + case QCss::PERCENTAGE: return "PERCENTAGE"; + case QCss::NUMBER: return "NUMBER"; + case QCss::FUNCTION: return "FUNCTION"; + case QCss::COLON: return "COLON"; + case QCss::SEMICOLON: return "SEMICOLON"; + case QCss::RBRACE: return "RBRACE"; + case QCss::SLASH: return "SLASH"; + case QCss::MINUS: return "MINUS"; + case QCss::DOT: return "DOT"; + case QCss::STAR: return "STAR"; + case QCss::LBRACKET: return "LBRACKET"; + case QCss::RBRACKET: return "RBRACKET"; + case QCss::EQUAL: return "EQUAL"; + case QCss::LPAREN: return "LPAREN"; + case QCss::RPAREN: return "RPAREN"; + case QCss::OR: return "OR"; + } + return ""; +} + static void debug(const QVector &symbols, int index = -1) { qDebug() << "all symbols:"; for (int i = 0; i < symbols.count(); ++i) - qDebug() << "(" << i << "); Token:" << QCss::Scanner::tokenName(symbols.at(i).token) << "; Lexem:" << symbols.at(i).lexem(); + qDebug() << "(" << i << "); Token:" << tokenName(symbols.at(i).token) << "; Lexem:" << symbols.at(i).lexem(); if (index != -1) qDebug() << "failure at index" << index; } @@ -160,7 +201,7 @@ void tst_CssParser::scanner() QCOMPARE(l.count(), 2); const QString expectedToken = l.at(0); const QString expectedLexem = l.at(1); - QString actualToken = QString::fromLatin1(QCss::Scanner::tokenName(symbols.at(i).token)); + QString actualToken = QString::fromLatin1(tokenName(symbols.at(i).token)); if (actualToken != expectedToken) { debug(symbols, i); QCOMPARE(actualToken, expectedToken); -- cgit v0.12 From d367ee08d1a07f1a30665b77ec11acec96e65a65 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 9 Jun 2009 15:23:59 +0200 Subject: Doc: Fixed QWebPage::forwardUnsupportedContent documentation and added more information about Web plugins. Reviewed-by: Trust Me --- src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp | 8 +++++--- src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp | 22 +++++++++++++++------- src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc | 3 ++- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp index 01b68eb..77add54 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp @@ -1986,10 +1986,12 @@ bool QWebPage::isContentEditable() const /*! \property QWebPage::forwardUnsupportedContent - \brief whether QWebPage should forward unsupported content through the - unsupportedContent signal + \brief whether QWebPage should forward unsupported content - If disabled the download of such content is aborted immediately. + If enabled, the unsupportedContent() signal is emitted with a network reply that + can be used to read the content. + + If disabled, the download of such content is aborted immediately. By default unsupported content is not forwarded. */ diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp index 1ad23f6..b516263 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp @@ -213,17 +213,25 @@ QWebSettings *QWebSettings::globalSettings() Each QWebPage object has its own QWebSettings object, which configures the settings for that page. If a setting is not configured, then it is looked up in the global settings object, which can be accessed using - QWebSettings::globalSettings(). + globalSettings(). - QWebSettings allows configuring font properties such as font size and font - family, the location of a custom stylesheet, and generic attributes like java - script, plugins, etc. The \l{QWebSettings::WebAttribute}{WebAttribute} - enum further describes this. + QWebSettings allows configuration of browser properties, such as font sizes and + families, the location of a custom style sheet, and generic attributes like + JavaScript and plugins. Individual attributes are set using the setAttribute() + function. The \l{QWebSettings::WebAttribute}{WebAttribute} enum further describes + each attribute. - QWebSettings also configures global properties such as the web page memory - cache and the web page icon database, local database storage and offline + QWebSettings also configures global properties such as the Web page memory + cache and the Web page icon database, local database storage and offline applications storage. + \section1 Enabling Plugins + + Support for browser plugins can enabled by setting the + \l{QWebSettings::PluginsEnabled}{PluginsEnabled} attribute. For many applications, + this attribute is enabled for all pages by setting it on the + \l{globalSettings()}{global settings object}. + \section1 Web Application Support WebKit provides support for features specified in \l{HTML 5} that improve the diff --git a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc index 06305e0..119c126 100644 --- a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc +++ b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc @@ -96,7 +96,8 @@ Since WebKit supports the Netscape Plugin API, Qt applications can display Web pages that embed common plugins, as long as the user has the appropriate - binary files for those plugins installed. + binary files for those plugins installed and the \l{QWebSettings::PluginsEnabled} + attribute is set for the application. The following locations are searched for plugins: -- cgit v0.12 From 4d7a1cbb060a7fe933f674e1a9ebaa9e81fe2896 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 9 Jun 2009 15:54:19 +0200 Subject: qdoc: The gray version. --- src/corelib/kernel/qtimer.cpp | 2 +- tools/qdoc3/htmlgenerator.cpp | 2 -- tools/qdoc3/test/classic.css | 49 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 8ca53b9..29bdf7e 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -251,7 +251,7 @@ void QTimer::stop() /*! - \reimp + \reimp */ void QTimer::timerEvent(QTimerEvent *e) { diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 0c21534..fb33de4 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -2349,8 +2349,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*()" static const QString linkTag("link"); - if (src.contains("setAcceptDrops")) - qDebug() << "SRC:" << src; bool done = false; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { diff --git a/tools/qdoc3/test/classic.css b/tools/qdoc3/test/classic.css index 85bb348..9c59c81 100644 --- a/tools/qdoc3/test/classic.css +++ b/tools/qdoc3/test/classic.css @@ -14,12 +14,49 @@ H3 { h3.fn,span.fn { - background-color: #e0eff6; + background-color: #eee; border-width: 1px; border-style: solid; - border-color: #3388be #3388be #e9f8ff #3388be; + border-color: #ddd #ddd #ddd #ddd ; font-weight: bold; padding: 6px 0px 6px 10px; + margin: 42px 0px 0px 0px; +} + +hr { + border: 0; + color: #9E9E9E; + background-color: #ccc; + height: 1px; + width: 100%; + text-align: left; + margin: 34px 0px 34px 0px; +} + +table { + border-width: 1px 1px 1px 1px; + border-style: solid; + border-color: #dddddd; + border-collapse: collapse; + background-color: #f0f0f0; + margin-left: 1.5%; + width: 97% +} + +table th { + border-width: 1px 1px 1px 2px; + padding: 4px; + border-style: solid; + border-color: #444; + color:white; + background-color:#444; +} + +p { + margin-left: 1.5%; + margin-top: 8px; + width: 97% + margin-bottom: 8px; } a:link @@ -66,7 +103,7 @@ body table td.memItemLeft { width: 200px; - padding: 1px 0px 0px 8px; + padding: 2px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; @@ -76,7 +113,7 @@ table td.memItemLeft { border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; - border-top-style: solid; + border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; @@ -85,7 +122,7 @@ table td.memItemLeft { white-space: nowrap } table td.memItemRight { - padding: 1px 8px 0px 8px; + padding: 2px 8px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; @@ -95,7 +132,7 @@ table td.memItemRight { border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; - border-top-style: solid; + border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; -- cgit v0.12 From 6185ff436816738e933e3c88d44c45faa7f401f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 9 Jun 2009 16:13:18 +0200 Subject: Remove duplicated code for removing an item from the scene. Before we had almost two identical functions for removing an item from the scene. There was only minor differences depending on whether the item was removed from QGraphicsScene::removeItem or from the item's destructor. Now we have one function that handles both cases just fine. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 36 +++--- src/gui/graphicsview/qgraphicsitem_p.h | 6 +- src/gui/graphicsview/qgraphicsscene.cpp | 193 +++++++++++++------------------- src/gui/graphicsview/qgraphicsscene.h | 1 - src/gui/graphicsview/qgraphicsscene_p.h | 5 +- 5 files changed, 101 insertions(+), 140 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5ba87ee..db16213 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -840,11 +840,11 @@ QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query /*! \internal - If \a deleting is true, then this item is being deleted, and \a parent is - null. Make sure not to trigger any pure virtual function calls (e.g., - prepareGeometryChange). + Make sure not to trigger any pure virtual function calls (e.g., + prepareGeometryChange) if the item is in its destructor, i.e. + inDestructor is 1. */ -void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool deleting) +void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) { Q_Q(QGraphicsItem); if (newParent == q) { @@ -871,7 +871,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de // We anticipate geometry changes. If the item is deleted, it will be // removed from the index at a later stage, and the whole scene will be // updated. - if (!deleting) + if (!inDestructor) q_ptr->prepareGeometryChange(); const QVariant thisPointerVariant(qVariantFromValue(q)); @@ -883,7 +883,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de // Update toplevelitem list. If this item is being deleted, its parent // will be 0 but we don't want to register/unregister it in the TLI list. - if (scene && !deleting) { + if (scene && !inDestructor) { if (parent && !newParent) { scene->d_func()->registerTopLevelItem(q); } else if (!parent && newParent) { @@ -931,7 +931,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); - if (!deleting) { + if (!inDestructor) { // Update item visible / enabled. if (!visible && !explicitlyHidden) setVisibleHelper(true, /* explicit = */ false); @@ -1115,22 +1115,22 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, */ QGraphicsItem::~QGraphicsItem() { - if (d_ptr->scene && !d_ptr->parent) - d_ptr->scene->d_func()->unregisterTopLevelItem(this); + d_ptr->inDestructor = 1; + d_ptr->removeExtraItemCache(); clearFocus(); + if (!d_ptr->children.isEmpty()) { + QList oldChildren = d_ptr->children; + qDeleteAll(oldChildren); + Q_ASSERT(d_ptr->children.isEmpty()); + } - d_ptr->removeExtraItemCache(); - QList oldChildren = d_ptr->children; - qDeleteAll(oldChildren); - Q_ASSERT(d_ptr->children.isEmpty()); - - d_ptr->setParentItemHelper(0, /* deleting = */ true); if (d_ptr->scene) - d_ptr->scene->d_func()->_q_removeItemLater(this); + d_ptr->scene->d_func()->removeItemHelper(this); + else + d_ptr->setParentItemHelper(0); delete d_ptr->transformData; - delete d_ptr; qt_dataStore()->data.remove(this); @@ -1272,7 +1272,7 @@ QGraphicsWidget *QGraphicsItem::window() const */ void QGraphicsItem::setParentItem(QGraphicsItem *parent) { - d_ptr->setParentItemHelper(parent, /* deleting = */ false); + d_ptr->setParentItemHelper(parent); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index e2a37a1..c502655 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -148,6 +148,7 @@ public: paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), geometryChanged(0), + inDestructor(0), globalStackingOrder(-1), q_ptr(0) { @@ -183,7 +184,7 @@ public: void resolveDepth(int parentDepth); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); - void setParentItemHelper(QGraphicsItem *parent, bool deleting); + void setParentItemHelper(QGraphicsItem *parent); void childrenBoundingRectHelper(QTransform *x, QRectF *rect); void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, const QRegion &exposedRegion, bool allItems = false) const; @@ -403,7 +404,8 @@ public: quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; quint32 geometryChanged : 1; - quint32 unused : 16; // feel free to use + quint32 inDestructor : 1; + quint32 unused : 15; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e43c9cd..b63efd6 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -710,39 +710,65 @@ void QGraphicsScenePrivate::_q_processDirtyItems() \internal Schedules an item for removal. This function leaves some stale indexes - around in the BSP tree; these will be cleaned up the next time someone - triggers purgeRemovedItems(). + around in the BSP tree if called from the item's destructor; these will + be cleaned up the next time someone triggers purgeRemovedItems(). - Note: This function is called from QGraphicsItem's destructor. \a item is + Note: This function might get called from QGraphicsItem's destructor. \a item is being destroyed, so we cannot call any pure virtual functions on it (such as boundingRect()). Also, it is unnecessary to update the item's own state in any way. - - ### Refactoring: This function shares much functionality with removeItem() */ -void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) +void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) { Q_Q(QGraphicsScene); - // Clear focus on the item to remove any reference in the focusWidget - // chain. + // Clear focus on the item to remove any reference in the focusWidget chain. item->clearFocus(); - - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - indexedItems[index] = (QGraphicsItem *)0; - if (!purgePending) { + markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true); + + if (!item->d_ptr->inDestructor) { + // Can potentially call item->boundingRect() (virtual function), that's why + // we only can call this function if the item is not in its destructor. + removeFromIndex(item); + } else if (item->d_ptr->index != -1) { + // Important: The index is useless until purgeRemovedItems() is called. + indexedItems[item->d_ptr->index] = (QGraphicsItem *)0; + if (!purgePending) purgePending = true; - q->update(); - } removedItems << item; } else { // Recently added items are purged immediately. unindexedItems() never // contains stale items. unindexedItems.removeAll(item); - q->update(); + } + + if (!item->d_ptr->inDestructor && item == tabFocusFirst) { + QGraphicsWidget *widget = static_cast(item); + widget->d_func()->fixFocusChainBeforeReparenting(0, 0); + } + + item->d_func()->scene = 0; + + // Remove from parent, or unregister from toplevels. + if (QGraphicsItem *parentItem = item->parentItem()) { + if (parentItem->scene()) { + Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem", + "Parent item's scene is different from this item's scene"); + item->d_ptr->setParentItemHelper(0); + } + } else { + unregisterTopLevelItem(item); + } + + if (!item->d_ptr->inDestructor) { + // Remove from our item lists. + int index = item->d_func()->index; + if (index != -1) { + freeItemIndexes << index; + indexedItems[index] = 0; + } else { + unindexedItems.removeAll(item); + } } // Reset the mouse grabber and focus item data. @@ -776,13 +802,19 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) ++iterator; } - // Reset the mouse grabber + if (!item->d_ptr->inDestructor) { + // Remove all children recursively + for (int i = 0; i < item->d_ptr->children.size(); ++i) + q->removeItem(item->d_ptr->children.at(i)); + } + + // Reset the mouse grabber and focus item data. if (mouseGrabberItems.contains(item)) - ungrabMouse(item, /* item is dying */ true); + ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor); // Reset the keyboard grabber if (keyboardGrabberItems.contains(item)) - ungrabKeyboard(item, /* item is dying */ true); + ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor); // Reset the last mouse grabber item if (item == lastMouseGrabberItem) @@ -801,8 +833,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) */ void QGraphicsScenePrivate::purgeRemovedItems() { - Q_Q(QGraphicsScene); - if (!purgePending && removedItems.isEmpty()) return; @@ -818,9 +848,6 @@ void QGraphicsScenePrivate::purgeRemovedItems() freeItemIndexes << i; } purgePending = false; - - // No locality info for the items; update the whole scene. - q->update(); } /*! @@ -3352,95 +3379,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) return; } - // If the item has focus, remove it (and any focusWidget reference). - item->clearFocus(); - - // Clear its background - item->update(); - - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromIndex(item); - - if (item == d->tabFocusFirst) { - QGraphicsWidget *widget = static_cast(item); - widget->d_func()->fixFocusChainBeforeReparenting(0, 0); - } - // Set the item's scene ptr to 0. - item->d_func()->scene = 0; - - // Remove from parent, or unregister from toplevels. - if (QGraphicsItem *parentItem = item->parentItem()) { - if (parentItem->scene()) { - Q_ASSERT_X(parentItem->scene() == this, "QGraphicsScene::removeItem", - "Parent item's scene is different from this item's scene"); - item->setParentItem(0); - } - } else { - d->unregisterTopLevelItem(item); - } - - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - } else { - d->unindexedItems.removeAll(item); - } - - if (item == d->focusItem) - d->focusItem = 0; - if (item == d->lastFocusItem) - d->lastFocusItem = 0; - if (item == d->activeWindow) { - // ### deactivate... - d->activeWindow = 0; - } - - // Disable selectionChanged() for individual items - ++d->selectionChanging; - int oldSelectedItemsSize = d->selectedItems.size(); - - // Update selected & hovered item bookkeeping - d->selectedItems.remove(item); - d->hoverItems.removeAll(item); - d->pendingUpdateItems.removeAll(item); - d->cachedItemsUnderMouse.removeAll(item); - d->unpolishedItems.removeAll(item); - d->resetDirtyItem(item); - - //We remove all references of item from the sceneEventFilter arrays - QMultiMap::iterator iterator = d->sceneEventFilters.begin(); - while (iterator != d->sceneEventFilters.end()) { - if (iterator.value() == item || iterator.key() == item) - iterator = d->sceneEventFilters.erase(iterator); - else - ++iterator; - } - - // Remove all children recursively - foreach (QGraphicsItem *child, item->children()) - removeItem(child); - - // Reset the mouse grabber and focus item data. - if (d->mouseGrabberItems.contains(item)) - d->ungrabMouse(item); - - // Reset the keyboard grabber - if (d->keyboardGrabberItems.contains(item)) - item->ungrabKeyboard(); - - // Reset the last mouse grabber item - if (item == d->lastMouseGrabberItem) - d->lastMouseGrabberItem = 0; - - // Reenable selectionChanged() for individual items - --d->selectionChanging; - - if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemsSize) - emit selectionChanged(); + d->removeItemHelper(item); // Deliver post-change notification item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); @@ -5272,7 +5211,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, - bool maybeDirtyClipPath, bool force, bool ignoreOpacity) + bool maybeDirtyClipPath, bool force, bool ignoreOpacity, + bool removingItemFromScene) { Q_ASSERT(item); if (updateAll) @@ -5280,7 +5220,8 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force, - /*ignoreDirtyBit=*/false, ignoreOpacity)) { + /*ignoreDirtyBit=*/removingItemFromScene, + /*ignoreOpacity=*/ignoreOpacity)) { return; } @@ -5293,6 +5234,24 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b processDirtyItemsEmitted = true; } + if (removingItemFromScene) { + // Note that this function can be called from the item's destructor, so + // do NOT call any virtual functions on it within this block. + if ((connectedSignals & changedSignalMask) || views.isEmpty()) { + // This block of code is kept for compatibility. Since 4.5, by default + // QGraphicsView does not connect the signal and we use the below + // method of delivering updates. + q_func()->update(); + return; + } + + for (int i = 0; i < views.size(); ++i) { + QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func(); + viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport)); + } + return; + } + item->d_ptr->dirty = 1; if (fullItemUpdate) item->d_ptr->fullUpdatePending = 1; diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 4c0f2ec..c4c9f9c 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -275,7 +275,6 @@ private: Q_DISABLE_COPY(QGraphicsScene) Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) - Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item)) Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 42c4d8c..11e9b64 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -131,7 +131,7 @@ public: bool regenerateIndex; bool purgePending; - void _q_removeItemLater(QGraphicsItem *item); + void removeItemHelper(QGraphicsItem *item); QSet removedItems; void purgeRemovedItems(); @@ -264,7 +264,8 @@ public: QRegion *exposedRegion, QWidget *widget, QList *topLevelItems = 0, qreal parentOpacity = qreal(1.0)); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, - bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false); + bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false, + bool removingItemFromScene = false); void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false); inline void resetDirtyItem(QGraphicsItem *item) -- cgit v0.12 From a15cce3256e57464720ea7fe7cf663c973f43c7b Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 9 Jun 2009 16:46:18 +0200 Subject: small changes in private headers --- src/gui/image/qpicture_p.h | 2 +- src/gui/painting/qtextureglyphcache_p.h | 2 +- src/gui/text/qfontengine.cpp | 6 ------ src/gui/text/qfontengine_p.h | 1 - src/gui/text/qfontengineglyphcache_p.h | 4 ++-- 5 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h index a3fd34f..3e8391f 100644 --- a/src/gui/image/qpicture_p.h +++ b/src/gui/image/qpicture_p.h @@ -69,7 +69,7 @@ class QPaintEngine; extern const char *qt_mfhdr_tag; -class Q_GUI_EXPORT QPicturePrivate +class QPicturePrivate { Q_DECLARE_PUBLIC(QPicture) friend class QPicturePaintEngine; diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index cb5be75..689c091 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -121,7 +121,7 @@ protected: }; -class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache +class QImageTextureGlyphCache : public QTextureGlyphCache { public: QImageTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 6e8adcf..79e341a 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -70,12 +70,6 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr } } - - -QFontEngineGlyphCache::~QFontEngineGlyphCache() -{ -} - // Harfbuzz helper functions static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft) diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 0f8d81c..3ef9d5f 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -93,7 +93,6 @@ struct QGlyphLayout; class Q_GUI_EXPORT QFontEngine : public QObject { - Q_OBJECT public: enum Type { Box, diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h index 8589cc6..ca67e3f 100644 --- a/src/gui/text/qfontengineglyphcache_p.h +++ b/src/gui/text/qfontengineglyphcache_p.h @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE -class Q_GUI_EXPORT QFontEngineGlyphCache +class QFontEngineGlyphCache { public: QFontEngineGlyphCache(const QTransform &matrix) : m_transform(matrix) { } @@ -83,7 +83,7 @@ public: Raster_Mono }; - virtual ~QFontEngineGlyphCache(); + virtual ~QFontEngineGlyphCache() { } QTransform m_transform; }; -- cgit v0.12 From df7d44d9e826e608d280270125b2d376c33c66ad Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 9 Jun 2009 17:02:32 +0200 Subject: removed foreach usage from animation API --- src/corelib/animation/qparallelanimationgroup.cpp | 33 +++++++++++++---------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index c148cb5d..6ec4679 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -135,13 +135,14 @@ void QParallelAnimationGroup::updateCurrentTime(int) // simulate completion of the loop int dura = duration(); if (dura > 0) { - foreach (QAbstractAnimation *animation, d->animations) { - animation->setCurrentTime(dura); // will stop + for (int i = 0; i < d->animations.size(); ++i) { + d->animations.at(i)->setCurrentTime(dura); // will stop } } } else if (d->currentLoop < d->lastLoop) { // simulate completion of the loop seeking backwards - foreach (QAbstractAnimation *animation, d->animations) { + for (int i = 0; i < d->animations.size(); ++i) { + QAbstractAnimation *animation = d->animations.at(i); animation->setCurrentTime(0); animation->stop(); } @@ -154,7 +155,8 @@ void QParallelAnimationGroup::updateCurrentTime(int) __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state()); #endif // finally move into the actual time of the current loop - foreach (QAbstractAnimation *animation, d->animations) { + for (int i = 0; i < d->animations.size(); ++i) { + QAbstractAnimation *animation = d->animations.at(i); const int dura = animation->totalDuration(); if (dura == -1 && d->isUncontrolledAnimationFinished(animation)) continue; @@ -200,17 +202,18 @@ void QParallelAnimationGroup::updateState(QAbstractAnimation::State oldState, switch (newState) { case Stopped: - foreach (QAbstractAnimation *animation, d->animations) - animation->stop(); + for (int i = 0; i < d->animations.size(); ++i) + d->animations.at(i)->stop(); d->disconnectUncontrolledAnimations(); break; case Paused: - foreach (QAbstractAnimation *animation, d->animations) - animation->pause(); + for (int i = 0; i < d->animations.size(); ++i) + d->animations.at(i)->pause(); break; case Running: d->connectUncontrolledAnimations(); - foreach (QAbstractAnimation *animation, d->animations) { + for (int i = 0; i < d->animations.size(); ++i) { + QAbstractAnimation *animation = d->animations.at(i); animation->stop(); animation->setDirection(d->direction); animation->start(); @@ -243,8 +246,8 @@ void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished() return; int maxDuration = 0; - foreach (QAbstractAnimation *a, animations) - maxDuration = qMax(maxDuration, a->totalDuration()); + for (int i = 0; i < animations.size(); ++i) + maxDuration = qMax(maxDuration, animations.at(i)->totalDuration()); if (currentTime >= maxDuration) q->stop(); @@ -267,7 +270,8 @@ void QParallelAnimationGroupPrivate::connectUncontrolledAnimations() { Q_Q(QParallelAnimationGroup); - foreach (QAbstractAnimation *animation, animations) { + for (int i = 0; i < animations.size(); ++i) { + QAbstractAnimation *animation = animations.at(i); if (animation->duration() == -1 || animation->loopCount() < 0) { uncontrolledFinishTime[animation] = -1; QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); @@ -288,8 +292,9 @@ void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction dire Q_D(QParallelAnimationGroup); //we need to update the direction of the current animation if (state() != Stopped) { - foreach(QAbstractAnimation *anim, d->animations) { - anim->setDirection(direction); + for (int i = 0; i < d->animations.size(); ++i) { + QAbstractAnimation *animation = d->animations.at(i); + animation->setDirection(direction); } } else { if (direction == Forward) { -- cgit v0.12 From 861bf225fedc452ab5b18c12e18e38c4172a5f1a Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 9 Jun 2009 17:04:33 +0200 Subject: Improves the documentation of QHeaderView::setResizeMode to specify that the section indicated by the parameter logicalIndex should exist Task-number: 255541 --- src/gui/itemviews/qheaderview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp index d28c08a..7ad825a 100644 --- a/src/gui/itemviews/qheaderview.cpp +++ b/src/gui/itemviews/qheaderview.cpp @@ -1153,7 +1153,8 @@ void QHeaderView::setResizeMode(ResizeMode mode) \overload Sets the constraints on how the section specified by \a logicalIndex in - the header can be resized to those described by the given \a mode. + the header can be resized to those described by the given \a mode. The logical + index should exist at the time this function is called. \note This setting will be ignored for the last section if the stretchLastSection property is set to true. This is the default for the horizontal headers provided -- cgit v0.12 From 2312b121131774a84d01854b3e47d3d2a035a6a1 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 4 Jun 2009 12:10:06 +0200 Subject: Implemented the NET_WM_SYNC protocol on X11. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Done with Thorbjørn Lindeijer Task-number: 220550 Reviewed-by: Thorbjørn Lindeijer Reviewed-by: mae --- src/gui/kernel/qapplication_x11.cpp | 87 ++++++++++++++++++++++++++++++++++++- src/gui/kernel/qt_x11_p.h | 6 +++ src/gui/kernel/qwidget_p.h | 8 ++++ src/gui/kernel/qwidget_x11.cpp | 28 +++++++++++- 4 files changed, 127 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 1473421..8ebea19 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -157,6 +157,8 @@ static const char * x11_atomnames = { "WM_TAKE_FOCUS\0" "_NET_WM_PING\0" "_NET_WM_CONTEXT_HELP\0" + "_NET_WM_SYNC_REQUEST\0" + "_NET_WM_SYNC_REQUEST_COUNTER\0" // ICCCM window state "WM_STATE\0" @@ -508,6 +510,7 @@ static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg) class QETWidget : public QWidget // event translator widget { public: + QWidgetPrivate* d_func() { return QWidget::d_func(); } bool translateMouseEvent(const XEvent *); void translatePaintEvent(const XEvent *); bool translateConfigEvent(const XEvent *); @@ -718,6 +721,44 @@ static int qt_xio_errhandler(Display *) } #endif +#ifndef QT_NO_XSYNC +struct qt_sync_request_event_data +{ + WId window; +}; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg) +{ + qt_sync_request_event_data *data = + reinterpret_cast(arg); + if (event->type == ClientMessage && + event->xany.window == data->window && + event->xclient.message_type == ATOM(WM_PROTOCOLS) && + (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) { + QWidget *w = QWidget::find(event->xany.window); + if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) { + const ulong timestamp = (const ulong) event->xclient.data.l[1]; + if (timestamp > X11->time) + X11->time = timestamp; + if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) { + tlw->syncRequestTimestamp = timestamp; + tlw->newCounterValueLo = event->xclient.data.l[2]; + tlw->newCounterValueHi = event->xclient.data.l[3]; + } + } + return true; + } + return false; +} + +#if defined(Q_C_CALLBACKS) +} +#endif +#endif // QT_NO_XSYNC static void qt_x11_create_intern_atoms() { @@ -2090,6 +2131,13 @@ void qt_init(QApplicationPrivate *priv, int, #endif // QT_RUNTIME_XCURSOR #endif // QT_NO_XCURSOR +#ifndef QT_NO_XSYNC + int xsync_evbase, xsync_errbase; + int major, minor; + if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase)) + XSyncInitialize(X11->display, &major, &minor); +#endif // QT_NO_XSYNC + #ifndef QT_NO_XINERAMA #ifdef QT_RUNTIME_XINERAMA X11->ptrXineramaQueryExtension = 0; @@ -3116,6 +3164,19 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only) XSendEvent(event->xclient.display, event->xclient.window, False, SubstructureNotifyMask|SubstructureRedirectMask, event); } +#ifndef QT_NO_XSYNC + } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) { + const ulong timestamp = (const ulong) event->xclient.data.l[1]; + if (timestamp > X11->time) + X11->time = timestamp; + if (QTLWExtra *tlw = w->d_func()->maybeTopData()) { + if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) { + tlw->syncRequestTimestamp = timestamp; + tlw->newCounterValueLo = event->xclient.data.l[2]; + tlw->newCounterValueHi = event->xclient.data.l[3]; + } + } +#endif } } else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) { widget->translateScrollDoneEvent(event); @@ -4144,7 +4205,9 @@ bool QETWidget::translateMouseEvent(const XEvent *event) || ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify) && qt_button_down == this) || (nextEvent.type == ClientMessage - && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) { + && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) || + (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) && + (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) { qApp->x11ProcessEvent(&nextEvent); continue; } else if (nextEvent.type != MotionNotify || @@ -5200,6 +5263,14 @@ bool QETWidget::translateConfigEvent(const XEvent *event) otherEvent.xconfigure.border_width; } } +#ifndef QT_NO_XSYNC + qt_sync_request_event_data sync_event; + sync_event.window = internalWinId(); + for (XEvent ev;;) { + if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event)) + break; + } +#endif // QT_NO_XSYNC } QRect cr (geometry()); @@ -5285,6 +5356,20 @@ bool QETWidget::translateConfigEvent(const XEvent *event) if (d->extra && d->extra->topextra) d->extra->topextra->inTopLevelResize = false; } +#ifndef QT_NO_XSYNC + if (QTLWExtra *tlwExtra = d->maybeTopData()) { + if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) { + XSyncValue value; + XSyncIntsToValue(&value, + tlwExtra->newCounterValueLo, + tlwExtra->newCounterValueHi); + + XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value); + tlwExtra->newCounterValueHi = 0; + tlwExtra->newCounterValueLo = 0; + } + } +#endif return true; } diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index b9ace9d..21bb550 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -154,6 +154,10 @@ extern "C" { # include #endif // QT_NO_XRENDER +#ifndef QT_NO_XSYNC +# include "X11/extensions/sync.h" +#endif + // #define QT_NO_XKB #ifndef QT_NO_XKB # include @@ -514,6 +518,8 @@ struct QX11Data WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_CONTEXT_HELP, + _NET_WM_SYNC_REQUEST, + _NET_WM_SYNC_REQUEST_COUNTER, // ICCCM window state WM_STATE, diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index bf4f091..ff194f7 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -131,6 +131,10 @@ struct QTLWExtra { uint embedded : 1; // *************************** Platform specific values (bit fields first) ********** +#ifndef QT_NO_XSYNC + int newCounterValueHi : 32; + uint newCounterValueLo : 32; +#endif #if defined(Q_WS_X11) // <----------------------------------------------------------- X11 uint spont_unmapped: 1; // window was spontaneously unmapped uint dnd : 1; // DND properties installed @@ -156,6 +160,10 @@ struct QTLWExtra { QWSManager *qwsManager; #endif #endif +#ifndef QT_NO_XSYNC + WId syncUpdateCounter; + ulong syncRequestTimestamp; +#endif }; struct QWExtra { diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 4e34045..8159f8e 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -754,11 +754,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO qBound(1, data.crect.width(), XCOORD_MAX), qBound(1, data.crect.height(), XCOORD_MAX)); XStoreName(dpy, id, appName.data()); - Atom protocols[4]; + Atom protocols[5]; int n = 0; protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol +#ifndef QT_NO_XSYNC + protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol +#endif // QT_NO_XSYNC if (flags & Qt::WindowContextHelpButtonHint) protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP); XSetWMProtocols(dpy, id, protocols, n); @@ -1877,6 +1880,23 @@ void QWidgetPrivate::show_sys() if (setUserTime) qt_net_update_user_time(q, userTime); +#ifndef QT_NO_XSYNC + if (!topData()->syncUpdateCounter) { + XSyncValue value; + XSyncIntToValue(&value, 0); + topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value); + + XChangeProperty(X11->display, q->internalWinId(), + ATOM(_NET_WM_SYNC_REQUEST_COUNTER), + XA_CARDINAL, + 32, PropModeReplace, + (uchar *) &topData()->syncUpdateCounter, 1); + + topData()->newCounterValueHi = 0; + topData()->newCounterValueLo = 0; + } +#endif + if (!topData()->embedded && (topData()->validWMState || topData()->waitingForMapNotify) && !q->isMinimized()) { @@ -2687,6 +2707,12 @@ void QWidgetPrivate::createTLSysExtra() extra->topextra->waitingForMapNotify = 0; extra->topextra->parentWinId = 0; extra->topextra->userTimeWindow = 0; +#ifndef QT_NO_XSYNC + extra->topextra->syncUpdateCounter = 0; + extra->topextra->syncRequestTimestamp = 0; + extra->topextra->newCounterValueHi = 0; + extra->topextra->newCounterValueLo = 0; +#endif } void QWidgetPrivate::deleteTLSysExtra() -- cgit v0.12 From 2dc47ad36f235ba053a329179be4ed87d0b4d484 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Tue, 9 Jun 2009 18:48:16 +0200 Subject: Add support for TIFF formats (Mono and indexed) Add support for reading and writing for Mono, MonoLSB and Indexed images in the tiff format. Previously, the images were always written in RGB32, dismissing the input format. Task-number: 254317 Reviewed-by: Samuel --- src/plugins/imageformats/tiff/qtiffhandler.cpp | 342 +++++++++++++++++++------ tests/auto/qimagewriter/tst_qimagewriter.cpp | 26 ++ 2 files changed, 285 insertions(+), 83 deletions(-) diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index 77dfeb3..791aeaa 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -131,58 +131,138 @@ bool QTiffHandler::read(QImage *image) if (!canRead()) return false; - TIFF *tiff = TIFFClientOpen("foo", - "r", - this, - qtiffReadProc, - qtiffWriteProc, - qtiffSeekProc, - qtiffCloseProc, - qtiffSizeProc, - qtiffMapProc, - qtiffUnmapProc); - - if (tiff) { - uint32 width = 0; - uint32 height = 0; - TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height); - if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32) - *image = QImage(width, height, QImage::Format_ARGB32); + TIFF *const tiff = TIFFClientOpen("foo", + "r", + this, + qtiffReadProc, + qtiffWriteProc, + qtiffSeekProc, + qtiffCloseProc, + qtiffSizeProc, + qtiffMapProc, + qtiffUnmapProc); + + if (!tiff) { + return false; + } + uint32 width; + uint32 height; + uint16 photometric; + if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width) + || !TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height) + || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) { + TIFFClose(tiff); + return false; + } + + if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) { + if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) + *image = QImage(width, height, QImage::Format_Mono); + QVector colortable(2); + if (photometric == PHOTOMETRIC_MINISBLACK) { + colortable[0] = 0xff000000; + colortable[1] = 0xffffffff; + } else { + colortable[0] = 0xffffffff; + colortable[1] = 0xff000000; + } + image->setColorTable(colortable); + if (!image->isNull()) { - if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), ORIENTATION_TOPLEFT, 0)) { - uint16 resUnit = RESUNIT_NONE; - float resX = 0; - float resY = 0; - TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit); - TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX); - TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY); - switch(resUnit) { - case RESUNIT_CENTIMETER: - image->setDotsPerMeterX(qRound(resX * 100)); - image->setDotsPerMeterY(qRound(resY * 100)); - break; - case RESUNIT_INCH: - image->setDotsPerMeterX(qRound(resX * (100 / 2.54))); - image->setDotsPerMeterY(qRound(resY * (100 / 2.54))); - break; - default: - // do nothing as defaults have already - // been set within the QImage class - break; + for (uint32 y=0; yscanLine(y), y, 0) < 0) { + TIFFClose(tiff); + return false; + } + } + } + } else { + uint16 bitPerSample; + if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { + TIFFClose(tiff); + return false; + } + if (photometric == PHOTOMETRIC_PALETTE && bitPerSample == 8) { + if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) + *image = QImage(width, height, QImage::Format_Indexed8); + if (!image->isNull()) { + // create the color table + const uint16 tableSize = 256; + uint16 *redTable = static_cast(qMalloc(tableSize * sizeof(uint16))); + uint16 *greenTable = static_cast(qMalloc(tableSize * sizeof(uint16))); + uint16 *blueTable = static_cast(qMalloc(tableSize * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } + if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { + TIFFClose(tiff); + return false; + } + + QVector qtColorTable(tableSize); + for (int i = 0; isetColorTable(qtColorTable); + for (uint32 y=0; yscanLine(y), y, 0) < 0) { + TIFFClose(tiff); + return false; + } + } + + // free redTable, greenTable and greenTable done by libtiff + } + } else { + if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32) + *image = QImage(width, height, QImage::Format_ARGB32); + if (!image->isNull()) { + if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), ORIENTATION_TOPLEFT, 0)) { + for (uint32 y=0; yscanLine(y), width); + } else { + TIFFClose(tiff); + return false; } - for (uint32 y=0; yscanLine(y), width); - } else { - *image = QImage(); } } - TIFFClose(tiff); } - if (image->isNull()) + if (image->isNull()) { + TIFFClose(tiff); return false; + } + + float resX = 0; + float resY = 0; + uint16 resUnit = RESUNIT_NONE; + if (TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit) + && TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX) + && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) { + + switch(resUnit) { + case RESUNIT_CENTIMETER: + image->setDotsPerMeterX(qRound(resX * 100)); + image->setDotsPerMeterY(qRound(resY * 100)); + break; + case RESUNIT_INCH: + image->setDotsPerMeterX(qRound(resX * (100 / 2.54))); + image->setDotsPerMeterY(qRound(resY * (100 / 2.54))); + break; + default: + // do nothing as defaults have already + // been set within the QImage class + break; + } + } + TIFFClose(tiff); return true; } @@ -191,48 +271,145 @@ bool QTiffHandler::write(const QImage &image) if (!device()->isWritable()) return false; - TIFF *tiff = TIFFClientOpen("foo", - "w", - this, - qtiffReadProc, - qtiffWriteProc, - qtiffSeekProc, - qtiffCloseProc, - qtiffSizeProc, - qtiffMapProc, - qtiffUnmapProc); - - if (tiff) { - int width = image.width(); - int height = image.height(); - int depth = 32; - - if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width) - || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height) - || !TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) - || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW) - || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, depth/8) - || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) - || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFF *const tiff = TIFFClientOpen("foo", + "w", + this, + qtiffReadProc, + qtiffWriteProc, + qtiffSeekProc, + qtiffCloseProc, + qtiffSizeProc, + qtiffMapProc, + qtiffUnmapProc); + if (!tiff) + return false; + + const int width = image.width(); + const int height = image.height(); + + if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width) + || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height) + || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) { + TIFFClose(tiff); + return false; + } + + // set the resolution + bool resolutionSet = false; + const int dotPerMeterX = image.dotsPerMeterX(); + const int dotPerMeterY = image.dotsPerMeterY(); + if ((dotPerMeterX % 100) == 0 + && (dotPerMeterY % 100) == 0) { + resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER) + && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0) + && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0); + } else { + resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH) + && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast(image.logicalDpiX())) + && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast(image.logicalDpiY())); + } + if (!resolutionSet) { + TIFFClose(tiff); + return false; + } + + // configure image depth + const QImage::Format format = image.format(); + if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) { + uint16 photometric = PHOTOMETRIC_MINISBLACK; + if (image.colorTable().at(0) == 0xffffffff) + photometric = PHOTOMETRIC_MINISWHITE; + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)) { TIFFClose(tiff); return false; } - // set the resolution - bool resolutionSet = false; - const int dotPerMeterX = image.dotsPerMeterX(); - const int dotPerMeterY = image.dotsPerMeterY(); - if ((dotPerMeterX % 100) == 0 - && (dotPerMeterY % 100) == 0) { - resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER) - && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0) - && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0); - } else { - resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH) - && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast(image.logicalDpiX())) - && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast(image.logicalDpiY())); + // try to do the conversion in chunks no greater than 16 MB + int chunks = (width * height / (1024 * 1024 * 16)) + 1; + int chunkHeight = qMax(height / chunks, 1); + + int y = 0; + while (y < height) { + QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_Mono); + + int chunkStart = y; + int chunkEnd = y + chunk.height(); + while (y < chunkEnd) { + if (TIFFWriteScanline(tiff, reinterpret_cast(chunk.scanLine(y - chunkStart)), y) != 1) { + TIFFClose(tiff); + return false; + } + ++y; + } + } + TIFFClose(tiff); + } else if (format == QImage::Format_Indexed8) { + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFFClose(tiff); + return false; + } + //// write the color table + // allocate the color tables + uint16 *redTable = static_cast(qMalloc(256 * sizeof(uint16))); + uint16 *greenTable = static_cast(qMalloc(256 * sizeof(uint16))); + uint16 *blueTable = static_cast(qMalloc(256 * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } + + // set the color table + const QVector colorTable = image.colorTable(); + + const int tableSize = colorTable.size(); + Q_ASSERT(tableSize <= 256); + for (int i = 0; i(chunk.scanLine(y - chunkStart)), y) != 1) { + TIFFClose(tiff); + return false; + } + ++y; + } } - if (!resolutionSet) { + TIFFClose(tiff); + + } else { + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW) + || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { TIFFClose(tiff); return false; } @@ -260,9 +437,8 @@ bool QTiffHandler::write(const QImage &image) } } TIFFClose(tiff); - } else { - return false; } + return true; } diff --git a/tests/auto/qimagewriter/tst_qimagewriter.cpp b/tests/auto/qimagewriter/tst_qimagewriter.cpp index 349afa5..3ceb2c2 100644 --- a/tests/auto/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/qimagewriter/tst_qimagewriter.cpp @@ -59,6 +59,7 @@ Q_DECLARE_METATYPE(QStringMap) Q_DECLARE_METATYPE(QIntList) Q_DECLARE_METATYPE(QImageWriter::ImageWriterError) Q_DECLARE_METATYPE(QIODevice *) +Q_DECLARE_METATYPE(QImage::Format) //TESTED_FILES= @@ -82,6 +83,9 @@ private slots: void writeImage2(); void supportedFormats(); + void readWriteNonDestructive_data(); + void readWriteNonDestructive(); + #if defined QTEST_HAVE_TIFF void largeTiff(); #endif @@ -376,6 +380,28 @@ void tst_QImageWriter::supportedFormats() QCOMPARE(formatSet.size(), formats.size()); } +void tst_QImageWriter::readWriteNonDestructive_data() +{ + QTest::addColumn("format"); + QTest::addColumn("expectedFormat"); + QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono; + QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8; + QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32; +} + +void tst_QImageWriter::readWriteNonDestructive() +{ + QFETCH(QImage::Format, format); + QFETCH(QImage::Format, expectedFormat); + QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format); + QVERIFY(image.save(prefix + "gen-readWriteNonDestructive.tiff")); + + QImage image2 = QImage(prefix + "gen-readWriteNonDestructive.tiff"); + QImage::Format readFormat = image2.format(); + QCOMPARE(readFormat, expectedFormat); + QCOMPARE(image, image2); +} + void tst_QImageWriter::setDescription_data() { QTest::addColumn("fileName"); -- cgit v0.12 From 2af18f51f216d5c624ce28b3fa966a17050d882b Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 9 Jun 2009 17:45:04 +0200 Subject: Fix sorting bug when using BSP tree index + add autotest. We use stable sorting to keep insertion order. This works fine as long as we sort a complete list of siblings in one go, and this list already has items in insertion order. But if we shuffle such a list, the only way to get proper sort order again (with insertion order intact), is if each item has a sibling index. We used to have this, but we don't have it anymore (as it's not needed for NoIndex mode). So until we separate the BSP index into a separate class and add this index there, we add this workaround which uses the toplevelitems list to ensure the items have the correct order. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 8 +--- src/gui/graphicsview/qgraphicsscene.cpp | 46 +++++++++++++++------ tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 56 ++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index db16213..f50d210 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -6190,10 +6190,8 @@ void QGraphicsItem::addToIndex() // ### add to child index only if applicable return; } - if (d_ptr->scene) { + if (d_ptr->scene) d_ptr->scene->d_func()->addToIndex(this); - d_ptr->scene->d_func()->markDirty(this); - } } /*! @@ -6209,10 +6207,8 @@ void QGraphicsItem::removeFromIndex() // ### remove from child index only if applicable return; } - if (d_ptr->scene) { - d_ptr->scene->d_func()->markDirty(this); + if (d_ptr->scene) d_ptr->scene->d_func()->removeFromIndex(this); - } } /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b63efd6..e6c3503 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5112,18 +5112,42 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } else if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) { children = &this->topLevelItems; } else { - tmp = estimateItemsInRect(viewTransform.inverted().mapRect(exposedRegion->boundingRect())); + QRectF sceneRect = viewTransform.inverted().mapRect(QRectF(exposedRegion->boundingRect().adjusted(-1, -1, 1, 1))); + if (!largestUntransformableItem.isEmpty()) { + // ### Nuke this when we move the indexing code into a separate + // class. All the largestUntransformableItem code should then go + // away, and the estimate function should return untransformable + // items as well. + QRectF untr = largestUntransformableItem; + QRectF ltri = viewTransform.inverted().mapRect(untr); + ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height()); + sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height()); + } + tmp = estimateItemsInRect(sceneRect); QList tli; - for (int i = 0; i < tmp.size(); ++i) { - QGraphicsItem *it = tmp.at(i)->topLevelItem(); - if (!it->d_ptr->itemDiscovered) { - tli << it; - it->d_ptr->itemDiscovered = 1; + for (int i = 0; i < tmp.size(); ++i) + tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1; + + // Sort if the toplevel list is unsorted. + if (needSortTopLevelItems) { + needSortTopLevelItems = false; + qStableSort(this->topLevelItems.begin(), + this->topLevelItems.end(), qt_notclosestLeaf); + } + + for (int i = 0; i < this->topLevelItems.size(); ++i) { + // ### Investigate smarter ways. Looping through all top level + // items is not optimal. If the BSP tree is to have maximum + // effect, it should be possible to sort the subset of items + // quickly. We must use this approach for now, as it's the only + // current way to keep the stable sorting order (insertion order). + QGraphicsItem *item = this->topLevelItems.at(i); + if (item->d_ptr->itemDiscovered) { + item->d_ptr->itemDiscovered = 0; + tli << item; } } - for (int i = 0; i < tli.size(); ++i) - tli.at(i)->d_ptr->itemDiscovered = 0; tmp = tli; children = &tmp; @@ -5147,9 +5171,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (item && item->d_ptr->needSortChildren) { item->d_ptr->needSortChildren = 0; qStableSort(children->begin(), children->end(), qt_notclosestLeaf); - } else if (!item && children == &tmp) { - qStableSort(children->begin(), children->end(), qt_notclosestLeaf); - } else if (!item && needSortTopLevelItems) { + } else if (!item && needSortTopLevelItems && children != &tmp) { needSortTopLevelItems = false; qStableSort(children->begin(), children->end(), qt_notclosestLeaf); } @@ -5220,7 +5242,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force, - /*ignoreDirtyBit=*/removingItemFromScene, + /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren, /*ignoreOpacity=*/ignoreOpacity)) { return; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index af34fe5..481dc6b 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -226,6 +226,8 @@ private slots: void itemUsesExtendedStyleOption(); void itemSendsGeometryChanges(); void moveItem(); + void sorting_data(); + void sorting(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -6926,5 +6928,59 @@ void tst_QGraphicsItem::moveItem() QCOMPARE(view.paintedRegion, expectedParentRegion); } +void tst_QGraphicsItem::sorting_data() +{ + QTest::addColumn("index"); + + QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex); + QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex); +} + +void tst_QGraphicsItem::sorting() +{ + _paintedItems.clear(); + + QGraphicsScene scene; + QGraphicsItem *grid[100][100]; + for (int x = 0; x < 100; ++x) { + for (int y = 0; y < 100; ++y) { + PainterItem *item = new PainterItem; + item->setPos(x * 25, y * 25); + item->setData(0, QString("%1x%2").arg(x).arg(y)); + grid[x][y] = item; + scene.addItem(item); + } + } + + PainterItem *item1 = new PainterItem; + PainterItem *item2 = new PainterItem; + item1->setData(0, "item1"); + item2->setData(0, "item2"); + scene.addItem(item1); + scene.addItem(item2); + + QGraphicsView view(&scene); + view.setResizeAnchor(QGraphicsView::NoAnchor); + view.setTransformationAnchor(QGraphicsView::NoAnchor); + view.resize(100, 100); + view.setFrameStyle(0); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(100); + + _paintedItems.clear(); + + view.viewport()->repaint(); + + QCOMPARE(_paintedItems, QList() + << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3] + << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3] + << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3] + << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3] + << item1 << item2); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 5b24c5793607c809b1bac82c7cc3696001ee9217 Mon Sep 17 00:00:00 2001 From: Prasanth Ullattil Date: Tue, 9 Jun 2009 18:49:40 +0200 Subject: Opening links with cyrillic file names does not work in QLabel. QDestopServices was converting the file names to percentage encoding before calling ShellExecute. This will not work with URLs without a scheme. These are now being treated similar to a file. Task-number: 254501 Reviewed-by: Jens Bache-Wiig --- src/gui/util/qdesktopservices_win.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp index 9f8efb4..a8aa11c 100644 --- a/src/gui/util/qdesktopservices_win.cpp +++ b/src/gui/util/qdesktopservices_win.cpp @@ -165,6 +165,9 @@ static bool launchWebBrowser(const QUrl &url) if (!url.isValid()) return false; + if (url.scheme().isEmpty()) + return openDocument(url); + quintptr returnValue; returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *) QString::fromUtf8(url.toEncoded().constData()).utf16(), 0, 0, SW_SHOWNORMAL); -- cgit v0.12 From b14a89473a51bee7cc2f313b88a8bc1e87a454d8 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 14:16:19 +1000 Subject: Improve bindings startup performance --- src/declarative/qml/qml.pri | 3 +- src/declarative/qml/qmlbasicscript.cpp | 166 ++++++++++++++++++++++++++++----- src/declarative/qml/qmlbasicscript_p.h | 11 ++- src/declarative/qml/qmlcompiler.cpp | 55 ++++++----- src/declarative/qml/qmlcompiler_p.h | 44 ++++++--- src/declarative/qml/qmlengine.cpp | 28 +----- src/declarative/qml/qmlengine_p.h | 12 +-- src/declarative/qml/qmlexpression.h | 2 +- src/declarative/qml/qmlvme.cpp | 4 +- src/declarative/qml/qpodvector_p.h | 124 ++++++++++++++++++++++++ 10 files changed, 356 insertions(+), 93 deletions(-) create mode 100644 src/declarative/qml/qpodvector_p.h diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index c61200e..efe4d3f 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -63,7 +63,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmldeclarativedata_p.h \ qml/qmlerror.h \ qml/qmlscriptparser_p.h \ - qml/qmlbasicscript_p.h + qml/qmlbasicscript_p.h \ + qml/qpodvector_p.h # for qtscript debugger QT += scripttools diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 7bd898c..d8e65bf 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -22,11 +22,19 @@ QT_BEGIN_NAMESPACE +using namespace JavaScript; + struct ScriptInstruction { enum { Load, // fetch Fetch, // fetch + LoadIdObject, // fetch + FetchConstant, // constant + FetchD0Constant, // constant + FetchD1Constant, // constant + + Add, // NA Subtract, // NA Multiply, // NA @@ -47,6 +55,11 @@ struct ScriptInstruction { struct { bool value; } boolean; + struct { + short idx; + short notify; + int type; + } constant; }; }; @@ -249,9 +262,14 @@ struct QmlBasicScriptCompiler { QmlBasicScriptCompiler() : script(0), stateSize(0) {} + QmlBasicScript *script; int stateSize; + QmlParser::Object *context; + QmlParser::Object *component; + QHash > ids; + bool compile(JavaScript::AST::Node *); bool compileExpression(JavaScript::AST::Node *); @@ -259,7 +277,7 @@ struct QmlBasicScriptCompiler bool tryConstant(JavaScript::AST::Node *); bool parseConstant(JavaScript::AST::Node *); bool tryName(JavaScript::AST::Node *); - bool parseName(JavaScript::AST::Node *); + bool parseName(JavaScript::AST::Node *, QmlParser::Object ** = 0); bool tryBinaryExpression(JavaScript::AST::Node *); bool compileBinaryExpression(JavaScript::AST::Node *); @@ -437,19 +455,18 @@ bool QmlBasicScript::isValid() const return d != 0; } -/*! - Compile \a v and return true if the compilation is successful, otherwise - returns false. - */ -bool QmlBasicScript::compile(const QmlParser::Variant &v) +bool QmlBasicScript::compile(const Expression &expression) { - if (!v.asAST()) return false; + if (!expression.expression.asAST()) return false; - QByteArray expr = v.asScript().toLatin1(); + QByteArray expr = expression.expression.asScript().toLatin1(); const char *src = expr.constData(); QmlBasicScriptCompiler bsc; bsc.script = this; + bsc.context = expression.context; + bsc.component = expression.component; + bsc.ids = expression.ids; if (d) { if (flags & QmlBasicScriptPrivate::OwnData) @@ -458,7 +475,7 @@ bool QmlBasicScript::compile(const QmlParser::Variant &v) flags = 0; } - if (bsc.compile(v.asAST())) { + if (bsc.compile(expression.expression.asAST())) { int len = ::strlen(src); flags = QmlBasicScriptPrivate::OwnData; int size = sizeof(QmlBasicScriptPrivate) + @@ -483,7 +500,6 @@ bool QmlBasicScriptCompiler::compile(JavaScript::AST::Node *node) return compileExpression(node); } -using namespace JavaScript; bool QmlBasicScriptCompiler::tryConstant(JavaScript::AST::Node *node) { if (node->kind == AST::Node::Kind_TrueLiteral || @@ -524,10 +540,11 @@ bool QmlBasicScriptCompiler::tryName(JavaScript::AST::Node *node) node->kind == AST::Node::Kind_FieldMemberExpression; } -bool QmlBasicScriptCompiler::parseName(AST::Node *node) +bool QmlBasicScriptCompiler::parseName(AST::Node *node, + QmlParser::Object **type) { bool load = false; - + QmlParser::Object *loadedType = 0; QString name; if (node->kind == AST::Node::Kind_IdentifierExpression) { name = static_cast(node)->name->asString(); @@ -535,7 +552,7 @@ bool QmlBasicScriptCompiler::parseName(AST::Node *node) } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { AST::FieldMemberExpression *expr = static_cast(node); - if (!parseName(expr->base)) + if (!parseName(expr->base, &loadedType)) return false; name = expr->name->asString(); @@ -543,18 +560,72 @@ bool QmlBasicScriptCompiler::parseName(AST::Node *node) return false; } - int nref = data.count(); - data.append(name.toUtf8()); - data.append('\0'); ScriptInstruction instr; - if (load) - instr.type = ScriptInstruction::Load; - else - instr.type = ScriptInstruction::Fetch; - instr.fetch.idx = nref; - bytecode.append(instr); - ++stateSize; + if (load) { + if (ids.contains(name)) { + instr.type = ScriptInstruction::LoadIdObject; + instr.fetch.idx = ids.value(name).second; + + if (type) + *type = ids.value(name).first; + + } else { + int d0Idx = context->metaObject()->indexOfProperty(name.toUtf8().constData()); + int d1Idx = -1; + if (d0Idx == -1) + d1Idx = component->metaObject()->indexOfProperty(name.toUtf8().constData()); + if (d0Idx != -1) { + + instr.type = ScriptInstruction::FetchD0Constant; + instr.constant.idx = d0Idx; + QMetaProperty prop = context->metaObject()->property(d0Idx); + instr.constant.notify = prop.notifySignalIndex(); + instr.constant.type = prop.userType(); + + } else if (d1Idx != -1) { + + instr.type = ScriptInstruction::FetchD1Constant; + instr.constant.idx = d1Idx; + QMetaProperty prop = component->metaObject()->property(d1Idx); + instr.constant.notify = prop.notifySignalIndex(); + instr.constant.type = prop.userType(); + + } else { + + int nref = data.count(); + data.append(name.toUtf8()); + data.append('\0'); + instr.type = ScriptInstruction::Load; + instr.fetch.idx = nref; + ++stateSize; + + } + } + + } else { + + int idx = -1; + if (loadedType) + idx = loadedType->metaObject()->indexOfProperty(name.toUtf8().constData()); + if (idx != -1) { + instr.type = ScriptInstruction::FetchConstant; + instr.constant.idx = idx; + QMetaProperty prop = loadedType->metaObject()->property(idx); + instr.constant.notify = prop.notifySignalIndex(); + instr.constant.type = prop.userType(); + } else { + int nref = data.count(); + data.append(name.toUtf8()); + data.append('\0'); + instr.type = ScriptInstruction::Fetch; + instr.fetch.idx = nref; + ++stateSize; + } + + } + + bytecode.append(instr); return true; } @@ -679,12 +750,16 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c { if (!isValid()) return QVariant(); + + QmlContextPrivate *contextPrivate = context->d_func(); + QmlEnginePrivate *enginePrivate = context->engine()->d_func(); QmlBasicScriptNodeCache *dataCache = reinterpret_cast(voidCache); int dataCacheItem; - QStack stack; + QStack stack; + bool resetting = false; bool hasReset = false; @@ -702,6 +777,49 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c const ScriptInstruction &instr = d->instructions()[idx]; switch(instr.type) { + case ScriptInstruction::LoadIdObject: + { + stack.push(contextPrivate->propertyValues.at(instr.fetch.idx)); + enginePrivate->capturedProperties << + QmlEnginePrivate::CapturedProperty(context, contextPrivate->notifyIndex + instr.fetch.idx); + state = Reset; + } + break; + + case ScriptInstruction::FetchD0Constant: + { + QObject *obj = contextPrivate->defaultObjects.at(0); + + stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); + enginePrivate->capturedProperties << + QmlEnginePrivate::CapturedProperty(obj, instr.constant.notify); + state = Reset; + } + break; + + case ScriptInstruction::FetchD1Constant: + { + QObject *obj = contextPrivate->defaultObjects.at(1); + + stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); + enginePrivate->capturedProperties << + QmlEnginePrivate::CapturedProperty(obj, instr.constant.notify); + state = Reset; + } + break; + + case ScriptInstruction::FetchConstant: + { + QVariant o = stack.pop(); + QObject *obj = qvariant_cast(o); + + stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); + enginePrivate->capturedProperties << + QmlEnginePrivate::CapturedProperty(obj, instr.constant.notify); + state = Reset; + } + break; + case ScriptInstruction::Load: // either an object or a property case ScriptInstruction::Fetch: // can only be a property { diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index 1117e11..43c0d36 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -38,7 +38,16 @@ public: QByteArray expression() const; - bool compile(const QmlParser::Variant &); + struct Expression + { + QmlParser::Object *component; + QmlParser::Object *context; + QmlParser::Property *property; + QmlParser::Variant expression; + QHash > ids; + }; + + bool compile(const Expression &); bool isValid() const; void clear(); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index b28d7dd..fe3da57 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -533,6 +533,8 @@ bool QmlCompiler::compile(QmlEngine *engine, void QmlCompiler::compileTree(Object *tree) { + compileState.root = tree; + QmlInstruction init; init.type = QmlInstruction::Init; init.line = 0; @@ -557,7 +559,7 @@ void QmlCompiler::compileTree(Object *tree) finalizeComponent(0); } -bool QmlCompiler::compileObject(Object *obj, int ctxt) +bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt) { Q_ASSERT (obj->type != -1); obj->metatype = output->types.at(obj->type).metaObject(); @@ -567,7 +569,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) return true; } - ctxt = 0; + BindingContext objCtxt(obj); int createInstrIdx = output->bytecode.count(); // Create the object @@ -617,7 +619,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) if (isCustomParser) { // Custom parser types don't support signal properties if (testProperty(prop, obj)) { - COMPILE_CHECK(compileProperty(prop, obj, ctxt)); + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } else { customProps << QmlCustomParserNodePrivate::fromProperty(prop); } @@ -625,7 +627,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) if (isSignalPropertyName(prop->name)) { COMPILE_CHECK(compileSignal(prop,obj)); } else { - COMPILE_CHECK(compileProperty(prop, obj, ctxt)); + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } } @@ -637,12 +639,12 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) if (isCustomParser) { if (testProperty(prop, obj)) { - COMPILE_CHECK(compileProperty(prop, obj, ctxt)); + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } else { customProps << QmlCustomParserNodePrivate::fromProperty(prop); } } else { - COMPILE_CHECK(compileProperty(prop, obj, ctxt)); + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } } @@ -673,7 +675,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) return true; } -bool QmlCompiler::compileComponent(Object *obj, int ctxt) +bool QmlCompiler::compileComponent(Object *obj, const BindingContext &ctxt) { Property *idProp = 0; if (obj->properties.count() > 1 || @@ -709,6 +711,7 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt) reference.id = val; reference.object = obj; reference.instructionIdx = output->bytecode.count(); + reference.idx = compileState.ids.count(); compileState.ids.insert(val, reference); int pref = output->indexForString(val); @@ -724,7 +727,7 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt) return true; } -bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt) +bool QmlCompiler::compileComponentFromRoot(Object *obj, const BindingContext &ctxt) { output->bytecode.push_back(QmlInstruction()); QmlInstruction &create = output->bytecode.last(); @@ -743,6 +746,7 @@ bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt) ComponentCompileState oldComponentCompileState = compileState; compileState = ComponentCompileState(); + compileState.root = obj; if (obj) COMPILE_CHECK(compileObject(obj, ctxt)); @@ -753,7 +757,7 @@ bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt) } -bool QmlCompiler::compileFetchedObject(Object *obj, int ctxt) +bool QmlCompiler::compileFetchedObject(Object *obj, const BindingContext &ctxt) { Q_ASSERT(obj->metatype); @@ -871,7 +875,7 @@ bool QmlCompiler::testProperty(QmlParser::Property *prop, return false; } -bool QmlCompiler::compileProperty(Property *prop, Object *obj, int ctxt) +bool QmlCompiler::compileProperty(Property *prop, Object *obj, const BindingContext &ctxt) { if (prop->values.isEmpty() && !prop->value) COMPILE_EXCEPTION2(prop, "Empty property assignment"); @@ -992,6 +996,7 @@ bool QmlCompiler::compileIdProperty(QmlParser::Property *prop, reference.id = val; reference.object = obj; reference.instructionIdx = output->bytecode.count(); + reference.idx = compileState.ids.count(); compileState.ids.insert(val, reference); QmlInstruction id; @@ -1012,7 +1017,7 @@ bool QmlCompiler::compileIdProperty(QmlParser::Property *prop, // } // GridView is an attached property object. bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop, - int ctxt) + const BindingContext &ctxt) { Q_ASSERT(prop->value); int id = QmlMetaType::attachedPropertiesFuncId(prop->name); @@ -1024,7 +1029,7 @@ bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop, fetch.fetchAttached.id = id; output->bytecode << fetch; - COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1)); + COMPILE_CHECK(compileFetchedObject(prop->value, ctxt.incr())); QmlInstruction pop; pop.type = QmlInstruction::PopFetchedObject; @@ -1040,7 +1045,7 @@ bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop, // } // font is a nested property. size is not. bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop, - int ctxt) + const BindingContext &ctxt) { Q_ASSERT(prop->type != 0); Q_ASSERT(prop->index != -1); @@ -1057,7 +1062,7 @@ bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop, fetch.line = prop->location.start.line; output->bytecode << fetch; - COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1)); + COMPILE_CHECK(compileFetchedObject(prop->value, ctxt.incr())); QmlInstruction pop; pop.type = QmlInstruction::PopFetchedObject; @@ -1074,7 +1079,7 @@ bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop, // QmlList * types can accept a list of objects bool QmlCompiler::compileListProperty(QmlParser::Property *prop, QmlParser::Object *obj, - int ctxt) + const BindingContext &ctxt) { Q_ASSERT(QmlMetaType::isList(prop->type) || QmlMetaType::isQmlList(prop->type)); @@ -1166,7 +1171,7 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, // We allow assignming multiple values to single value properties bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop, QmlParser::Object *obj, - int ctxt) + const BindingContext &ctxt) { for (int ii = 0; ii < prop->values.count(); ++ii) { Value *v = prop->values.at(ii); @@ -1187,7 +1192,7 @@ bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop, // Compile assigning a single object instance to a regular property bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop, QmlParser::Value *v, - int ctxt) + const BindingContext &ctxt) { Q_ASSERT(prop->index != -1); Q_ASSERT(v->object->type != -1); @@ -1296,7 +1301,7 @@ bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop, bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, QmlParser::Object *obj, QmlParser::Value *v, - int ctxt) + const BindingContext &ctxt) { Q_ASSERT(prop->index != -1); @@ -1409,7 +1414,7 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj) bool QmlCompiler::compileBinding(QmlParser::Value *value, QmlParser::Property *prop, - int ctxt) + const BindingContext &ctxt) { Q_ASSERT(prop->index); Q_ASSERT(prop->parent); @@ -1491,7 +1496,15 @@ void QmlCompiler::finalizeComponent(int patch) void QmlCompiler::finalizeBinding(const BindingReference &binding) { QmlBasicScript bs; - bs.compile(binding.expression); + QmlBasicScript::Expression expr; + expr.component = compileState.root; + expr.context = binding.bindingContext.object; + expr.property = binding.property; + expr.expression = binding.expression; + foreach (const IdReference &id, compileState.ids) + expr.ids.insert(id.id, qMakePair(id.object, id.idx)); + + bs.compile(expr); QmlInstruction &instr = output->bytecode[binding.instructionIdx]; instr.line = binding.value->location.start.line; @@ -1553,7 +1566,7 @@ void QmlCompiler::finalizeBinding(const BindingReference &binding) bref = output->indexForString(binding.expression.asScript()); } - instr.assignBinding.context = binding.bindingContext; + instr.assignBinding.context = binding.bindingContext.stack; if (bs.isValid()) instr.type = QmlInstruction::StoreCompiledBinding; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 6b6e1e2..6b6d8cb 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -125,41 +125,55 @@ public: private: void reset(QmlCompiledComponent *, bool); + struct BindingContext { + BindingContext() + : stack(0), object(0) {} + BindingContext(QmlParser::Object *o) + : stack(0), object(o) {} + BindingContext incr() const { + BindingContext rv(object); + rv.stack = stack + 1; + return rv; + } + int stack; + QmlParser::Object *object; + }; + void compileTree(QmlParser::Object *tree); - bool compileObject(QmlParser::Object *obj, int); - bool compileComponent(QmlParser::Object *obj, int); - bool compileComponentFromRoot(QmlParser::Object *obj, int); - bool compileFetchedObject(QmlParser::Object *obj, int); + bool compileObject(QmlParser::Object *obj, const BindingContext &); + bool compileComponent(QmlParser::Object *obj, const BindingContext &); + bool compileComponentFromRoot(QmlParser::Object *obj, const BindingContext &); + bool compileFetchedObject(QmlParser::Object *obj, const BindingContext &); bool compileSignal(QmlParser::Property *prop, QmlParser::Object *obj); bool testProperty(QmlParser::Property *prop, QmlParser::Object *obj); int signalByName(const QMetaObject *, const QByteArray &name); - bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, int); + bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &); bool compileIdProperty(QmlParser::Property *prop, QmlParser::Object *obj); bool compileAttachedProperty(QmlParser::Property *prop, - int ctxt); + const BindingContext &ctxt); bool compileNestedProperty(QmlParser::Property *prop, - int ctxt); + const BindingContext &ctxt); bool compileListProperty(QmlParser::Property *prop, QmlParser::Object *obj, - int ctxt); + const BindingContext &ctxt); bool compilePropertyAssignment(QmlParser::Property *prop, QmlParser::Object *obj, - int ctxt); + const BindingContext &ctxt); bool compilePropertyObjectAssignment(QmlParser::Property *prop, QmlParser::Value *value, - int ctxt); + const BindingContext &ctxt); bool compilePropertyLiteralAssignment(QmlParser::Property *prop, QmlParser::Object *obj, QmlParser::Value *value, - int ctxt); + const BindingContext &ctxt); bool compileStoreInstruction(QmlInstruction &instr, const QMetaProperty &prop, QmlParser::Value *value); bool compileDynamicMeta(QmlParser::Object *obj); bool compileBinding(QmlParser::Value *, QmlParser::Property *prop, - int ctxt); + const BindingContext &ctxt); void finalizeComponent(int patch); struct BindingReference; @@ -169,6 +183,7 @@ private: QString id; QmlParser::Object *object; int instructionIdx; + int idx; }; struct BindingReference { @@ -176,17 +191,18 @@ private: QmlParser::Property *property; QmlParser::Value *value; int instructionIdx; - int bindingContext; + BindingContext bindingContext; }; struct ComponentCompileState { - ComponentCompileState() : parserStatusCount(0), savedObjects(0), pushedProperties(0) {} + ComponentCompileState() : parserStatusCount(0), savedObjects(0), pushedProperties(0), root(0) {} QHash ids; int parserStatusCount; int savedObjects; int pushedProperties; QList bindings; + QmlParser::Object *root; }; ComponentCompileState compileState; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 73b9245..66781ce 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -219,30 +219,11 @@ QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c) return old; } -QmlEnginePrivate::CapturedProperty::CapturedProperty(QObject *obj, int n) -: object(obj), notifyIndex(n) -{ -} - QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p) -: object(p.object()), name(p.name()), notifyIndex(p.property().notifySignalIndex()) -{ -} - -QmlEnginePrivate::CapturedProperty::CapturedProperty(const CapturedProperty &o) -: object(o.object), name(o.name), notifyIndex(o.notifyIndex) +: object(p.object()), notifyIndex(p.property().notifySignalIndex()) { } -QmlEnginePrivate::CapturedProperty & -QmlEnginePrivate::CapturedProperty::operator=(const CapturedProperty &o) -{ - object = o.object; - name = o.name; - notifyIndex = o.notifyIndex; - return *this; -} - //////////////////////////////////////////////////////////////////// typedef QHash, bool> FunctionCache; Q_GLOBAL_STATIC(FunctionCache, functionCache); @@ -1224,8 +1205,9 @@ QVariant QmlExpression::value() QMetaObject::connect(prop.object, prop.notifyIndex, d->proxy, changedIndex); } else { - QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object->metaObject()->className()) + QLatin1String("].") + prop.name; - log.addWarning(warn); + // ### FIXME + //QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object->metaObject()->className()) + QLatin1String("].") + prop.name; + //log.addWarning(warn); } } d->addLog(log); @@ -1305,7 +1287,7 @@ void QmlExpression::setTrackChange(bool trackChange) Set the location of this expression to \a line of \a fileName. This information is used by the script engine. */ -void QmlExpression::setSourceLocation(const QString &fileName, int line) +void QmlExpression::setSourceLocation(const QUrl &fileName, int line) { d->fileName = fileName; d->line = line; diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index d7249e4..a1028e6 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -90,16 +91,14 @@ public: QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0); struct CapturedProperty { - CapturedProperty(QObject *, int); + CapturedProperty(QObject *o, int n) + : object(o), notifyIndex(n) {} CapturedProperty(const QmlMetaProperty &); - CapturedProperty(const CapturedProperty &); - CapturedProperty &operator=(const CapturedProperty &); QObject *object; - QString name; int notifyIndex; }; - QList capturedProperties; + QPODVector capturedProperties; QmlContext *rootContext; QmlContext *currentBindContext; @@ -280,7 +279,8 @@ public: BindExpressionProxy *proxy; QObject *me; bool trackChange; - QString fileName; + + QUrl fileName; int line; quint32 id; diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index 651fd9c..15d026a 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -77,7 +77,7 @@ public: bool trackChange() const; void setTrackChange(bool); - void setSourceLocation(const QString &fileName, int line); + void setSourceLocation(const QUrl &fileName, int line); QObject *scopeObject() const; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index f00d282..9ed7e95 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -695,7 +695,7 @@ case QmlInstruction::StoreDouble: QFx_setParent_noEvent(bind, target); bind->setTarget(mp); - bind->setSourceLocation(comp->url.toString(), instr.line); + bind->setSourceLocation(comp->url, instr.line); } break; @@ -719,7 +719,7 @@ case QmlInstruction::StoreDouble: QFx_setParent_noEvent(bind, target); bind->setTarget(mp); - bind->setSourceLocation(comp->url.toString(), instr.line); + bind->setSourceLocation(comp->url, instr.line); } break; diff --git a/src/declarative/qml/qpodvector_p.h b/src/declarative/qml/qpodvector_p.h new file mode 100644 index 0000000..55c04e7 --- /dev/null +++ b/src/declarative/qml/qpodvector_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module 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 QPODVECTOR_P_H +#define QPODVECTOR_P_H + +#include + +QT_BEGIN_NAMESPACE + +template +class QPODVector +{ +public: + QPODVector() + : m_count(0), m_capacity(0), m_data(0) {} + + const T &at(int idx) { + return m_data[idx]; + } + + T &operator[](int idx) { + return m_data[idx]; + } + + void clear() { + m_count = 0; + } + + void prepend(const T &v) { + insert(0, v); + } + + void append(const T &v) { + insert(m_count, v); + } + + void insert(int idx, const T &v) { + if (m_count == m_capacity) { + m_capacity += 1024; + m_data = (T *)realloc(m_data, m_capacity * sizeof(T)); + } + int moveCount = m_count - idx; + if (moveCount) + ::memmove(m_data + idx + 1, m_data + idx, moveCount * sizeof(T)); + m_count++; + m_data[idx] = v; + } + + void insertBlank(int idx, int count) { + int newSize = m_count + count; + if (newSize >= m_capacity) { + m_capacity = (newSize + 1023) & 0xFFFFFC00; + m_data = (T *)realloc(m_data, m_capacity * sizeof(T)); + } + + int moveCount = m_count - idx; + if (moveCount) + ::memmove(m_data + idx + count, m_data + idx, + moveCount * sizeof(T)); + m_count = newSize; + } + + void remove(int idx, int count = 1) { + int moveCount = m_count - (idx + count); + if (moveCount) + ::memmove(m_data + idx, m_data + idx + count, + moveCount * sizeof(T)); + m_count -= count; + } + + int count() const { + return m_count; + } + + QPODVector &operator<<(const T &v) { append(v); return *this; } +private: + QPODVector(const QPODVector &); + QPODVector &operator=(const QPODVector &); + int m_count; + int m_capacity; + T *m_data; +}; +QT_END_NAMESPACE + +#endif -- cgit v0.12 From 5c24620b91ee57629b4356885f8b5517e3d82e32 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 14:22:04 +1000 Subject: Remove dead code --- src/declarative/qml/qmlcompiler.cpp | 4 ---- src/declarative/qml/qmlinstruction.cpp | 2 +- src/declarative/qml/qmlinstruction_p.h | 6 +----- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index fe3da57..04a488d 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1102,8 +1102,6 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, QmlInstruction assign; assign.type = QmlInstruction::AssignObjectList; assign.line = prop->location.start.line; - assign.assignObject.property = output->indexForByteArray(prop->name); - assign.assignObject.castValue = 0; output->bytecode << assign; } else { COMPILE_EXCEPTION("Cannot assign primitives to lists"); @@ -1130,8 +1128,6 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, QmlInstruction assign; assign.type = QmlInstruction::AssignObjectList; assign.line = v->location.start.line; - assign.assignObject.property = output->indexForByteArray(prop->name); - assign.assignObject.castValue = 0; output->bytecode << assign; } else if (v->value.isScript()) { if (assignedBinding) diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index af1489a..bcc1f0d 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -146,7 +146,7 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx) qWarning() << idx << "\t" << line << "\t" << "COMPLETE\t\t" << instr->complete.castValue; break; case QmlInstruction::AssignObjectList: - qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t" << instr->assignObject.property << "\t" << instr->assignObject.castValue << "\t\t" << ((instr->assignObject.property == -1)?QByteArray("default"):datas.at(instr->assignObject.property)); + qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t"; break; case QmlInstruction::FetchAttached: qWarning() << idx << "\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 5a1729f..bdbbaff 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -122,7 +122,7 @@ public: BeginObject, /* begin */ CompleteObject, /* complete */ - AssignObjectList, /* assignObject */ + AssignObjectList, /* NA */ FetchAttached, /* fetchAttached */ FetchQmlList, /* fetchQmlList */ @@ -170,10 +170,6 @@ public: } setId; struct { int property; - int castValue; - } assignObject; - struct { - int property; } assignValueSource; struct { int property; -- cgit v0.12 From 4dc4cfac667389efda4a43df5ff8cfa4ba305a2f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 10 Jun 2009 14:57:51 +1000 Subject: Support URLs directly (not just as strings), so they are correctly resolved. URLs expressed as strings (possible relative) are resolved relative to the component in which the string expression is converted to a url value. All items are converted to use QUrl properties, except SqlConnection, where the databasename is only a special-case URL (this may need further consideration). --- doc/src/declarative/basictypes.qdoc | 20 +++++++++++++ src/declarative/extra/qmlxmllistmodel.cpp | 8 ++--- src/declarative/extra/qmlxmllistmodel.h | 6 ++-- src/declarative/fx/qfxanimatedimageitem.cpp | 5 ++-- src/declarative/fx/qfxblendedimage.cpp | 34 +++++++++++----------- src/declarative/fx/qfxblendedimage.h | 14 ++++----- src/declarative/fx/qfxhighlightfilter.cpp | 12 ++++---- src/declarative/fx/qfxhighlightfilter.h | 8 ++--- src/declarative/fx/qfximage.cpp | 15 +++++----- src/declarative/fx/qfximage.h | 8 ++--- src/declarative/fx/qfximage_p.h | 1 - src/declarative/fx/qfxitem.cpp | 21 +++++++------ src/declarative/fx/qfxitem.h | 6 ++-- src/declarative/fx/qfxitem_p.h | 3 +- src/declarative/fx/qfxparticles.cpp | 18 +++++------- src/declarative/fx/qfxparticles.h | 6 ++-- src/declarative/fx/qfxwebview.cpp | 18 +++++------- src/declarative/fx/qfxwebview.h | 6 ++-- src/declarative/qml/qmlbindablevalue.cpp | 4 +++ src/declarative/qml/qmlcompiler.cpp | 11 +++++++ src/declarative/qml/qmlinstruction.cpp | 3 ++ src/declarative/qml/qmlinstruction_p.h | 6 ++++ src/declarative/qml/qmlparser_p.h | 2 +- src/declarative/qml/qmlscriptparser.cpp | 1 + src/declarative/qml/qmlvme.cpp | 16 ++++++++++ src/declarative/qml/qmlvmemetaobject.cpp | 3 ++ src/declarative/util/qfxview.cpp | 6 ---- src/declarative/util/qmlscript.cpp | 17 +++++------ src/declarative/util/qmlscript.h | 6 ++-- .../numberformatter/tst_numberformatter.cpp | 1 + 30 files changed, 166 insertions(+), 119 deletions(-) diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index f7eee50..2ef91e6 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -82,6 +82,26 @@ \raw HTML \endraw + \target basicqmlurl + \raw HTML +
+ + +
url
+ \endraw + + URLs are resource locators, such as file names. They can be either absolute, like "http://qtsoftware.com", + or relative, like "pics/logo.png". Relative URLs are resolved relative to the URL of the component where + the URL is converted from a JavaScript string expression to a url property value. + + Setting a url looks like this: + \code + Image { source: "pics/logo.png" } + \endcode + + \raw HTML + \endraw + \target basicqmlcolor \raw HTML
diff --git a/src/declarative/extra/qmlxmllistmodel.cpp b/src/declarative/extra/qmlxmllistmodel.cpp index a7f5d72..62ede80 100644 --- a/src/declarative/extra/qmlxmllistmodel.cpp +++ b/src/declarative/extra/qmlxmllistmodel.cpp @@ -270,7 +270,7 @@ public: , queryId(-1), roleObjects(this) {} bool isClassComplete; - QString src; + QUrl src; QString query; QString namespaces; int size; @@ -388,13 +388,13 @@ QString QmlXmlListModel::toString(int role) const return d->roleNames.at(index); } -QString QmlXmlListModel::source() const +QUrl QmlXmlListModel::source() const { Q_D(const QmlXmlListModel); return d->src; } -void QmlXmlListModel::setSource(const QString &src) +void QmlXmlListModel::setSource(const QUrl &src) { Q_D(QmlXmlListModel); if (d->src != src) { @@ -483,7 +483,7 @@ void QmlXmlListModel::reload() emit progressChanged(d->progress); emit statusChanged(d->status); - QNetworkRequest req((QUrl(d->src))); + QNetworkRequest req(d->src); req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req); QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); diff --git a/src/declarative/extra/qmlxmllistmodel.h b/src/declarative/extra/qmlxmllistmodel.h index 052a0c2..bdbba47 100644 --- a/src/declarative/extra/qmlxmllistmodel.h +++ b/src/declarative/extra/qmlxmllistmodel.h @@ -93,7 +93,7 @@ class Q_DECLARATIVE_EXPORT QmlXmlListModel : public QListModelInterface, public Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) - Q_PROPERTY(QString source READ source WRITE setSource) + Q_PROPERTY(QUrl source READ source WRITE setSource) Q_PROPERTY(QString query READ query WRITE setQuery) Q_PROPERTY(QString namespaceDeclarations READ namespaceDeclarations WRITE setNamespaceDeclarations) Q_PROPERTY(QmlList *roles READ roleObjects) @@ -109,8 +109,8 @@ public: QmlList *roleObjects(); - QString source() const; - void setSource(const QString&); + QUrl source() const; + void setSource(const QUrl&); QString query() const; void setQuery(const QString&); diff --git a/src/declarative/fx/qfxanimatedimageitem.cpp b/src/declarative/fx/qfxanimatedimageitem.cpp index 029206b..604481c 100644 --- a/src/declarative/fx/qfxanimatedimageitem.cpp +++ b/src/declarative/fx/qfxanimatedimageitem.cpp @@ -155,7 +155,7 @@ int QFxAnimatedImageItem::frameCount() const void QFxAnimatedImageItem::setSource(const QString &url) { Q_D(QFxAnimatedImageItem); - if (url == d->source) + if (url == d->url) return; delete d->_movie; @@ -166,8 +166,7 @@ void QFxAnimatedImageItem::setSource(const QString &url) d->reply = 0; } - d->source = url; - d->url = qmlContext(this)->resolvedUrl(url); + d->url = url; if (url.isEmpty()) { delete d->_movie; diff --git a/src/declarative/fx/qfxblendedimage.cpp b/src/declarative/fx/qfxblendedimage.cpp index 4c6eb58..1f805df 100644 --- a/src/declarative/fx/qfxblendedimage.cpp +++ b/src/declarative/fx/qfxblendedimage.cpp @@ -84,9 +84,9 @@ QFxBlendedImage::QFxBlendedImage(QFxItem *parent) \qmlproperty string BlendedImage::primaryUrl The URL of the first image to be displayed in this item. */ -QString QFxBlendedImage::primaryUrl() const +QUrl QFxBlendedImage::primaryUrl() const { - return primSrc; + return primUrl; } void QFxBlendedImage::primaryLoaded() @@ -96,15 +96,15 @@ void QFxBlendedImage::primaryLoaded() update(); } -void QFxBlendedImage::setPrimaryUrl(const QString &url) +void QFxBlendedImage::setPrimaryUrl(const QUrl &url) { - if (primSrc == url) + if (primUrl == url) return; - if (!primSrc.isEmpty()) + if (!primUrl.isEmpty()) QFxPixmap::cancelGet(primUrl,this); - primSrc = url; - primUrl = qmlContext(this)->resolvedUrl(url); - if (!primSrc.isEmpty()) + Q_ASSERT(!primUrl.isRelative()); + primUrl = url; + if (!primUrl.isEmpty()) QFxPixmap::get(qmlEngine(this), primUrl,this,SLOT(primaryLoaded())); } @@ -112,9 +112,9 @@ void QFxBlendedImage::setPrimaryUrl(const QString &url) \qmlproperty string BlendedImage::secondaryUrl The URL of the second image to be displayed in this item. */ -QString QFxBlendedImage::secondaryUrl() const +QUrl QFxBlendedImage::secondaryUrl() const { - return secSrc; + return secUrl; } void QFxBlendedImage::secondaryLoaded() @@ -124,15 +124,15 @@ void QFxBlendedImage::secondaryLoaded() update(); } -void QFxBlendedImage::setSecondaryUrl(const QString &url) +void QFxBlendedImage::setSecondaryUrl(const QUrl &url) { - if (secSrc == url) + if (secUrl == url) return; - if (!secSrc.isEmpty()) + if (!secUrl.isEmpty()) QFxPixmap::cancelGet(secUrl,this); - secSrc = url; - secUrl = qmlContext(this)->resolvedUrl(url); - if (!secSrc.isEmpty()) + Q_ASSERT(!url.isRelative()); + secUrl = url; + if (!secUrl.isEmpty()) QFxPixmap::get(qmlEngine(this), secUrl,this,SLOT(secondaryLoaded())); } @@ -183,7 +183,7 @@ void QFxBlendedImage::setSmoothTransform(bool s) void QFxBlendedImage::paintContents(QPainter &p) { - if (primSrc.isNull() && secSrc.isNull()) + if (primUrl.isEmpty() && secUrl.isEmpty()) return; if (_smooth) { diff --git a/src/declarative/fx/qfxblendedimage.h b/src/declarative/fx/qfxblendedimage.h index baf4b64..7169b92 100644 --- a/src/declarative/fx/qfxblendedimage.h +++ b/src/declarative/fx/qfxblendedimage.h @@ -57,18 +57,18 @@ class Q_DECLARATIVE_EXPORT QFxBlendedImage : public QFxItem { Q_OBJECT - Q_PROPERTY(QString primaryUrl READ primaryUrl WRITE setPrimaryUrl) - Q_PROPERTY(QString secondaryUrl READ secondaryUrl WRITE setSecondaryUrl) + Q_PROPERTY(QUrl primaryUrl READ primaryUrl WRITE setPrimaryUrl) + Q_PROPERTY(QUrl secondaryUrl READ secondaryUrl WRITE setSecondaryUrl) Q_PROPERTY(qreal blend READ blend WRITE setBlend) Q_PROPERTY(bool smooth READ smoothTransform WRITE setSmoothTransform) public: QFxBlendedImage(QFxItem *parent=0); - QString primaryUrl() const; - void setPrimaryUrl(const QString &); + QUrl primaryUrl() const; + void setPrimaryUrl(const QUrl &); - QString secondaryUrl() const; - void setSecondaryUrl(const QString &); + QUrl secondaryUrl() const; + void setSecondaryUrl(const QUrl &); qreal blend() const; void setBlend(qreal); @@ -87,8 +87,6 @@ private Q_SLOTS: void secondaryLoaded(); private: - QString primSrc; - QString secSrc; QUrl primUrl; QUrl secUrl; diff --git a/src/declarative/fx/qfxhighlightfilter.cpp b/src/declarative/fx/qfxhighlightfilter.cpp index 6bf3148..3d5f413 100644 --- a/src/declarative/fx/qfxhighlightfilter.cpp +++ b/src/declarative/fx/qfxhighlightfilter.cpp @@ -128,7 +128,7 @@ QFxHighlightFilter::~QFxHighlightFilter() \property QFxHighlightFilter::source \brief the URL of the image to be used as the highlight. */ -QString QFxHighlightFilter::source() const +QUrl QFxHighlightFilter::source() const { return d->source; } @@ -144,14 +144,14 @@ void QFxHighlightFilter::imageLoaded() update(); } -void QFxHighlightFilter::setSource(const QString &f) +void QFxHighlightFilter::setSource(const QUrl &f) { - if (d->source == f) + if (d->url == f) return; - if (!d->source.isEmpty()) + if (!d->url.isEmpty()) QFxPixmap::cancelGet(d->url, this); - d->source = f; - d->url = qmlContext(this)->resolvedUrl(f); + Q_ASSERT(!f.isRelative()); + d->url = f; #if defined(QFX_RENDER_OPENGL2) d->tex.clear(); #endif diff --git a/src/declarative/fx/qfxhighlightfilter.h b/src/declarative/fx/qfxhighlightfilter.h index 19e95ac..33f0963 100644 --- a/src/declarative/fx/qfxhighlightfilter.h +++ b/src/declarative/fx/qfxhighlightfilter.h @@ -56,7 +56,7 @@ class Q_DECLARATIVE_EXPORT QFxHighlightFilter : public QSimpleCanvasFilter { Q_OBJECT - Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(bool tiled READ tiled WRITE setTiled NOTIFY tiledChanged) Q_PROPERTY(int xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged) Q_PROPERTY(int yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged) @@ -64,8 +64,8 @@ public: QFxHighlightFilter(QObject *parent=0); virtual ~QFxHighlightFilter(); - QString source() const; - void setSource(const QString &); + QUrl source() const; + void setSource(const QUrl &); bool tiled() const; void setTiled(bool); @@ -76,7 +76,7 @@ public: void setYOffset(int); Q_SIGNALS: - void sourceChanged(const QString &); + void sourceChanged(const QUrl &); void offsetChanged(int x, int y); void tiledChanged(bool); diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 224c25e..05738e3 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -825,19 +825,19 @@ qreal QFxImage::progress() const The content specified can be of any image type loadable by QImage. Alternatively, you can specify an sci format file, which specifies both an image and it's scale grid. */ -QString QFxImage::source() const +QUrl QFxImage::source() const { Q_D(const QFxImage); - return d->source; + return d->url; } -void QFxImage::setSource(const QString &url) +void QFxImage::setSource(const QUrl &url) { #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer perf; #endif Q_D(QFxImage); - if (url == d->source) + if (url == d->url) return; if (d->sciReply) { @@ -850,8 +850,7 @@ void QFxImage::setSource(const QString &url) if (!d->sciurl.isEmpty()) QFxPixmap::cancelGet(d->sciurl, this); - d->source = url; - d->url = qmlContext(this)->resolvedUrl(url); + d->url = url; d->sciurl = QUrl(); if (d->progress != 0.0) { d->progress = 0.0; @@ -872,7 +871,7 @@ void QFxImage::setSource(const QString &url) } #endif emit statusChanged(d->status); - emit sourceChanged(d->source); + emit sourceChanged(d->url); emit progressChanged(1.0); update(); } else { @@ -936,7 +935,7 @@ void QFxImage::requestFinished() } #endif emit statusChanged(d->status); - emit sourceChanged(d->source); + emit sourceChanged(d->url); emit progressChanged(1.0); update(); } diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index 4d5f134..35b921a 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -58,7 +58,7 @@ class Q_DECLARATIVE_EXPORT QFxImage : public QFxItem Q_ENUMS(Status) Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid) @@ -88,8 +88,8 @@ public: Status status() const; qreal progress() const; - QString source() const; - virtual void setSource(const QString &url); + QUrl source() const; + virtual void setSource(const QUrl &url); virtual void dump(int depth); virtual QString propertyInfo() const; @@ -102,7 +102,7 @@ public: #endif Q_SIGNALS: - void sourceChanged(const QString &); + void sourceChanged(const QUrl &); void statusChanged(Status); void progressChanged(qreal progress); diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index cd07a37..1785abb 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -106,7 +106,6 @@ public: #endif QFxImage::Status status; - QString source; QUrl url; QUrl sciurl; QNetworkReply *sciReply; diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 7129757..09ec748 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -792,12 +792,12 @@ QFxItem *QFxItem::qmlItem() const } /*! - \qmlproperty string Item::qml - This property holds the dynamic QML for the item. + \qmlproperty url Item::qml + This property holds the dynamic URL of the QML for the item. This property is used for dynamically loading QML into the item. Querying for the QML only has meaning if the QML has been - dynamically set; otherwise an empty string is returned. + dynamically set; otherwise an empty URL is returned. */ /*! \fn void QFxItem::qmlChanged() @@ -809,32 +809,31 @@ QFxItem *QFxItem::qmlItem() const /*! \property QFxItem::qml - This property holds the dynamic QML for the item. + This property holds the dynamic URL of the QML for the item. This property is used for dynamically loading QML into the item. Querying for the QML only has meaning if the QML has been - dynamically set; otherwise an empty string is returned. + dynamically set; otherwise an empty URL is returned. */ -QString QFxItem::qml() const +QUrl QFxItem::qml() const { Q_D(const QFxItem); return d->_qml; } -void QFxItem::setQml(const QString &qml) +void QFxItem::setQml(const QUrl &qml) { Q_D(QFxItem); if (d->_qml == qml) return; if (!d->_qml.isEmpty()) { - QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml); + QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml.toString()); if (iter != d->_qmlChildren.end()) (*iter)->setOpacity(0.); } d->_qml = qml; - d->_qmlurl = qmlContext(this)->resolvedUri(qml); d->qmlItem = 0; if (d->_qml.isEmpty()) { @@ -842,14 +841,14 @@ void QFxItem::setQml(const QString &qml) return; } - QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml); + QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml.toString()); if (iter != d->_qmlChildren.end()) { (*iter)->setOpacity(1.); d->qmlItem = (*iter); emit qmlChanged(); } else { d->_qmlcomp = - new QmlComponent(qmlEngine(this), d->_qmlurl, this); + new QmlComponent(qmlEngine(this), d->_qml, this); if (!d->_qmlcomp->isLoading()) qmlLoaded(); else diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index 8ca1f9e..3c872e1 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -111,7 +111,7 @@ class Q_DECLARATIVE_EXPORT QFxItem : public QSimpleCanvasItem, public QmlParserS Q_PROPERTY(QmlList* states READ states DESIGNABLE false) Q_PROPERTY(QmlList* transitions READ transitions DESIGNABLE false) Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged) - Q_PROPERTY(QString qml READ qml WRITE setQml NOTIFY qmlChanged) + Q_PROPERTY(QUrl qml READ qml WRITE setQml NOTIFY qmlChanged) Q_PROPERTY(QFxItem *qmlItem READ qmlItem NOTIFY qmlChanged) Q_PROPERTY(qreal x READ x WRITE setX NOTIFY leftChanged) Q_PROPERTY(qreal y READ y WRITE setY NOTIFY topChanged) @@ -171,8 +171,8 @@ public: void setState(const QString &); QFxItem *qmlItem() const; - QString qml() const; - void setQml(const QString &); + QUrl qml() const; + void setQml(const QUrl &); bool flipVertically() const; void setFlipVertically(bool); diff --git a/src/declarative/fx/qfxitem_p.h b/src/declarative/fx/qfxitem_p.h index a54f523..b38d877 100644 --- a/src/declarative/fx/qfxitem_p.h +++ b/src/declarative/fx/qfxitem_p.h @@ -133,9 +133,8 @@ public: QFxAnchors *_anchors; QFxContents *_contents; QFxItem *qmlItem; - QUrl _qmlurl; QmlComponent *_qmlcomp; - QString _qml; + QUrl _qml; QList _qmlnewloading; QList _qmlnewcomp; diff --git a/src/declarative/fx/qfxparticles.cpp b/src/declarative/fx/qfxparticles.cpp index 41fb5bc..25e359d 100644 --- a/src/declarative/fx/qfxparticles.cpp +++ b/src/declarative/fx/qfxparticles.cpp @@ -395,7 +395,6 @@ public: void createParticle(int time); void updateOpacity(QFxParticle &p, int age); - QString source; QUrl url; QPixmap image; int count; @@ -642,10 +641,10 @@ QFxParticles::~QFxParticles() \property QFxParticles::source \brief the URL of the particle image. */ -QString QFxParticles::source() const +QUrl QFxParticles::source() const { Q_D(const QFxParticles); - return d->source; + return d->url; } void QFxParticles::imageLoaded() @@ -659,18 +658,17 @@ void QFxParticles::imageLoaded() update(); } -void QFxParticles::setSource(const QString &name) +void QFxParticles::setSource(const QUrl &name) { Q_D(QFxParticles); - if (name == d->source) + if (name == d->url) return; - if (!d->source.isEmpty()) + if (!d->url.isEmpty()) QFxPixmap::cancelGet(d->url, this); if (name.isEmpty()) { - d->source = name; - d->url = QUrl(); + d->url = name; d->image = QPixmap(); #if defined(QFX_RENDER_OPENGL) d->texDirty = true; @@ -678,8 +676,8 @@ void QFxParticles::setSource(const QString &name) #endif update(); } else { - d->source = name; - d->url = qmlContext(this)->resolvedUrl(name); + d->url = name; + Q_ASSERT(!name.isRelative()); QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(imageLoaded())); } } diff --git a/src/declarative/fx/qfxparticles.h b/src/declarative/fx/qfxparticles.h index 6ef2582..b3a569b 100644 --- a/src/declarative/fx/qfxparticles.h +++ b/src/declarative/fx/qfxparticles.h @@ -153,7 +153,7 @@ class Q_DECLARATIVE_EXPORT QFxParticles : public QFxItem { Q_OBJECT - Q_PROPERTY(QString source READ source WRITE setSource) + Q_PROPERTY(QUrl source READ source WRITE setSource) Q_PROPERTY(int count READ count WRITE setCount) Q_PROPERTY(int lifeSpan READ lifeSpan WRITE setLifeSpan) Q_PROPERTY(int lifeSpanDeviation READ lifeSpanDeviation WRITE setLifeSpanDeviation) @@ -172,8 +172,8 @@ public: QFxParticles(QFxItem *parent=0); ~QFxParticles(); - QString source() const; - void setSource(const QString &); + QUrl source() const; + void setSource(const QUrl &); int count() const; void setCount(int cnt); diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index bfccd34..d15502b 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -287,7 +287,7 @@ void QFxWebView::componentComplete() Q_D(QFxWebView); switch (d->pending) { case QFxWebViewPrivate::PendingUrl: - setUrl(d->pending_url.toString()); + setUrl(d->pending_url); break; case QFxWebViewPrivate::PendingHtml: setHtml(d->pending_string, d->pending_url); @@ -339,7 +339,7 @@ void QFxWebView::doLoadFinished(bool ok) } /*! - \qmlproperty string WebView::url + \qmlproperty url WebView::url This property holds the URL to the page displayed in this item. Note that after this property is set, it may take some time @@ -358,24 +358,22 @@ void QFxWebView::doLoadFinished(bool ok) Emitted when loading of the URL successfully starts after setUrl() is called. */ -QString QFxWebView::url() const +QUrl QFxWebView::url() const { - return page()->mainFrame()->url().toString(); + return page()->mainFrame()->url(); } -void QFxWebView::setUrl(const QString &n) +void QFxWebView::setUrl(const QUrl &url) { Q_D(QFxWebView); - if (n == page()->mainFrame()->url().toString()) + if (url == page()->mainFrame()->url()) return; page()->setViewportSize(QSize( d->idealwidth>0 ? d->idealwidth : width(), d->idealheight>0 ? d->idealheight : height())); - QUrl url(n); - if (url.isRelative()) - url = qmlContext(this)->resolvedUrl(n); + Q_ASSERT(!url.isRelative()); if (isComponentComplete()) page()->mainFrame()->load(url); @@ -942,7 +940,7 @@ void QFxWebView::setHtml(const QString &html, const QUrl &baseUrl) d->idealwidth>0 ? d->idealwidth : width(), d->idealheight>0 ? d->idealheight : height())); if (isComponentComplete()) - page()->mainFrame()->setHtml(html, qmlContext(this)->resolvedUrl(baseUrl)); + page()->mainFrame()->setHtml(html, baseUrl); else { d->pending = d->PendingHtml; d->pending_url = baseUrl; diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index 28ef6c3..f30fd0d 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -90,7 +90,7 @@ class Q_DECLARATIVE_EXPORT QFxWebView : public QFxPaintedItem Q_PROPERTY(int idealWidth READ idealWidth WRITE setIdealWidth NOTIFY idealWidthChanged) Q_PROPERTY(int idealHeight READ idealHeight WRITE setIdealHeight NOTIFY idealHeightChanged) - Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(bool interactive READ interactive WRITE setInteractive NOTIFY interactiveChanged) @@ -108,8 +108,8 @@ public: QFxWebView(QFxItem *parent=0); ~QFxWebView(); - QString url() const; - void setUrl(const QString &); + QUrl url() const; + void setUrl(const QUrl &); QString title() const; diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp index 351e0bd..de01387 100644 --- a/src/declarative/qml/qmlbindablevalue.cpp +++ b/src/declarative/qml/qmlbindablevalue.cpp @@ -220,6 +220,10 @@ void QmlBindableValue::update() } else if (d->property.propertyCategory() == QmlMetaProperty::Normal) { QVariant value = this->value(); + if (d->property.propertyType() == QVariant::Url && value.canConvert(QVariant::String) && !value.isNull()) { + // Must resolve first + value.setValue(context()->resolvedUrl(value.toString())); + } d->property.write(value); } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index b28d7dd..8b4be2b 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -278,6 +278,14 @@ bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr, instr.storeString.value = output->indexForString(string); } break; + case QVariant::Url: + { + instr.type = QmlInstruction::StoreUrl; + QUrl u = output->url.resolved(string); + instr.storeUrl.propertyIndex = prop.propertyIndex(); + instr.storeUrl.value = output->indexForString(u.toString()); + } + break; case QVariant::UInt: { instr.type = QmlInstruction::StoreInteger; @@ -1355,6 +1363,9 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj) case Object::DynamicProperty::String: type = "QString"; break; + case Object::DynamicProperty::Url: + type = "QUrl"; + break; case Object::DynamicProperty::Color: type = "QColor"; break; diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index af1489a..3fe3a8e 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -85,6 +85,9 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx) case QmlInstruction::StoreString: qWarning() << idx << "\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); break; + case QmlInstruction::StoreUrl: + qWarning() << idx << "\t" << line << "\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << primitives.at(instr->storeUrl.value); + break; case QmlInstruction::StoreColor: qWarning() << idx << "\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t" << QString::number(instr->storeColor.value, 16); break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 5a1729f..7cdc1ed 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -76,6 +76,7 @@ public: // StoreInteger - Store a int or uint in a core property // StoreBool - Store a bool in a core property // StoreString - Store a QString in a core property + // StoreUrl - Store a QUrl in a core property // StoreColor - Store a QColor in a core property // StoreDate - Store a QDate in a core property // StoreTime - Store a QTime in a core property @@ -88,6 +89,7 @@ public: StoreInteger, /* storeInteger */ StoreBool, /* storeBool */ StoreString, /* storeString */ + StoreUrl, /* storeUrl */ StoreColor, /* storeColor */ StoreDate, /* storeDate */ StoreTime, /* storeTime */ @@ -217,6 +219,10 @@ public: } storeString; struct { int propertyIndex; + int value; + } storeUrl; + struct { + int propertyIndex; unsigned int value; } storeColor; struct { diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 0fdd26b..7989933 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -131,7 +131,7 @@ namespace QmlParser DynamicProperty(); DynamicProperty(const DynamicProperty &); - enum Type { Variant, Int, Bool, Real, String, Color, Date }; + enum Type { Variant, Int, Bool, Real, String, Url, Color, Date }; bool isDefaultProperty; Type type; diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 5207292..cab7915 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -501,6 +501,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node) { "double", Object::DynamicProperty::Real }, { "real", Object::DynamicProperty::Real }, { "string", Object::DynamicProperty::String }, + { "url", Object::DynamicProperty::Url }, { "color", Object::DynamicProperty::Color }, { "date", Object::DynamicProperty::Date }, { "var", Object::DynamicProperty::Variant }, diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index f00d282..af0b3e0 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -77,6 +77,7 @@ Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) { Q_DECLARE_PERFORMANCE_METRIC(InstrStoreInteger); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBool); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreString); + Q_DECLARE_PERFORMANCE_METRIC(InstrStoreUrl); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreColor); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDate); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDateTime); @@ -116,6 +117,7 @@ Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") { Q_DEFINE_PERFORMANCE_METRIC(InstrStoreInteger, "StoreInteger"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBool, "StoreBool"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreString, "StoreString"); + Q_DEFINE_PERFORMANCE_METRIC(InstrStoreUrl, "StoreUrl"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreColor, "StoreColor"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDate, "StoreDate"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDateTime, "StoreDateTime"); @@ -337,6 +339,20 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in } break; + case QmlInstruction::StoreUrl: + { +#ifdef Q_ENABLE_PERFORMANCE_LOG + QFxCompilerTimer cc; +#endif + QObject *target = stack.top(); + void *a[1]; + QUrl u(primitives.at(instr.storeUrl.value)); + a[0] = (void *)&u; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.storeUrl.propertyIndex, a); + } + break; + case QmlInstruction::StoreFloat: { #ifdef Q_ENABLE_PERFORMANCE_LOG diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index 58708cf..0117448 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -134,6 +134,9 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int id, void **a) case QVariant::String: *reinterpret_cast(a[0]) = data[propId].toString(); break; + case QVariant::Url: + *reinterpret_cast(a[0]) = data[propId].toUrl(); + break; case QVariant::Color: *reinterpret_cast(a[0]) = data[propId].value(); break; diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp index 0d5b796..d8d9ba1 100644 --- a/src/declarative/util/qfxview.cpp +++ b/src/declarative/util/qfxview.cpp @@ -84,11 +84,6 @@ static QVariant stringToKeySequence(const QString &str) return QVariant::fromValue(QKeySequence(str)); } -static QVariant stringToUrl(const QString &str) -{ - return QVariant(QUrl(str)); -} - class QFxViewPrivate { public: @@ -166,7 +161,6 @@ void QFxViewPrivate::init() QmlMetaType::registerCustomStringConverter(QVariant::Pixmap, &stringToPixmap); QmlMetaType::registerCustomStringConverter(QVariant::Icon, &stringToIcon); QmlMetaType::registerCustomStringConverter(QVariant::KeySequence, &stringToKeySequence); - QmlMetaType::registerCustomStringConverter(QVariant::Url, &stringToUrl); #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer perf; diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp index 45370e2..e422f37 100644 --- a/src/declarative/util/qmlscript.cpp +++ b/src/declarative/util/qmlscript.cpp @@ -69,7 +69,6 @@ public: void addScriptToEngine(const QString &, const QString &fileName=QString()); QString script; - QString source; QNetworkReply *reply; QUrl url; }; @@ -138,26 +137,26 @@ void QmlScript::setScript(const QString &script) \property QmlScript::source \brief the path to a script file. */ -QString QmlScript::source() const +QUrl QmlScript::source() const { Q_D(const QmlScript); - return d->source; + return d->url; } -void QmlScript::setSource(const QString &source) +void QmlScript::setSource(const QUrl &source) { Q_D(QmlScript); - if (d->source == source) + if (d->url == source) return; - d->source = source; - d->url = qmlContext(this)->resolvedUrl(source); + d->url = source; + Q_ASSERT(!source.isRelative()); #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML if (d->url.scheme() == QLatin1String("file")) { QFile file(d->url.toLocalFile()); file.open(QIODevice::ReadOnly); QByteArray ba = file.readAll(); - d->addScriptToEngine(QString::fromUtf8(ba), d->source); + d->addScriptToEngine(QString::fromUtf8(ba), d->url); } else #endif { @@ -174,7 +173,7 @@ void QmlScript::replyFinished() Q_D(QmlScript); if (!d->reply->error()) { QByteArray ba = d->reply->readAll(); - d->addScriptToEngine(QString::fromUtf8(ba), d->source); + d->addScriptToEngine(QString::fromUtf8(ba), d->url); } d->reply->deleteLater(); d->reply = 0; diff --git a/src/declarative/util/qmlscript.h b/src/declarative/util/qmlscript.h index dc090bc..09ebc2c 100644 --- a/src/declarative/util/qmlscript.h +++ b/src/declarative/util/qmlscript.h @@ -58,7 +58,7 @@ class Q_DECLARATIVE_EXPORT QmlScript : public QObject Q_DECLARE_PRIVATE(QmlScript) Q_PROPERTY(QString script READ script WRITE setScript) - Q_PROPERTY(QString source READ source WRITE setSource) + Q_PROPERTY(QUrl source READ source WRITE setSource) Q_CLASSINFO("DefaultProperty", "script") public: @@ -67,8 +67,8 @@ public: QString script() const; void setScript(const QString &); - QString source() const; - void setSource(const QString &); + QUrl source() const; + void setSource(const QUrl &); private Q_SLOTS: void replyFinished(); diff --git a/tests/auto/declarative/numberformatter/tst_numberformatter.cpp b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp index e70d651..9a2f4f3 100644 --- a/tests/auto/declarative/numberformatter/tst_numberformatter.cpp +++ b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include -- cgit v0.12 From 6b88d7152a72a3a6ba12cb6b4eeeecc1a0c24c51 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 15:03:29 +1000 Subject: Improve list assignment performance --- src/declarative/qml/qmlcompiler.cpp | 68 +++++++++++++++++--- src/declarative/qml/qmlcompiler_p.h | 2 + src/declarative/qml/qmlinstruction_p.h | 4 +- src/declarative/qml/qmlvme.cpp | 110 +++++++++++++++++---------------- 4 files changed, 120 insertions(+), 64 deletions(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 04a488d..16e1b13 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1091,7 +1091,9 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, fetch.line = prop->location.start.line; fetch.type = QmlInstruction::FetchQmlList; fetch.fetchQmlList.property = prop->index; - fetch.fetchQmlList.type = QmlMetaType::qmlListType(t); + int listType = QmlMetaType::qmlListType(t); + bool listTypeIsInterface = QmlMetaType::isInterface(listType); + fetch.fetchQmlList.type = listType; output->bytecode << fetch; for (int ii = 0; ii < prop->values.count(); ++ii) { @@ -1099,10 +1101,23 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, if (v->object) { v->type = Value::CreatedObject; COMPILE_CHECK(compileObject(v->object, ctxt)); - QmlInstruction assign; - assign.type = QmlInstruction::AssignObjectList; - assign.line = prop->location.start.line; - output->bytecode << assign; + + if (!listTypeIsInterface) { + if (canConvert(listType, v->object)) { + QmlInstruction store; + store.type = QmlInstruction::StoreObjectQmlList; + store.line = prop->location.start.line; + output->bytecode << store; + } else { + COMPILE_EXCEPTION("Cannot assign object to list"); + } + + } else { + QmlInstruction assign; + assign.type = QmlInstruction::AssignObjectList; + assign.line = prop->location.start.line; + output->bytecode << assign; + } } else { COMPILE_EXCEPTION("Cannot assign primitives to lists"); } @@ -1116,7 +1131,10 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, QmlInstruction fetch; fetch.type = QmlInstruction::FetchQList; fetch.line = prop->location.start.line; - fetch.fetch.property = prop->index; + fetch.fetchQmlList.property = prop->index; + int listType = QmlMetaType::listType(t); + bool listTypeIsInterface = QmlMetaType::isInterface(listType); + fetch.fetchQmlList.type = listType; output->bytecode << fetch; bool assignedBinding = false; @@ -1125,10 +1143,22 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, if (v->object) { v->type = Value::CreatedObject; COMPILE_CHECK(compileObject(v->object, ctxt)); - QmlInstruction assign; - assign.type = QmlInstruction::AssignObjectList; - assign.line = v->location.start.line; - output->bytecode << assign; + + if (!listTypeIsInterface) { + if (canConvert(listType, v->object)) { + QmlInstruction store; + store.type = QmlInstruction::StoreObjectQList; + store.line = prop->location.start.line; + output->bytecode << store; + } else { + COMPILE_EXCEPTION("Cannot assign object to list"); + } + } else { + QmlInstruction assign; + assign.type = QmlInstruction::AssignObjectList; + assign.line = v->location.start.line; + output->bytecode << assign; + } } else if (v->value.isScript()) { if (assignedBinding) COMPILE_EXCEPTION("Can only assign one binding to lists"); @@ -1575,6 +1605,24 @@ void QmlCompiler::finalizeBinding(const BindingReference &binding) instr.assignBinding.category = QmlMetaProperty::propertyCategory(mp); } +/*! + Returns true if object can be assigned to a (QObject) property of type + convertType. +*/ +bool QmlCompiler::canConvert(int convertType, QmlParser::Object *object) +{ + const QMetaObject *convertTypeMo = + QmlMetaType::rawMetaObjectForType(convertType); + const QMetaObject *objectMo = object->metaObject(); + + while (objectMo) { + if (objectMo == convertTypeMo) + return true; + objectMo = objectMo->superClass(); + } + return false; +} + QmlCompiledData::QmlCompiledData() { } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 6b6d8cb..3b1a496 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -179,6 +179,8 @@ private: struct BindingReference; void finalizeBinding(const BindingReference &); + bool canConvert(int, QmlParser::Object *); + struct IdReference { QString id; QmlParser::Object *object; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index bdbbaff..a1d923d 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -105,8 +105,6 @@ public: StoreSignal, /* storeSignal */ - StoreObjectQmlList, - // XXX need to handle storing objects in variants // @@ -122,6 +120,8 @@ public: BeginObject, /* begin */ CompleteObject, /* complete */ + StoreObjectQmlList, /* NA */ + StoreObjectQList, /* NA */ AssignObjectList, /* NA */ FetchAttached, /* fetchAttached */ diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 9ed7e95..3f7739e 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -87,6 +87,7 @@ Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) { Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObject); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSignal); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQmlList); + Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQList); Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignalObject); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBinding); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreCompiledBinding); @@ -126,6 +127,7 @@ Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") { Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObject, "StoreObject"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSignal, "StoreSignal"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQmlList, "StoreObjectQmlList"); + Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQList, "StoreObjectQList"); Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignalObject, "AssignSignalObject"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBinding, "StoreBinding"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreCompiledBinding, "StoreCompiledBinding"); @@ -171,13 +173,18 @@ QmlVME::QmlVME() struct ListInstance { ListInstance() {} + /* ListInstance(const QVariant &l, int t) : list(l), type(t), qmlListInterface(0) {} + */ + ListInstance(QList *q, int t) + : type(t), qListInterface(q) {} ListInstance(QmlPrivate::ListInterface *q, int t) : type(t), qmlListInterface(q) {} - QVariant list; + //QVariant list; int type; + QList *qListInterface; QmlPrivate::ListInterface *qmlListInterface; }; @@ -737,65 +744,56 @@ case QmlInstruction::StoreDouble: } break; + case QmlInstruction::StoreObjectQmlList: + { +#ifdef Q_ENABLE_PERFORMANCE_LOG + QFxCompilerTimer cc; +#endif + QObject *assign = stack.pop(); + const ListInstance &list = qliststack.top(); + + void *d = (void *)&assign; + list.qmlListInterface->append(d); + } + break; + + case QmlInstruction::StoreObjectQList: + { +#ifdef Q_ENABLE_PERFORMANCE_LOG + QFxCompilerTimer cc; +#endif + QObject *assign = stack.pop(); + + const ListInstance &list = qliststack.top(); + list.qListInterface->append((void *)assign); + } + break; + case QmlInstruction::AssignObjectList: { + // This is only used for assigning interfaces #ifdef Q_ENABLE_PERFORMANCE_LOG QFxCompilerTimer cc; #endif QObject *assign = stack.pop(); const ListInstance &list = qliststack.top(); - if (list.qmlListInterface) { - int type = list.type; - - void *d = 0; - void *ptr = 0; - bool found = false; - - if (QmlMetaType::isInterface(type)) { - const char *iid = QmlMetaType::interfaceIId(type); - if (iid) - ptr = assign->qt_metacast(iid); - if (ptr) { - d = &ptr; - found = true; - } - } else { - const QMetaObject *mo = - QmlMetaType::rawMetaObjectForType(type); - - const QMetaObject *assignMo = assign->metaObject(); - while(!found && assignMo) { - if (assignMo == mo) - found = true; - else - assignMo = assignMo->superClass(); - } - - // NOTE: This assumes a cast to QObject does not alter - // the object pointer - d = (void *)&assign; - } + int type = list.type; - if (!found) - VME_EXCEPTION("Cannot assign object to list"); + void *ptr = 0; - list.qmlListInterface->append(d); + const char *iid = QmlMetaType::interfaceIId(type); + if (iid) + ptr = assign->qt_metacast(iid); + if (!ptr) + VME_EXCEPTION("Cannot assign object to list"); + + if (list.qmlListInterface) { + void *d = (void *)&ptr; + list.qmlListInterface->append(d); } else { - int type = list.type; - - if (QmlMetaType::isInterface(type)) { - void *ptr = 0; - const char *iid = QmlMetaType::interfaceIId(type); - if (iid) - ptr = assign->qt_metacast(iid); - QVariant v(list.type, &ptr); - QmlMetaType::append(list.list, v); - } else { - QVariant v = QmlMetaType::fromObject(assign, list.type); - QmlMetaType::append(list.list, v); - } + list.qListInterface->append(ptr); } } break; @@ -883,10 +881,18 @@ case QmlInstruction::StoreDouble: QFxCompilerTimer cc; #endif QObject *target = stack.top(); - QMetaProperty prop = - target->metaObject()->property(instr.fetch.property); - QVariant v = prop.read(target); - qliststack.push(ListInstance(v, QmlMetaType::listType(prop.userType()))); + + void *a[1]; + // We know that QList* can be converted to + // QList* + QList *list = 0; + a[0] = &list; + QMetaObject::metacall(target, QMetaObject::ReadProperty, + instr.fetchQmlList.property, a); + if (!list) + VME_EXCEPTION("Cannot assign to null list"); + + qliststack.push(ListInstance(list, instr.fetchQmlList.type)); } break; -- cgit v0.12 From 4f40fa9b92f6f31f5a6d584f8890e2331b68f3bc Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 15:07:51 +1000 Subject: Remove perf metrics These numbers were always too small to be measured meaningfully in this way. --- src/declarative/qml/qmlvme.cpp | 209 ----------------------------------------- 1 file changed, 209 deletions(-) diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 3f7739e..28b880c 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -66,91 +66,6 @@ #include QT_BEGIN_NAMESPACE -Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) { - Q_DECLARE_PERFORMANCE_METRIC(InstrCreateObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrCreateCustomObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrSetId); - Q_DECLARE_PERFORMANCE_METRIC(InstrSetDefault); - Q_DECLARE_PERFORMANCE_METRIC(InstrCreateComponent); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreMetaObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreReal); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreInteger); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBool); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreString); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreColor); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDate); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDateTime); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreTime); - Q_DECLARE_PERFORMANCE_METRIC(InstrStorePoint); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSize); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreVariant); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSignal); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQmlList); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQList); - Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignalObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBinding); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreCompiledBinding); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreValueSource); - Q_DECLARE_PERFORMANCE_METRIC(InstrBeginObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrCompleteObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrAssignObjectList); - Q_DECLARE_PERFORMANCE_METRIC(InstrFetchAttached); - Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQmlList); - Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQList); - Q_DECLARE_PERFORMANCE_METRIC(InstrFetchObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrPopFetchedObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrPopQList); - Q_DECLARE_PERFORMANCE_METRIC(InstrPushProperty); - Q_DECLARE_PERFORMANCE_METRIC(InstrStoreStackObject); - Q_DECLARE_PERFORMANCE_METRIC(Dummy); -} - -Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") { - Q_DEFINE_PERFORMANCE_METRIC(InstrCreateObject, "CreateObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrCreateCustomObject, "CreateCustomObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrSetId, "SetId"); - Q_DEFINE_PERFORMANCE_METRIC(InstrSetDefault, "SetDefault"); - Q_DEFINE_PERFORMANCE_METRIC(InstrCreateComponent, "CreateComponent"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreMetaObject, "StoreMetaObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreReal, "StoreReal"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreInteger, "StoreInteger"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBool, "StoreBool"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreString, "StoreString"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreColor, "StoreColor"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDate, "StoreDate"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDateTime, "StoreDateTime"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreTime, "StoreTime"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStorePoint, "StorePoint(F)"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSize, "StoreSize(F)"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreVariant, "StoreVariant"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObject, "StoreObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSignal, "StoreSignal"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQmlList, "StoreObjectQmlList"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQList, "StoreObjectQList"); - Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignalObject, "AssignSignalObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBinding, "StoreBinding"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreCompiledBinding, "StoreCompiledBinding"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreValueSource, "StoreValueSource"); - Q_DEFINE_PERFORMANCE_METRIC(InstrBeginObject, "BeginObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrCompleteObject, "CompleteObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrAssignObjectList, "AssignObjectList"); - Q_DEFINE_PERFORMANCE_METRIC(InstrFetchAttached, "FetchAttached"); - Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQmlList, "FetchQmlList"); - Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQList, "FetchQList"); - Q_DEFINE_PERFORMANCE_METRIC(InstrFetchObject, "FetchObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrPopFetchedObject, "PopFetchedObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrPopQList, "PopQList"); - Q_DEFINE_PERFORMANCE_METRIC(InstrPushProperty, "PushProperty"); - Q_DEFINE_PERFORMANCE_METRIC(InstrStoreStackObject, "StoreStackObject"); - Q_DEFINE_PERFORMANCE_METRIC(Dummy, "Dummy"); -} - -static inline int qIndexOfProperty(QObject *o, const char *name) -{ - int idx = o->metaObject()->indexOfProperty(name); - return idx; -} QmlVME::QmlVME() { @@ -207,9 +122,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in const QList &floatData = comp->floatData; -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxPerfTimer cr; -#endif QmlEnginePrivate::SimpleList bindValues; QmlEnginePrivate::SimpleList parserStatus; @@ -245,9 +157,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::CreateObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *o = types.at(instr.create.type).createInstance(QmlContext::activeContext()); if (!o) { if(types.at(instr.create.type).component) @@ -271,9 +180,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::SetId: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QmlContext *ctxt = QmlContext::activeContext(); @@ -287,9 +193,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::SetDefault: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QmlContext::activeContext()->addDefaultObject(target); } @@ -297,9 +200,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::CreateComponent: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top()); stack.push(qcomp); ii += instr.createComponent.count; @@ -308,9 +208,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::StoreMetaObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); new QmlVMEMetaObject(target, synthesizedMetaObjects.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, comp); } @@ -318,9 +215,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::StoreVariant: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; // XXX - can be more efficient @@ -333,9 +227,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::StoreString: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; a[0] = (void *)&primitives.at(instr.storeString.value); @@ -346,9 +237,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::StoreFloat: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); float f = instr.storeFloat.value; void *a[1]; @@ -360,9 +248,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in case QmlInstruction::StoreDouble: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); double d = instr.storeDouble.value; void *a[1]; @@ -374,9 +259,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreBool: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; a[0] = (void *)&instr.storeBool.value; @@ -387,9 +269,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreInteger: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; a[0] = (void *)&instr.storeInteger.value; @@ -400,9 +279,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreColor: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QColor c = QColor::fromRgba(instr.storeColor.value); @@ -414,9 +290,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreDate: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QDate d = QDate::fromJulianDay(instr.storeDate.value); @@ -428,9 +301,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreTime: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - //QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QTime t; @@ -446,9 +316,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreDateTime: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - //QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QTime t; @@ -465,9 +332,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StorePoint: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex), @@ -480,9 +344,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StorePointF: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QPointF p(floatData.at(instr.storeRealPair.valueIndex), @@ -495,9 +356,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreSize: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex), @@ -510,9 +368,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreSizeF: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QSizeF s(floatData.at(instr.storeRealPair.valueIndex), @@ -525,9 +380,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreRect: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - //QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QRect r = QRectF(floatData.at(instr.storeRect.valueIndex), @@ -542,9 +394,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreRectF: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - //QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; QRectF r(floatData.at(instr.storeRect.valueIndex), @@ -559,9 +408,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *assignObj = stack.pop(); QObject *target = stack.top(); @@ -597,9 +443,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::AssignSignalObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif // XXX optimize QObject *assign = stack.pop(); @@ -629,9 +472,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreSignal: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); // XXX scope QMetaMethod signal = @@ -647,9 +487,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::BeginObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QmlParserStatus *status = reinterpret_cast(reinterpret_cast(target) + instr.begin.castValue); parserStatus.append(status); @@ -661,9 +498,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::CompleteObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QmlParserStatus *status = reinterpret_cast(reinterpret_cast(target) + instr.complete.castValue); status->classComplete(); @@ -672,9 +506,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::PushProperty: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QmlMetaProperty mp(target, instr.pushProperty.property, QmlMetaProperty::Object); @@ -684,9 +515,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreCompiledBinding: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QObject *context = stack.at(stack.count() - 1 - instr.assignBinding.context); @@ -708,9 +536,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreBinding: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QObject *context = stack.at(stack.count() - 1 - instr.assignBinding.context); @@ -732,9 +557,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreValueSource: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *assign = stack.pop(); QmlPropertyValueSource *vs = static_cast(assign); @@ -746,9 +568,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreObjectQmlList: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *assign = stack.pop(); const ListInstance &list = qliststack.top(); @@ -759,9 +578,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::StoreObjectQList: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *assign = stack.pop(); const ListInstance &list = qliststack.top(); @@ -772,9 +588,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::AssignObjectList: { // This is only used for assigning interfaces -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *assign = stack.pop(); const ListInstance &list = qliststack.top(); @@ -840,9 +653,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::FetchAttached: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target); @@ -856,9 +666,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::FetchQmlList: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; @@ -877,9 +684,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::FetchQList: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); void *a[1]; @@ -898,9 +702,6 @@ case QmlInstruction::StoreDouble: case QmlInstruction::FetchObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif QObject *target = stack.top(); QObject *obj = 0; @@ -930,28 +731,18 @@ case QmlInstruction::StoreDouble: case QmlInstruction::PopQList: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif qliststack.pop(); } break; case QmlInstruction::PopFetchedObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif stack.pop(); } break; case QmlInstruction::StoreStackObject: { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif - const QmlMetaProperty &prop = pushedProperties.at(instr.assignStackObject.property); QObject *obj = savedObjects[instr.assignStackObject.object]; -- cgit v0.12 From 5419a744c830003cb2e93e5de731e684a67930a2 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 10 Jun 2009 15:59:41 +1000 Subject: Ideas for full module support. --- doc/src/declarative/modules.qdoc | 94 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/doc/src/declarative/modules.qdoc b/doc/src/declarative/modules.qdoc index 5933223..d84ad46 100644 --- a/doc/src/declarative/modules.qdoc +++ b/doc/src/declarative/modules.qdoc @@ -20,3 +20,97 @@ the component issuing the import. The import statement cannot be used by remote content. */ + +/* + +Ideas for full module support.... + + +* Modularity within applications + +This is the currently-supported mechanism. + +By using the "import" statement, a subdirectory of types can be added to the +empty namespace. Alternatively, a type in a subdirectory can be referenced +explicitly: + + ./SubModule1/Type1.qml + ./SubModule2/Type1.qml + import "SubModule1" + Type1 { ... } + SubModule2.Type1 { ... } + + +* System-installed modules (dependencies) + +To use system-installed modules, the dependency must be explicitly stated +using the "require" statement. Types in required modules must still be +explicitly qualified. Dependencies cannot be added to the empty namespace. + + QMLPATH=/opt/Nokia/qml:/usr/share/lib/qml + /opt/Nokia/qml/Module1/Type1.qml + /usr/share/lib/qml/Module1/Type1.qml + require "Module1" + Module1.Type1 { ... } + + +* Grouping of components within application modules + +Sub-sub directories allow further grouping of types. + + ./SubModule1/Group1/*.qml + ./SubModule1/Group2/*.qml + + SubModule1.Group1.Type1 { ... } + SubModule1.Group1.Type2 { ... } + SubModule1.Group2.Type1 { ... } + SubModule1.Group2.Type2 { ... } + + import "SubModule1/Group1" + Type1 { ... } + + import "SubModule1" + Group1.Type1 { ... } + + +* Grouping of components within system-installed modules + +System-installed types may also be grouped into types. The hierarchy is a +global namespace, so such grouping is recommended to reduce clashes. + + /opt/Nokia/qml/Module1/Group1/*.qml + /opt/Nokia/qml/Module1/Group2/*.qml + + require "Module1" + Module1.Group1.Type1 { ... } + Module1.Group1.Type2 { ... } + Module1.Group2.Type1 { ... } + Module1.Group2.Type2 { ... } + + require "Module1/Group1" + Group1.Type1 { ... } + + // Alternative syntax + /opt/qml/com/nokia/qml/Module1/Group1/*.qml + require "com.nokia.qml.Module1.Group1" + Group1.Type1 { ... } + + +* Private sub-components + +Directories begining with _ cannot be referenced except by types in the +directory immediately containing it. + + /opt/Nokia/qml/Module1/_private/Type1.qml + ./SubModule1/_private/Type1.qml + + SubModule1._private.Type1 { ... } // Not allowed + import "SubModule1._private" // Not allowed + require "SubModule1._private" // Not allowed + require "SubModule1" + Module1._private.Type1 { ... } // Not allowed + + import "_private" // allowed + Type1 { ... } + +*/ -- cgit v0.12 From 73fa8dd86f14ab161c84fa9224cd4335f352ba75 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Wed, 10 Jun 2009 16:10:21 +1000 Subject: Fix license headers for QStringBuilder. Only release branches are allowed to have the Commercial usage header. All other branches must have the No Commercial Usage header. Reviewed-by: Trust Me --- src/corelib/tools/qstringbuilder.cpp | 12 ++++++------ src/corelib/tools/qstringbuilder.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp index 03d8160..740deb4 100644 --- a/src/corelib/tools/qstringbuilder.cpp +++ b/src/corelib/tools/qstringbuilder.cpp @@ -3,14 +3,14 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 2c31476..30a7c67 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -3,14 +3,14 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 -- cgit v0.12 From df4763878d756fe1f5bcfe6b7dd8cf91cdd091e1 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 10 Jun 2009 16:11:05 +1000 Subject: doc --- doc/src/declarative/modules.qdoc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/src/declarative/modules.qdoc b/doc/src/declarative/modules.qdoc index d84ad46..194be40 100644 --- a/doc/src/declarative/modules.qdoc +++ b/doc/src/declarative/modules.qdoc @@ -32,10 +32,15 @@ This is the currently-supported mechanism. By using the "import" statement, a subdirectory of types can be added to the empty namespace. Alternatively, a type in a subdirectory can be referenced -explicitly: +explicitly. + +So, given these files: ./SubModule1/Type1.qml ./SubModule2/Type1.qml + +This is valid QML: + import "SubModule1" Type1 { ... } SubModule2.Type1 { ... } @@ -50,6 +55,7 @@ explicitly qualified. Dependencies cannot be added to the empty namespace. QMLPATH=/opt/Nokia/qml:/usr/share/lib/qml /opt/Nokia/qml/Module1/Type1.qml /usr/share/lib/qml/Module1/Type1.qml + require "Module1" Module1.Type1 { ... } -- cgit v0.12 From b2edf6ee037decf53c7d2698863ba63742317acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 10 Jun 2009 10:21:19 +0200 Subject: Fixed clipping bug in raster paint engine causing rendering artifacts. The artifacts were visible in the mainwindow demo when dragging the top toolbar separator left and right. We need to check that rect clipping is actually activated before we compare the new clip rect with the old, otherwise the clip type and clip bound flags won't get updated. --- src/gui/painting/qpaintengine_raster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 0810bb9..7ed2dfd 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -4311,7 +4311,7 @@ QClipData::QClipData(int height) clipSpanHeight = height; m_clipLines = 0; - allocated = height; + allocated = 0; m_spans = 0; xmin = xmax = ymin = ymax = 0; count = 0; @@ -4479,7 +4479,7 @@ void QClipData::fixup() */ void QClipData::setClipRect(const QRect &rect) { - if (rect == clipRect) + if (hasRectClip && rect == clipRect) return; // qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect; -- cgit v0.12 From 52ee3d6525e2b271fc50103001f9d71d681b6afe Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 18:29:12 +1000 Subject: Source location isn't needed for compiled bindings --- src/declarative/qml/qmlvme.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index cdc6a66..3a66c69 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -541,7 +541,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in QFx_setParent_noEvent(bind, target); bind->setTarget(mp); - bind->setSourceLocation(comp->url, instr.line); } break; -- cgit v0.12 From f0f12f3d1ad2041c57095edaa7683c5d3599a3e6 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Wed, 10 Jun 2009 18:47:49 +1000 Subject: Fix some incorrect license headers. The MODULE placeholder shouldn't be used anymore, and neither should the old Trolltech license header. Reviewed-by: Trust Me --- doc/src/diagrams/programs/easingcurve/main.cpp | 36 +++++++++++++++++++++-- src/gui/math3d/qgenericmatrix.cpp | 2 +- src/gui/math3d/qgenericmatrix.h | 2 +- src/gui/math3d/qmatrix4x4.cpp | 2 +- src/gui/math3d/qmatrix4x4.h | 2 +- src/gui/math3d/qquaternion.cpp | 2 +- src/gui/math3d/qquaternion.h | 2 +- src/gui/math3d/qvector2d.cpp | 2 +- src/gui/math3d/qvector2d.h | 2 +- src/gui/math3d/qvector3d.cpp | 2 +- src/gui/math3d/qvector3d.h | 2 +- src/gui/math3d/qvector4d.cpp | 2 +- src/gui/math3d/qvector4d.h | 2 +- tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp | 2 +- tests/auto/math3d/qquaternion/tst_qquaternion.cpp | 2 +- tests/auto/math3d/qvectornd/tst_qvectornd.cpp | 2 +- tests/auto/math3d/shared/math3dincludes.h | 2 +- 17 files changed, 49 insertions(+), 19 deletions(-) diff --git a/doc/src/diagrams/programs/easingcurve/main.cpp b/doc/src/diagrams/programs/easingcurve/main.cpp index 98e9d37..8d399a3 100644 --- a/doc/src/diagrams/programs/easingcurve/main.cpp +++ b/doc/src/diagrams/programs/easingcurve/main.cpp @@ -1,11 +1,41 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $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$ ** ****************************************************************************/ diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp index 6ecd878..19a0f6e 100644 --- a/src/gui/math3d/qgenericmatrix.cpp +++ b/src/gui/math3d/qgenericmatrix.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index b4d3707..330ded2 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 8ef4da3..a69b9df 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index ba7f67f..da1bcba 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index 96659ea..03f626a 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index c05c641..b17cf73 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp index c3aaa42..df2519d 100644 --- a/src/gui/math3d/qvector2d.cpp +++ b/src/gui/math3d/qvector2d.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h index b027df4..2be0a11 100644 --- a/src/gui/math3d/qvector2d.h +++ b/src/gui/math3d/qvector2d.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index c83cd60..a5f5c5b 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h index 02873f2..480667a 100644 --- a/src/gui/math3d/qvector3d.h +++ b/src/gui/math3d/qvector3d.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index 010fa53..c5124e2 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h index 8e673f3..e38f4e5 100644 --- a/src/gui/math3d/qvector4d.h +++ b/src/gui/math3d/qvector4d.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp index 4d51e89..dd3e396 100644 --- a/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp +++ b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp index f25f858..5d70e4d 100644 --- a/tests/auto/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp index a092fb0..f7d2411 100644 --- a/tests/auto/math3d/qvectornd/tst_qvectornd.cpp +++ b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/math3d/shared/math3dincludes.h b/tests/auto/math3d/shared/math3dincludes.h index 1ac0c08..a77090b 100644 --- a/tests/auto/math3d/shared/math3dincludes.h +++ b/tests/auto/math3d/shared/math3dincludes.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage -- cgit v0.12 From d0d89a49a7c1e5f302a8606448fc5defdb327a25 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 18:51:21 +1000 Subject: Minor cleanups --- src/declarative/qml/qmlbindablevalue.cpp | 28 +++--- src/declarative/qml/qmlmetaproperty.cpp | 162 +------------------------------ 2 files changed, 13 insertions(+), 177 deletions(-) diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp index de01387..d111bbb 100644 --- a/src/declarative/qml/qmlbindablevalue.cpp +++ b/src/declarative/qml/qmlbindablevalue.cpp @@ -179,34 +179,29 @@ void QmlBindableValue::update() } } else if (d->property.propertyCategory() == QmlMetaProperty::Bindable) { - // NOTE: We assume that only core properties can have - // propertyType == Bindable int idx = d->property.coreIndex(); Q_ASSERT(idx != -1); void *a[1]; QmlBindableValue *t = this; a[0] = (void *)&t; - d->property.object()->qt_metacall(QMetaObject::WriteProperty, - idx, a); + QMetaObject::metacall(d->property.object(), + QMetaObject::WriteProperty, + idx, a); } else if (d->property.propertyCategory() == QmlMetaProperty::Object) { QVariant value = this->value(); - if ((int)value.type() != qMetaTypeId()) { - if (scriptWarnings()) { - if (!value.isValid()) { - qWarning() << "QmlBindableValue: Unable to assign invalid value to object property"; - } else { - qWarning() << "QmlBindableValue: Unable to assign non-object to object property"; - } - } + + QObject *obj = QmlMetaType::toQObject(value); + + if (!obj) { + if (scriptWarnings()) + qWarning() << "QmlBindableValue: Unable to assign non-object to object property"; return; } - // NOTE: This assumes a cast to QObject does not alter the - // object pointer - QObject *obj = *(QObject **)value.data(); + // XXX This isn't type safe // NOTE: We assume that only core properties can have // propertyType == Object @@ -220,7 +215,8 @@ void QmlBindableValue::update() } else if (d->property.propertyCategory() == QmlMetaProperty::Normal) { QVariant value = this->value(); - if (d->property.propertyType() == QVariant::Url && value.canConvert(QVariant::String) && !value.isNull()) { + if (d->property.propertyType() == QVariant::Url && + value.canConvert(QVariant::String) && !value.isNull()) { // Must resolve first value.setValue(context()->resolvedUrl(value.toString())); } diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 4f39ebc..5cddf3d 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -813,168 +813,8 @@ void QmlMetaProperty::write(const QVariant &value) const } else if (prop.name()) { - if (prop.isEnumType()) { - QVariant v = value; - if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles - double integral; - double fractional = modf(value.toDouble(), &integral); - if (qFuzzyCompare(fractional, (double)0.0)) - v.convert(QVariant::Int); - } - prop.write(object(), v); - } else { - if (!value.isValid()) - return; - - int t = propertyType(); - int vt = value.type(); - - if (vt == t || - value.userType() == t) { - - void *a[1]; - a[0] = (void *)value.constData(); - QMetaObject::metacall(object(), QMetaObject::WriteProperty, d->coreIdx, a); - - } else if (qMetaTypeId() == t) { - - prop.write(object(), value); - - } else if (propertyCategory() == Object) { - - QObject *o = QmlMetaType::toQObject(value); - if (o) - prop.write(object(), QmlMetaType::fromObject(o, propertyType())); - - } else if (propertyCategory() == List) { - - int listType = QmlMetaType::listType(t); - if (value.userType() == qMetaTypeId >()) { - const QList &list = - qvariant_cast >(value); - QVariant listVar = prop.read(object()); - QmlMetaType::clear(listVar); - for (int ii = 0; ii < list.count(); ++ii) { - QVariant v = QmlMetaType::fromObject(list.at(ii), listType); - QmlMetaType::append(listVar, v); - } - - } else if (vt == listType || - value.userType() == listType) { - QVariant listVar = prop.read(object()); - if (!QmlMetaType::append(listVar, value)) { - qWarning() << "QmlMetaProperty: Unable to assign object to list"; - } - } - } else if (propertyCategory() == QmlList) { - // XXX - optimize! - QVariant list = prop.read(object()); - QmlPrivate::ListInterface *li = - *(QmlPrivate::ListInterface **)list.constData(); - - int type = li->type(); - - if (QObject *obj = QmlMetaType::toQObject(value)) { - const QMetaObject *mo = - QmlMetaType::rawMetaObjectForType(type); - - const QMetaObject *objMo = obj->metaObject(); - bool found = false; - while(!found && objMo) { - if (objMo == mo) - found = true; - else - objMo = objMo->superClass(); - } - - if (!found) { - qWarning() << "Unable to assign object to list"; - return; - } - - // NOTE: This assumes a cast to QObject does not alter - // the object pointer - void *d = (void *)&obj; - li->append(d); - } - } else if (propertyCategory() == Normal) { - - switch(t) { - case QVariant::Double: - { - double dd; - bool found = true; - if (vt == QVariant::Int) { - dd = value.toInt(); - } else if (vt == QVariant::UInt) { - dd = value.toUInt(); - } else { - found = false; - } - - if (found) { - void *a[1]; - a[0] = ⅆ - QMetaObject::metacall(object(), - QMetaObject::WriteProperty, - d->coreIdx, a); - return; - } - } - break; - - case QVariant::Int: - { - int i; - bool found = true; - if (vt == QVariant::Double) { - i = (int)value.toDouble(); - } else if (vt == QVariant::UInt) { - i = (int)value.toUInt(); - } else { - found = false; - } - - if (found) { - void *a[1]; - a[0] = &i; - QMetaObject::metacall(object(), - QMetaObject::WriteProperty, - d->coreIdx, a); - return; - } - } - break; - - case QVariant::String: - { - QString s; - bool found = true; - if (vt == QVariant::ByteArray) { - s = QLatin1String(value.toByteArray()); - } else { - found = false; - } - - if (found) { - void *a[1]; - a[0] = &s; - QMetaObject::metacall(object(), - QMetaObject::WriteProperty, - d->coreIdx, a); - return; - } - } - break; + d->writeValueProperty(value); - - default: - break; - } - prop.write(object(), value); - } - - } } } -- cgit v0.12 From 8b75843c44df306cf5003980f4563d0759dffe7e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 10 Jun 2009 10:54:11 +0200 Subject: Fix tst_QGraphicsProxyWidget::scrollUpdate test, wrong test. It should not be necessary to adjust the expose rectangle by 1 in all directions; the expose has already been adjusted by the scene and view. Reviewed-by: bnilsen --- tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index d856024..fa0e035 100644 --- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -1487,7 +1487,7 @@ void tst_QGraphicsProxyWidget::scrollUpdate() QVector() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10)); QCOMPARE(widget->npaints, 2); QCOMPARE(widget->paintEventRegion.rects(), - QVector() << QRect(0, 0, 200, 13) << QRect(0, 13, 103, 10)); + QVector() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10)); } void tst_QGraphicsProxyWidget::setWidget_simple() -- cgit v0.12 From f6f89890d032317d16cda7726b4d9f97c12d661d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 19:12:41 +1000 Subject: Simplify QmlBindableValue by using the logic already present in QmlMetaProperty --- src/declarative/qml/qmlbindablevalue.cpp | 84 +--------- src/declarative/qml/qmlmetaproperty.cpp | 274 +++++++++++++++++-------------- 2 files changed, 151 insertions(+), 207 deletions(-) diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp index d111bbb..293c3a8 100644 --- a/src/declarative/qml/qmlbindablevalue.cpp +++ b/src/declarative/qml/qmlbindablevalue.cpp @@ -125,59 +125,7 @@ void QmlBindableValue::update() if (!d->updating) { d->updating = true; - if (d->property.propertyCategory() == QmlMetaProperty::List) { - QVariant value = this->value(); - int listType = QmlMetaType::listType(d->property.propertyType()); - - if (value.userType() == qMetaTypeId >()) { - const QList &list = - qvariant_cast >(value); - QVariant listVar = d->property.read(); - QmlMetaType::clear(listVar); - for (int ii = 0; ii < list.count(); ++ii) { - QVariant v = QmlMetaType::fromObject(list.at(ii), listType); - QmlMetaType::append(listVar, v); - } - - } else if (value.type() == uint(listType) || - value.userType() == listType) { - QVariant listVar = d->property.read(); - QmlMetaType::clear(listVar); - QmlMetaType::append(listVar, value); - } - } else if (d->property.propertyCategory() == QmlMetaProperty::QmlList) { - // XXX - optimize! - QVariant value = this->value(); - QVariant list = d->property.read(); - QmlPrivate::ListInterface *li = - *(QmlPrivate::ListInterface **)list.constData(); - - int type = li->type(); - - if (QObject *obj = QmlMetaType::toQObject(value)) { - const QMetaObject *mo = - QmlMetaType::rawMetaObjectForType(type); - - const QMetaObject *objMo = obj->metaObject(); - bool found = false; - while(!found && objMo) { - if (objMo == mo) - found = true; - else - objMo = objMo->superClass(); - } - - if (!found) { - qWarning() << "Unable to assign object to list"; - return; - } - - // NOTE: This assumes a cast to QObject does not alter - // the object pointer - void *d = (void *)&obj; - li->append(d); - } - } else if (d->property.propertyCategory() == QmlMetaProperty::Bindable) { + if (d->property.propertyCategory() == QmlMetaProperty::Bindable) { int idx = d->property.coreIndex(); Q_ASSERT(idx != -1); @@ -189,37 +137,13 @@ void QmlBindableValue::update() QMetaObject::WriteProperty, idx, a); - } else if (d->property.propertyCategory() == QmlMetaProperty::Object) { + } else { QVariant value = this->value(); - - QObject *obj = QmlMetaType::toQObject(value); - - if (!obj) { - if (scriptWarnings()) - qWarning() << "QmlBindableValue: Unable to assign non-object to object property"; - return; - } - - // XXX This isn't type safe - - // NOTE: We assume that only core properties can have - // propertyType == Object - int idx = d->property.coreIndex(); - Q_ASSERT(idx != -1); - - void *a[1]; - a[0] = (void *)&obj; - d->property.object()->qt_metacall(QMetaObject::WriteProperty, - idx, a); - - } else if (d->property.propertyCategory() == QmlMetaProperty::Normal) { - QVariant value = this->value(); if (d->property.propertyType() == QVariant::Url && - value.canConvert(QVariant::String) && !value.isNull()) { - // Must resolve first + value.canConvert(QVariant::String) && !value.isNull()) value.setValue(context()->resolvedUrl(value.toString())); - } + d->property.write(value); } diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 5cddf3d..a152807 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -646,159 +646,179 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value) v.convert(QVariant::Int); } prop.write(object, v); - } else { - if (!value.isValid()) + return; + } + + if (!value.isValid()) + return; + + int t = propertyType(); + int vt = value.userType(); + int category = propertyCategory(); + + if (vt == t) { + + void *a[1]; + a[0] = (void *)value.constData(); + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + + } else if (qMetaTypeId() == t) { + + prop.write(object, value); + + } else if (category == QmlMetaProperty::Object) { + + QObject *o = QmlMetaType::toQObject(value); + + if (!o) return; - int t = propertyType(); - int vt = value.type(); + const QMetaObject *valMo = o->metaObject(); + const QMetaObject *propMo = QmlMetaType::rawMetaObjectForType(t); - if (vt == t || - value.userType() == t) { + while (valMo) { + if (valMo == propMo) + break; + valMo = valMo->superClass(); + } - void *a[1]; - a[0] = (void *)value.constData(); - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + if (valMo) { - } else if (qMetaTypeId() == t) { + void *args[] = { &o, 0 }; + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, + args); - prop.write(object, value); + } - } else if (propertyCategory() == QmlMetaProperty::Object) { + } else if (category == QmlMetaProperty::List) { - QObject *o = QmlMetaType::toQObject(value); - if (o) - prop.write(object, QmlMetaType::fromObject(o, propertyType())); + int listType = QmlMetaType::listType(t); - } else if (propertyCategory() == QmlMetaProperty::List) { + if (value.userType() == qMetaTypeId >()) { + const QList &list = + qvariant_cast >(value); + QVariant listVar = prop.read(object); + QmlMetaType::clear(listVar); + for (int ii = 0; ii < list.count(); ++ii) { + QVariant v = QmlMetaType::fromObject(list.at(ii), listType); + QmlMetaType::append(listVar, v); + } - int listType = QmlMetaType::listType(t); - if (value.userType() == qMetaTypeId >()) { - const QList &list = - qvariant_cast >(value); - QVariant listVar = prop.read(object); - QmlMetaType::clear(listVar); - for (int ii = 0; ii < list.count(); ++ii) { - QVariant v = QmlMetaType::fromObject(list.at(ii), listType); - QmlMetaType::append(listVar, v); - } + } else if (vt == listType || + value.userType() == listType) { + QVariant listVar = prop.read(object); + QmlMetaType::clear(listVar); + QmlMetaType::append(listVar, value); + } + } else if (category == QmlMetaProperty::QmlList) { + + // XXX - optimize! + QVariant list = prop.read(object); + QmlPrivate::ListInterface *li = + *(QmlPrivate::ListInterface **)list.constData(); + + int type = li->type(); + + if (QObject *obj = QmlMetaType::toQObject(value)) { + const QMetaObject *mo = + QmlMetaType::rawMetaObjectForType(type); + + const QMetaObject *objMo = obj->metaObject(); + bool found = false; + while(!found && objMo) { + if (objMo == mo) + found = true; + else + objMo = objMo->superClass(); + } - } else if (vt == listType || - value.userType() == listType) { - QVariant listVar = prop.read(object); - if (!QmlMetaType::append(listVar, value)) { - qWarning() << "QmlMetaProperty: Unable to assign object to list"; - } + if (!found) { + qWarning() << "Unable to assign object to list"; + return; } - } else if (propertyCategory() == QmlMetaProperty::QmlList) { - // XXX - optimize! - QVariant list = prop.read(object); - QmlPrivate::ListInterface *li = - *(QmlPrivate::ListInterface **)list.constData(); - - int type = li->type(); - - if (QObject *obj = QmlMetaType::toQObject(value)) { - const QMetaObject *mo = - QmlMetaType::rawMetaObjectForType(type); - - const QMetaObject *objMo = obj->metaObject(); - bool found = false; - while(!found && objMo) { - if (objMo == mo) - found = true; - else - objMo = objMo->superClass(); + + // NOTE: This assumes a cast to QObject does not alter + // the object pointer + void *d = (void *)&obj; + li->append(d); + } + } else if (category == QmlMetaProperty::Normal) { + + switch(t) { + case QVariant::Double: + { + double d; + bool found = true; + if (vt == QVariant::Int) { + d = value.toInt(); + } else if (vt == QVariant::UInt) { + d = value.toUInt(); + } else { + found = false; } - if (!found) { - qWarning() << "Unable to assign object to list"; + if (found) { + void *a[1]; + a[0] = &d; + QMetaObject::metacall(object, + QMetaObject::WriteProperty, + coreIdx, a); return; } - - // NOTE: This assumes a cast to QObject does not alter - // the object pointer - void *d = (void *)&obj; - li->append(d); } - } else if (propertyCategory() == QmlMetaProperty::Normal) { - - switch(t) { - case QVariant::Double: - { - double d; - bool found = true; - if (vt == QVariant::Int) { - d = value.toInt(); - } else if (vt == QVariant::UInt) { - d = value.toUInt(); - } else { - found = false; - } - - if (found) { - void *a[1]; - a[0] = &d; - QMetaObject::metacall(object, - QMetaObject::WriteProperty, - coreIdx, a); - return; - } + break; + + case QVariant::Int: + { + int i; + bool found = true; + if (vt == QVariant::Double) { + i = (int)value.toDouble(); + } else if (vt == QVariant::UInt) { + i = (int)value.toUInt(); + } else { + found = false; } - break; - case QVariant::Int: - { - int i; - bool found = true; - if (vt == QVariant::Double) { - i = (int)value.toDouble(); - } else if (vt == QVariant::UInt) { - i = (int)value.toUInt(); - } else { - found = false; - } - - if (found) { - void *a[1]; - a[0] = &i; - QMetaObject::metacall(object, - QMetaObject::WriteProperty, - coreIdx, a); - return; - } + if (found) { + void *a[1]; + a[0] = &i; + QMetaObject::metacall(object, + QMetaObject::WriteProperty, + coreIdx, a); + return; + } + } + break; + + case QVariant::String: + { + QString s; + bool found = true; + if (vt == QVariant::ByteArray) { + s = QLatin1String(value.toByteArray()); + } else { + found = false; } - break; - case QVariant::String: - { - QString s; - bool found = true; - if (vt == QVariant::ByteArray) { - s = QLatin1String(value.toByteArray()); - } else { - found = false; - } - - if (found) { - void *a[1]; - a[0] = &s; - QMetaObject::metacall(object, - QMetaObject::WriteProperty, - coreIdx, a); - return; - } + if (found) { + void *a[1]; + a[0] = &s; + QMetaObject::metacall(object, + QMetaObject::WriteProperty, + coreIdx, a); + return; } - break; + } + break; - default: - break; - } - prop.write(object, value); + default: + break; } - + prop.write(object, value); } + } /*! -- cgit v0.12 From 0bae9bea91f4fcf087edd6d5b2af5c9e1658fb4a Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 10 Jun 2009 19:16:35 +1000 Subject: Remove dead code --- src/declarative/qml/qmlbindablevalue.cpp | 6 ------ src/declarative/qml/qmlbindablevalue.h | 1 - 2 files changed, 7 deletions(-) diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp index 293c3a8..e1b6961 100644 --- a/src/declarative/qml/qmlbindablevalue.cpp +++ b/src/declarative/qml/qmlbindablevalue.cpp @@ -58,12 +58,6 @@ QmlBindableValuePrivate::QmlBindableValuePrivate() } QML_DEFINE_NOCREATE_TYPE(QmlBindableValue); -QmlBindableValue::QmlBindableValue(QObject *parent) -: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent) -{ - qFatal("QmlBindableValue: Default constructor not supported"); -} - QmlBindableValue::QmlBindableValue(void *data, QmlRefCount *rc, QObject *obj, QObject *parent) : QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(QmlContext::activeContext(), data, rc, obj) { diff --git a/src/declarative/qml/qmlbindablevalue.h b/src/declarative/qml/qmlbindablevalue.h index 71a7051..f54481a 100644 --- a/src/declarative/qml/qmlbindablevalue.h +++ b/src/declarative/qml/qmlbindablevalue.h @@ -62,7 +62,6 @@ class Q_DECLARATIVE_EXPORT QmlBindableValue : public QmlPropertyValueSource, { Q_OBJECT public: - QmlBindableValue(QObject *parent); QmlBindableValue(const QString &, QObject *, QObject *parent=0); QmlBindableValue(void *, QmlRefCount *, QObject *, QObject *parent); ~QmlBindableValue(); -- cgit v0.12 From c0bbe44ab6290dee088138c01724779026d2c033 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 10 Jun 2009 12:02:29 +0200 Subject: Changed the QML parser and the AST to store the position of comma tokens of QML arrays. Also exposed these positions through the QML DOM. --- src/declarative/qml/parser/javascript.g | 9 +++--- src/declarative/qml/parser/javascriptast.cpp | 12 ++++++- src/declarative/qml/parser/javascriptast_p.h | 37 ++++++++++++++++++++-- src/declarative/qml/parser/javascriptastfwd_p.h | 1 + .../qml/parser/javascriptastvisitor_p.h | 2 ++ src/declarative/qml/parser/javascriptparser.cpp | 9 +++--- src/declarative/qml/parser/javascriptparser_p.h | 1 + src/declarative/qml/qmldom.cpp | 10 ++++++ src/declarative/qml/qmldom.h | 2 ++ src/declarative/qml/qmlparser_p.h | 1 + src/declarative/qml/qmlscriptparser.cpp | 18 ++++++++++- 11 files changed, 90 insertions(+), 12 deletions(-) diff --git a/src/declarative/qml/parser/javascript.g b/src/declarative/qml/parser/javascript.g index 8cabeea..884d814 100644 --- a/src/declarative/qml/parser/javascript.g +++ b/src/declarative/qml/parser/javascript.g @@ -568,15 +568,16 @@ case $rule_number: { UiArrayMemberList: UiObjectDefinition ; /. case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); } break; ./ UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; /. case $rule_number: { - AST::UiObjectMemberList *node = makeAstNode (driver->nodePool(), - sym(1).UiObjectMemberList, sym(3).UiObjectMember); + AST::UiArrayMemberList *node = makeAstNode (driver->nodePool(), + sym(1).UiArrayMemberList, sym(3).UiObjectMember); + node->commaToken = loc(2); sym(1).Node = node; } break; ./ @@ -616,7 +617,7 @@ UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; /. case $rule_number: { AST::UiArrayBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(4).UiObjectMemberList->finish()); + sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); node->rbracketToken = loc(5); diff --git a/src/declarative/qml/parser/javascriptast.cpp b/src/declarative/qml/parser/javascriptast.cpp index 130229b..ada19d5 100644 --- a/src/declarative/qml/parser/javascriptast.cpp +++ b/src/declarative/qml/parser/javascriptast.cpp @@ -893,7 +893,7 @@ void UiArrayBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { acceptChild(qualifiedId, visitor); - for (UiObjectMemberList *it = members; it; it = it->next) + for (UiArrayMemberList *it = members; it; it = it->next) acceptChild(it->member, visitor); } @@ -910,6 +910,16 @@ void UiObjectMemberList::accept0(Visitor *visitor) visitor->endVisit(this); } +void UiArrayMemberList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiArrayMemberList *it = this; it; it = it->next) + acceptChild(it->member, visitor); + } + + visitor->endVisit(this); +} + void UiQualifiedId::accept0(Visitor *visitor) { if (visitor->visit(this)) { diff --git a/src/declarative/qml/parser/javascriptast_p.h b/src/declarative/qml/parser/javascriptast_p.h index 23d59e5..8c1e2bc 100644 --- a/src/declarative/qml/parser/javascriptast_p.h +++ b/src/declarative/qml/parser/javascriptast_p.h @@ -207,6 +207,7 @@ public: Kind_UiObjectDefinition, Kind_UiObjectInitializer, Kind_UiObjectMemberList, + Kind_UiArrayMemberList, Kind_UiProgram, Kind_UiPublicMember, Kind_UiQualifiedId, @@ -2301,6 +2302,38 @@ public: UiObjectMember *member; }; +class UiArrayMemberList: public Node +{ +public: + JAVASCRIPT_DECLARE_AST_NODE(UiArrayMemberList) + + UiArrayMemberList(UiObjectMember *member) + : next(this), member(member) + { kind = K; } + + UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member) + : member(member) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual void accept0(Visitor *visitor); + + UiArrayMemberList *finish() + { + UiArrayMemberList *head = next; + next = 0; + return head; + } + +// attributes + UiArrayMemberList *next; + UiObjectMember *member; + SourceLocation commaToken; +}; + class UiObjectInitializer: public Node { public: @@ -2481,7 +2514,7 @@ public: JAVASCRIPT_DECLARE_AST_NODE(UiArrayBinding) UiArrayBinding(UiQualifiedId *qualifiedId, - UiObjectMemberList *members) + UiArrayMemberList *members) : qualifiedId(qualifiedId), members(members) { kind = K; } @@ -2496,7 +2529,7 @@ public: // attributes UiQualifiedId *qualifiedId; - UiObjectMemberList *members; + UiArrayMemberList *members; SourceLocation colonToken; SourceLocation lbracketToken; SourceLocation rbracketToken; diff --git a/src/declarative/qml/parser/javascriptastfwd_p.h b/src/declarative/qml/parser/javascriptastfwd_p.h index 822a2d7..23270e5 100644 --- a/src/declarative/qml/parser/javascriptastfwd_p.h +++ b/src/declarative/qml/parser/javascriptastfwd_p.h @@ -174,6 +174,7 @@ class UiSourceElement; class UiArrayBinding; class UiObjectMember; class UiObjectMemberList; +class UiArrayMemberList; class UiQualifiedId; } } // namespace AST diff --git a/src/declarative/qml/parser/javascriptastvisitor_p.h b/src/declarative/qml/parser/javascriptastvisitor_p.h index 81df364..7c73e43 100644 --- a/src/declarative/qml/parser/javascriptastvisitor_p.h +++ b/src/declarative/qml/parser/javascriptastvisitor_p.h @@ -80,6 +80,7 @@ public: virtual bool visit(UiScriptBinding *) { return true; } virtual bool visit(UiArrayBinding *) { return true; } virtual bool visit(UiObjectMemberList *) { return true; } + virtual bool visit(UiArrayMemberList *) { return true; } virtual bool visit(UiQualifiedId *) { return true; } virtual void endVisit(UiProgram *) {} @@ -93,6 +94,7 @@ public: virtual void endVisit(UiScriptBinding *) {} virtual void endVisit(UiArrayBinding *) {} virtual void endVisit(UiObjectMemberList *) {} + virtual void endVisit(UiArrayMemberList *) {} virtual void endVisit(UiQualifiedId *) {} // JavaScript diff --git a/src/declarative/qml/parser/javascriptparser.cpp b/src/declarative/qml/parser/javascriptparser.cpp index 34ecd0e..bbffc4f 100644 --- a/src/declarative/qml/parser/javascriptparser.cpp +++ b/src/declarative/qml/parser/javascriptparser.cpp @@ -239,12 +239,13 @@ case 10: { } break; case 11: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); } break; case 12: { - AST::UiObjectMemberList *node = makeAstNode (driver->nodePool(), - sym(1).UiObjectMemberList, sym(3).UiObjectMember); + AST::UiArrayMemberList *node = makeAstNode (driver->nodePool(), + sym(1).UiArrayMemberList, sym(3).UiObjectMember); + node->commaToken = loc(2); sym(1).Node = node; } break; @@ -270,7 +271,7 @@ case 15: { case 17: { AST::UiArrayBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(4).UiObjectMemberList->finish()); + sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); node->rbracketToken = loc(5); diff --git a/src/declarative/qml/parser/javascriptparser_p.h b/src/declarative/qml/parser/javascriptparser_p.h index 2ae4c34..b6a2432 100644 --- a/src/declarative/qml/parser/javascriptparser_p.h +++ b/src/declarative/qml/parser/javascriptparser_p.h @@ -117,6 +117,7 @@ public: AST::UiArrayBinding *UiArrayBinding; AST::UiObjectMember *UiObjectMember; AST::UiObjectMemberList *UiObjectMemberList; + AST::UiArrayMemberList *UiArrayMemberList; AST::UiQualifiedId *UiQualifiedId; }; diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index e06afb5..d2608c8 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -1449,6 +1449,16 @@ int QmlDomList::length() const return 0; } +/*! + Returns a list of positions of the commas in the QML file. +*/ +QList QmlDomList:: commaPositions() const +{ + if (d && d->property) + return d->property->listCommaPositions; + else + return QList(); +} /*! \class QmlDomComponent diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h index 442a4fc..fde35a8 100644 --- a/src/declarative/qml/qmldom.h +++ b/src/declarative/qml/qmldom.h @@ -268,6 +268,8 @@ public: int position() const; int length() const; + QList commaPositions() const; + private: friend class QmlDomValue; QSharedDataPointer d; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 7989933..1481391 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -277,6 +277,7 @@ namespace QmlParser LocationSpan location; LocationRange listValueRange; + QList listCommaPositions; void dump(int = 0) const; }; diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index cab7915..ee2981e 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -649,7 +649,20 @@ bool ProcessAST::visit(AST::ExpressionStatement *node) return true; } -// UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiObjectMemberList T_RBRACKET ; +static QList collectCommas(AST::UiArrayMemberList *members) +{ + QList commas; + + if (members) { + for (AST::UiArrayMemberList *it = members->next; it; it = it->next) { + commas.append(it->commaToken.offset); + } + } + + return commas; +} + +// UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; bool ProcessAST::visit(AST::UiArrayBinding *node) { int propertyCount = 0; @@ -667,6 +680,9 @@ bool ProcessAST::visit(AST::UiArrayBinding *node) prop->listValueRange.offset = node->lbracketToken.offset; prop->listValueRange.length = node->rbracketToken.offset + node->rbracketToken.length - node->lbracketToken.offset; + // Store the positions of the comma token too, again for the DOM to be able to retreive it. + prop->listCommaPositions = collectCommas(node->members); + while (propertyCount--) _stateStack.pop(); -- cgit v0.12 From f2c4d2fe8a846cfce457512ef1806a7276745590 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 10 Jun 2009 12:10:33 +0200 Subject: qdoc: Added new class names for different tables. class="valuelist" is for the table used for enum types. class="alignedsummary" is for summary sections aligned on the name. class="propsummary" is for the property summary section. class="toc" is used for tables of contents. class="generic" is used for all other tables. We might need to break this down more. --- tools/qdoc3/htmlgenerator.cpp | 53 +++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index fb33de4..44401ed 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -678,13 +678,17 @@ int HtmlGenerator::generateAtom(const Atom *atom, else if (atom->string() == ATOM_LIST_VALUE) { threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom); if (threeColumnEnumValueTable) { - out() << "

\n" - "" - "\n"; + out() << "

ConstantValueDescription
\n" + << "" + << "" + << "\n"; } else { - out() << "

ConstantValueDescription
\n" - << "\n"; + out() << "

ConstantValue
\n" + << "\n"; } } else { @@ -858,14 +862,17 @@ int HtmlGenerator::generateAtom(const Atom *atom, } if (!atom->string().isEmpty()) { if (atom->string().contains("%")) - out() << "

ConstantValue
string() << "\" " + out() << "

string() << "\" " << "align=\"center\" cellpadding=\"2\" " << "cellspacing=\"1\" border=\"0\">\n"; - else - out() << "

\n"; + else { + out() << "

\n"; + } } else { - out() << "

\n"; + out() << "

\n"; } numTableRows = 0; break; @@ -1577,7 +1584,8 @@ void HtmlGenerator::generateTableOfContents(const Node *node, QString tdTag; if (numColumns > 1) { tdTag = "
"; - out() << "

\n" << tdTag << "\n"; + out() << "

\n" + << tdTag << "\n"; } // disable nested links in table of contents @@ -1596,7 +1604,8 @@ void HtmlGenerator::generateTableOfContents(const Node *node, out() << "
    "; sectionNumber.append("1"); } while (sectionNumber.size() < nextLevel); - } else { + } + else { while (sectionNumber.size() > nextLevel) { out() << "
\n"; sectionNumber.removeLast(); @@ -1804,10 +1813,13 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, } } -void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker, - const QMap &nodeMap) +void +HtmlGenerator::generateAnnotatedList(const Node *relative, + CodeMarker *marker, + const QMap&nodeMap) { - out() << "

\n"; + out() << "

\n"; int row = 0; foreach (const QString &name, nodeMap.keys()) { @@ -1960,7 +1972,7 @@ void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker } firstOffset[NumColumns] = classMap.count(); - out() << "

\n"; + out() << "

\n"; for (k = 0; k < numRows; k++) { out() << "\n"; for (i = 0; i < NumColumns; i++) { @@ -2213,12 +2225,12 @@ void HtmlGenerator::generateSectionList(const Section& section, name_alignment = false; } if (name_alignment) { - out() << "
\n"; } else { if (twoColumn) - out() << "

\n" << "
"; @@ -2513,12 +2525,13 @@ void HtmlGenerator::generateSectionList(const Section& section, bool twoColumn = false; if (style == CodeMarker::SeparateList) { twoColumn = (section.members.count() >= 16); - } else if (section.members.first()->type() == Node::Property) { + } + else if (section.members.first()->type() == Node::Property) { twoColumn = (section.members.count() >= 5); } if (twoColumn) - out() << "

\n" + out() << "

\n" << ""; if (qpgn->isDefault()) { - out() << "
" + out() << "
"; out() << "
    \n"; -- cgit v0.12 From 8179a9e2cd52b24c70b194106dd170ed1bb677e4 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 10 Jun 2009 12:54:53 +0200 Subject: small code cleanup that improves some loops it uses les foreach --- src/gui/itemviews/qabstractitemview.cpp | 4 ++-- src/gui/itemviews/qsortfilterproxymodel.cpp | 7 ++++--- src/gui/itemviews/qstandarditemmodel.cpp | 4 ++-- src/gui/itemviews/qtreeview.cpp | 6 ++++-- src/gui/kernel/qaction.cpp | 25 +++++++++++++++++-------- src/gui/kernel/qwidgetaction.cpp | 4 ++-- src/gui/widgets/qdockarealayout.cpp | 8 ++++---- src/gui/widgets/qdockwidget.cpp | 7 ++++--- src/gui/widgets/qmenubar.cpp | 6 ++++-- 9 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index c90216b..d353c2d 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -2398,8 +2398,8 @@ void QAbstractItemView::updateEditorGeometries() //we release the editor outside of the loop because it might change the focus and try //to change the d->editors list. - foreach(QWidget *editor, editorsToRelease) { - d->releaseEditor(editor); + for (int i = 0; i < editorsToRelease.count(); ++i) { + d->releaseEditor(editorsToRelease.at(i)); } } diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 96eb6f0..4021c83 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -884,8 +884,8 @@ void QSortFilterProxyModelPrivate::proxy_item_range( { proxy_low = INT_MAX; proxy_high = INT_MIN; - foreach (int source_item, source_items) { - int proxy_item = source_to_proxy.at(source_item); + for (int i = 0; i < source_items.count(); ++i) { + int proxy_item = source_to_proxy.at(source_items.at(i)); Q_ASSERT(proxy_item != -1); if (proxy_item < proxy_low) proxy_low = proxy_item; @@ -985,7 +985,8 @@ QSet QSortFilterProxyModelPrivate::handle_filter_changed( Q_Q(QSortFilterProxyModel); // Figure out which mapped items to remove QVector source_items_remove; - foreach (int source_item, proxy_to_source) { + for (int i = 0; i < proxy_to_source.count(); ++i) { + const int source_item = proxy_to_source.at(i); if ((orient == Qt::Vertical) ? !q->filterAcceptsRow(source_item, source_parent) : !q->filterAcceptsColumn(source_item, source_parent)) { diff --git a/src/gui/itemviews/qstandarditemmodel.cpp b/src/gui/itemviews/qstandarditemmodel.cpp index d8adbd2..9d0f796 100644 --- a/src/gui/itemviews/qstandarditemmodel.cpp +++ b/src/gui/itemviews/qstandarditemmodel.cpp @@ -2907,8 +2907,8 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const QStack stack; itemsSet.reserve(indexes.count()); stack.reserve(indexes.count()); - foreach (const QModelIndex &index, indexes) { - QStandardItem *item = itemFromIndex(index); + for (int i = 0; i < indexes.count(); ++i) { + QStandardItem *item = itemFromIndex(indexes.at(i)); itemsSet << item; stack.push(item); } diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 7837700..965a5c7 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2072,7 +2072,8 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie const bool useTopIndex = (cursorAction == MoveUp || cursorAction == MovePrevious); int index = useTopIndex ? INT_MAX : INT_MIN; const QItemSelection selection = d->selectionModel->selection(); - foreach (const QItemSelectionRange &range, selection) { + for (int i = 0; i < selection.count(); ++i) { + const QItemSelectionRange &range = selection.at(i); int candidate = d->viewIndex(useTopIndex ? range.topLeft() : range.bottomRight()); if (candidate >= 0) index = useTopIndex ? qMin(index, candidate) : qMax(index, candidate); @@ -3558,7 +3559,8 @@ QList > QTreeViewPrivate::columnRanges(const QModelIndex &topInd QPair current; current.first = -2; // -1 is not enough because -1+1 = 0 current.second = -2; - foreach (int logicalColumn, logicalIndexes) { + for(int i = 0; i < logicalIndexes.count(); ++i) { + const int logicalColumn = logicalIndexes.at(i); if (current.second + 1 != logicalColumn) { if (current.first != -2) { //let's save the current one diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index 051b6a6..f44d207 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -136,25 +136,31 @@ void QActionPrivate::redoGrab(QShortcutMap &map) void QActionPrivate::redoGrabAlternate(QShortcutMap &map) { Q_Q(QAction); - foreach (int id, alternateShortcutIds) - if (id) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) map.removeShortcut(id, q); + } alternateShortcutIds.clear(); if (alternateShortcuts.isEmpty()) return; - foreach (const QKeySequence& alternate, alternateShortcuts) { + for(int i = 0; i < alternateShortcuts.count(); ++i) { + const QKeySequence& alternate = alternateShortcuts.at(i); if (!alternate.isEmpty()) alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext)); else alternateShortcutIds.append(0); } if (!enabled) { - foreach (int id, alternateShortcutIds) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); map.setShortcutEnabled(false, id, q); + } } if (!autorepeat) { - foreach (int id, alternateShortcutIds) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); map.setShortcutAutoRepeat(false, id, q); + } } } @@ -163,9 +169,10 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) Q_Q(QAction); if (shortcutId) map.setShortcutEnabled(enable, shortcutId, q); - foreach (int id, alternateShortcutIds) - if (id) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) map.setShortcutEnabled(enable, id, q); + } } #endif // QT_NO_SHORTCUT @@ -615,8 +622,10 @@ QAction::~QAction() #ifndef QT_NO_SHORTCUT if (d->shortcutId && qApp) { qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this); - foreach (int id, d->alternateShortcutIds) + for(int i = 0; i < d->alternateShortcutIds.count(); ++i) { + const int id = d->alternateShortcutIds.at(i); qApp->d_func()->shortcutMap.removeShortcut(id, this); + } } #endif } diff --git a/src/gui/kernel/qwidgetaction.cpp b/src/gui/kernel/qwidgetaction.cpp index efdde5e..cd12029 100644 --- a/src/gui/kernel/qwidgetaction.cpp +++ b/src/gui/kernel/qwidgetaction.cpp @@ -228,8 +228,8 @@ bool QWidgetAction::event(QEvent *event) if (event->type() == QEvent::ActionChanged) { if (d->defaultWidget) d->defaultWidget->setEnabled(isEnabled()); - foreach (QWidget *w, d->createdWidgets) - w->setEnabled(isEnabled()); + for (int i = 0; i < d->createdWidgets.count(); ++i) + d->createdWidgets.at(i)->setEnabled(isEnabled()); } return QAction::event(event); } diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index 4f0ec1e..58e8f9c 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -2202,8 +2202,8 @@ QSet QDockAreaLayoutInfo::usedSeparatorWidgets() const { QSet result; - foreach (QWidget *sepWidget, separatorWidgets) - result << sepWidget; + for (int i = 0; i < separatorWidgets.count(); ++i) + result << separatorWidgets.at(i); for (int i = 0; i < item_list.count(); ++i) { const QDockAreaLayoutItem &item = item_list.at(i); @@ -3244,8 +3244,8 @@ QSet QDockAreaLayout::usedSeparatorWidgets() const { QSet result; - foreach (QWidget *sepWidget, separatorWidgets) - result << sepWidget; + for (int i = 0; i < separatorWidgets.count(); ++i) + result << separatorWidgets.at(i); for (int i = 0; i < QInternal::DockCount; ++i) { const QDockAreaLayoutInfo &dock = docks[i]; result += dock.usedSeparatorWidgets(); diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp index d573b8b..6a0c879 100644 --- a/src/gui/widgets/qdockwidget.cpp +++ b/src/gui/widgets/qdockwidget.cpp @@ -221,7 +221,8 @@ void QDockWidgetLayout::addItem(QLayoutItem*) QLayoutItem *QDockWidgetLayout::itemAt(int index) const { int cnt = 0; - foreach (QLayoutItem *item, item_list) { + for (int i = 0; i < item_list.count(); ++i) { + QLayoutItem *item = item_list.at(i); if (item == 0) continue; if (index == cnt++) @@ -250,8 +251,8 @@ QLayoutItem *QDockWidgetLayout::takeAt(int index) int QDockWidgetLayout::count() const { int result = 0; - foreach (QLayoutItem *item, item_list) { - if (item != 0) + for (int i = 0; i < item_list.count(); ++i) { + if (item_list.at(i)) ++result; } return result; diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index cffc3d5..fc7e901 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -220,7 +220,8 @@ void QMenuBarPrivate::updateGeometries() //we try to see if the actions will fit there bool hasHiddenActions = false; - foreach(QAction *action, actionList) { + for (int i = 0; i < actionList.count(); ++i) { + QAction *action = actionList.at(i); if (!menuRect.contains(actionRect(action))) { hasHiddenActions = true; break; @@ -230,7 +231,8 @@ void QMenuBarPrivate::updateGeometries() //...and if not, determine the ones that fit on the menu with the extension visible if (hasHiddenActions) { menuRect = this->menuRect(true); - foreach(QAction *action, actionList) { + for (int i = 0; i < actionList.count(); ++i) { + QAction *action = actionList.at(i); if (!menuRect.contains(actionRect(action))) { hiddenActions.append(action); } -- cgit v0.12 From 4a6548b83a6f1df42b82664efaca26c7efbc1909 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 10 Jun 2009 13:21:33 +0200 Subject: qdoc: Fix broken XHTML output. --- tools/qdoc3/htmlgenerator.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index c507f6c..eb8e65c 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -3456,7 +3456,9 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, generateQmlItem(qpn, relative, marker, false); out() << "
" + << "" + << "

" << "
" << "" << "
" -- cgit v0.12 From 53632d45ca64ad4c20d4302e0826c0234877dd69 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 10 Jun 2009 13:26:23 +0200 Subject: Revert "implement equality operator in a more sane way" This reverts commit 07dca7a30d4bd1efd8032915700420cca3fd60fa. Move the equality operator code back in (qFuzzyCompare) to avoid breaking many autotests. The change should go back in later on, possibly supplemented by a qFuzzyCompare(QTransform) function. But until we can figure out how to not break everything this patch has to wait. Reviewed-by: Lars --- src/gui/painting/qtransform.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index bd2ea31..86e594c 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -700,15 +700,11 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) */ bool QTransform::operator==(const QTransform &o) const { - return affine._m11 == o.affine._m11 && - affine._m12 == o.affine._m12 && - affine._m21 == o.affine._m21 && - affine._m22 == o.affine._m22 && - affine._dx == o.affine._dx && - affine._dy == o.affine._dy && - m_13 == o.m_13 && - m_23 == o.m_23 && - m_33 == o.m_33; +#define qFZ qFuzzyCompare + return qFZ(affine._m11, o.affine._m11) && qFZ(affine._m12, o.affine._m12) && qFZ(m_13, o.m_13) + && qFZ(affine._m21, o.affine._m21) && qFZ(affine._m22, o.affine._m22) && qFZ(m_23, o.m_23) + && qFZ(affine._dx, o.affine._dx) && qFZ(affine._dy, o.affine._dy) && qFZ(m_33, o.m_33); +#undef qFZ } /*! -- cgit v0.12 From 62725a02652cee576efe055d1371765945045026 Mon Sep 17 00:00:00 2001 From: Thomas Zander Date: Wed, 10 Jun 2009 13:31:06 +0200 Subject: add some api docs to clarify what collate does --- src/gui/painting/qprinter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp index ba208fd..ce33893 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -1308,6 +1308,9 @@ void QPrinter::setNumCopies(int numCopies) Returns true if collation is turned on when multiple copies is selected. Returns false if it is turned off when multiple copies is selected. + When collating is turned off the printing of each individual page will be repeated + the numCopies() amount before the next page is started. With collating turned on + all pages are printed before the next copy of those pages is started. \sa setCollateCopies() */ -- cgit v0.12 From 14f72183fbe1c7fad7c5434b2af032cc51436f5e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 10 Jun 2009 14:08:23 +0200 Subject: Revert "greatly speed up QTransform::mapRect() for projective transforms" This reverts commit 72e083c98c3adb07bb1578fb7f28f121fc3f34ac. This test broke the tst_QTransform::projectivePathMapping autotest. Lars is looking into it; for now we take the patch out. Reviewed-by: Lars --- src/gui/painting/qtransform.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 86e594c..c00012a 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1788,7 +1788,7 @@ QRect QTransform::mapRect(const QRect &rect) const y -= h; } return QRect(x, y, w, h); - } else { + } else if (t < TxProject) { // see mapToPolygon for explanations of the algorithm. qreal x = 0, y = 0; MAP(rect.left(), rect.top(), x, y); @@ -1812,6 +1812,10 @@ QRect QTransform::mapRect(const QRect &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin)); + } else { + QPainterPath path; + path.addRect(rect); + return map(path).boundingRect().toRect(); } } @@ -1854,7 +1858,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const y -= h; } return QRectF(x, y, w, h); - } else { + } else if (t < TxProject) { qreal x = 0, y = 0; MAP(rect.x(), rect.y(), x, y); qreal xmin = x; @@ -1877,6 +1881,10 @@ QRectF QTransform::mapRect(const QRectF &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRectF(xmin, ymin, xmax-xmin, ymax - ymin); + } else { + QPainterPath path; + path.addRect(rect); + return map(path).boundingRect(); } } -- cgit v0.12 From 0141b9b410278e064f3455d20cb21a50c926a2c8 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 10 Jun 2009 14:40:50 +0200 Subject: qdoc: Commented out debug code. Reviewed-by: Trust Me --- tools/qdoc3/htmlgenerator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 335cf66..cff8331 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -2498,8 +2498,8 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*()" static const QString linkTag("link"); - if (src.contains("setAcceptDrops")) - qDebug() << "SRC:" << src; + //if (src.contains("setAcceptDrops")) + // qDebug() << "SRC:" << src; bool done = false; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { @@ -3843,10 +3843,10 @@ void HtmlGenerator::generateQmlInherits(const QmlClassNode* cn, generateText(text, cn, marker); out() << "

"; } - else - qDebug() << "generateQmlInherits(): " - << "Inherited element not documented -->" - << linkPair.first; +// else +// qDebug() << "generateQmlInherits(): " +// << "Inherited element not documented -->" +// << linkPair.first; } } } -- cgit v0.12 From 08618c4d4e7b3d99ffa2b56ea03fa4e25de101bd Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 10 Jun 2009 14:41:33 +0200 Subject: Fix some possible double connected signals Task-number: 250147 Reviewed-by: Thierry --- src/gui/itemviews/qtableview.cpp | 6 +++--- src/gui/itemviews/qtreeview.cpp | 9 ++------- src/gui/widgets/qtoolbarlayout.cpp | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 0bded54..454b1f5 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -1844,14 +1844,14 @@ void QTableView::setSortingEnabled(bool enable) disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)), this, SLOT(selectColumn(int))); connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), - this, SLOT(sortByColumn(int))); + this, SLOT(sortByColumn(int)), Qt::UniqueConnection); sortByColumn(horizontalHeader()->sortIndicatorSection(), horizontalHeader()->sortIndicatorOrder()); } else { connect(d->horizontalHeader, SIGNAL(sectionEntered(int)), - this, SLOT(_q_selectColumn(int))); + this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection); connect(horizontalHeader(), SIGNAL(sectionPressed(int)), - this, SLOT(selectColumn(int))); + this, SLOT(selectColumn(int)), Qt::UniqueConnection); disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortByColumn(int))); } diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 965a5c7..9910118 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -238,11 +238,6 @@ void QTreeView::setModel(QAbstractItemModel *model) connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(rowsRemoved(QModelIndex,int,int))); - connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsRemoved(QModelIndex,int,int))); - connect(d->model, SIGNAL(modelAboutToBeReset()), SLOT(_q_modelAboutToBeReset())); if (d->sortingEnabled) @@ -3072,16 +3067,16 @@ void QTreeViewPrivate::_q_modelAboutToBeReset() void QTreeViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); if (start <= 0 && 0 <= end) viewItems.clear(); + QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(parent, start, end); } void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); if (start <= 0 && 0 <= end) doDelayedItemsLayout(); + QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end); } void QTreeViewPrivate::layout(int i) diff --git a/src/gui/widgets/qtoolbarlayout.cpp b/src/gui/widgets/qtoolbarlayout.cpp index 0bfa493..0af2b65 100644 --- a/src/gui/widgets/qtoolbarlayout.cpp +++ b/src/gui/widgets/qtoolbarlayout.cpp @@ -128,7 +128,7 @@ void QToolBarLayout::setUsePopupMenu(bool set) invalidate(); if (!set) { QObject::connect(extension, SIGNAL(clicked(bool)), - this, SLOT(setExpanded(bool))); + this, SLOT(setExpanded(bool)), Qt::UniqueConnection); extension->setPopupMode(QToolButton::DelayedPopup); extension->setMenu(0); delete popupMenu; -- cgit v0.12 From 686700203aa9deeafba3bae826c7caec6d6916fd Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 10 Jun 2009 14:44:52 +0200 Subject: Move declaration of QFileInfoPrivate in a separate file _p and add an auto-test when we copy file infos. Reviewed-by: ogoffart --- src/corelib/io/io.pri | 1 + src/corelib/io/qfileinfo.cpp | 65 +---------------- src/corelib/io/qfileinfo_p.h | 126 +++++++++++++++++++++++++++++++++ tests/auto/qfileinfo/tst_qfileinfo.cpp | 56 +++++++++++++++ 4 files changed, 184 insertions(+), 64 deletions(-) create mode 100644 src/corelib/io/qfileinfo_p.h diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 8f37e25..5033b21 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -10,6 +10,7 @@ HEADERS += \ io/qdiriterator.h \ io/qfile.h \ io/qfileinfo.h \ + io/qfileinfo_p.h \ io/qiodevice.h \ io/qiodevice_p.h \ io/qnoncontiguousbytedevice_p.h \ diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 36b1ed8..4f1b943 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -48,73 +48,10 @@ #include "qatomic.h" #include "qhash.h" #include "qdir.h" +#include "qfileinfo_p.h" QT_BEGIN_NAMESPACE -class QFileInfoPrivate -{ -public: - QFileInfoPrivate(const QFileInfo *copy=0); - ~QFileInfoPrivate(); - - void initFileEngine(const QString &); - - enum Access { - ReadAccess, - WriteAccess, - ExecuteAccess - }; - bool hasAccess(Access access) const; - - uint getFileFlags(QAbstractFileEngine::FileFlags) const; - QDateTime &getFileTime(QAbstractFileEngine::FileTime) const; - QString getFileName(QAbstractFileEngine::FileName) const; - - enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04, - CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40, - CachedSize =0x08 }; - struct Data { - inline Data() - : ref(1), fileEngine(0), cache_enabled(1) - { clear(); } - inline Data(const Data ©) - : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)), - fileName(copy.fileName), cache_enabled(copy.cache_enabled) - { clear(); } - inline ~Data() { delete fileEngine; } - inline void clearFlags() { - fileFlags = 0; - cachedFlags = 0; - if (fileEngine) - (void)fileEngine->fileFlags(QFSFileEngine::Refresh); - } - inline void clear() { - fileNames.clear(); - clearFlags(); - } - mutable QAtomicInt ref; - - QAbstractFileEngine *fileEngine; - mutable QString fileName; - mutable QHash fileNames; - - mutable uint cachedFlags : 31; - mutable uint cache_enabled : 1; - mutable uint fileFlags; - mutable qint64 fileSize; - mutable QDateTime fileTimes[3]; - inline bool getCachedFlag(uint c) const - { return cache_enabled ? (cachedFlags & c) : 0; } - inline void setCachedFlag(uint c) - { if (cache_enabled) cachedFlags |= c; } - } *data; - inline void reset() { - detach(); - data->clear(); - } - void detach(); -}; - QFileInfoPrivate::QFileInfoPrivate(const QFileInfo *copy) { if(copy) { diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h new file mode 100644 index 0000000..8155bcb --- /dev/null +++ b/src/corelib/io/qfileinfo_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module 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 QFILEINFO_P_H +#define QFILEINFO_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qfileinfo.h" + +QT_BEGIN_NAMESPACE + +class QFileInfoPrivate +{ +public: + QFileInfoPrivate(const QFileInfo *copy=0); + ~QFileInfoPrivate(); + + void initFileEngine(const QString &); + + enum Access { + ReadAccess, + WriteAccess, + ExecuteAccess + }; + bool hasAccess(Access access) const; + + uint getFileFlags(QAbstractFileEngine::FileFlags) const; + QDateTime &getFileTime(QAbstractFileEngine::FileTime) const; + QString getFileName(QAbstractFileEngine::FileName) const; + + enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04, + CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40, + CachedSize =0x08 }; + struct Data { + inline Data() + : ref(1), fileEngine(0), cache_enabled(1) + { clear(); } + inline Data(const Data ©) + : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)), + fileName(copy.fileName), cache_enabled(copy.cache_enabled) + { clear(); } + inline ~Data() { delete fileEngine; } + inline void clearFlags() { + fileFlags = 0; + cachedFlags = 0; + if (fileEngine) + (void)fileEngine->fileFlags(QFSFileEngine::Refresh); + } + inline void clear() { + fileNames.clear(); + clearFlags(); + } + mutable QAtomicInt ref; + + QAbstractFileEngine *fileEngine; + mutable QString fileName; + mutable QHash fileNames; + + mutable uint cachedFlags : 31; + mutable uint cache_enabled : 1; + mutable uint fileFlags; + mutable qint64 fileSize; + mutable QDateTime fileTimes[3]; + inline bool getCachedFlag(uint c) const + { return cache_enabled ? (cachedFlags & c) : 0; } + inline void setCachedFlag(uint c) + { if (cache_enabled) cachedFlags |= c; } + } *data; + inline void reset() { + detach(); + data->clear(); + } + void detach(); +}; + +QT_END_NAMESPACE + +#endif // QFILEINFO_P_H diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 3d7e6f8..cccdd64 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -61,6 +61,7 @@ #include #include "../network-settings.h" +#include //TESTED_CLASS= //TESTED_FILES= @@ -75,6 +76,9 @@ public: private slots: void getSetCheck(); + + void copy(); + void isFile_data(); void isFile(); @@ -178,6 +182,58 @@ void tst_QFileInfo::getSetCheck() QCOMPARE(true, obj1.caching()); } +static QFileInfoPrivate* getPrivate(QFileInfo &info) +{ + return (*reinterpret_cast(&info)); +} + +void tst_QFileInfo::copy() +{ + QTemporaryFile *t; + t = new QTemporaryFile; + t->open(); + QFileInfo info(t->fileName()); + QVERIFY(info.exists()); + + //copy constructor + QFileInfo info2(info); + QFileInfoPrivate *privateInfo = getPrivate(info); + QFileInfoPrivate *privateInfo2 = getPrivate(info2); + QCOMPARE(privateInfo->data, privateInfo2->data); + + //operator = + QFileInfo info3 = info; + QFileInfoPrivate *privateInfo3 = getPrivate(info3); + QCOMPARE(privateInfo->data, privateInfo3->data); + QCOMPARE(privateInfo2->data, privateInfo3->data); + + //refreshing info3 will detach it + QFile file(info.absoluteFilePath()); + QVERIFY(file.open(QFile::WriteOnly)); + QCOMPARE(file.write("JAJAJAA"), qint64(7)); + file.flush(); + + QTest::qWait(250); +#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) + if (QSysInfo::windowsVersion() & QSysInfo::WV_VISTA || + QSysInfo::windowsVersion() & QSysInfo::WV_CE_based) + file.close(); +#endif +#if defined(Q_OS_WINCE) + // On Windows CE we need to close the file. + // Otherwise the content will be cached and not + // flushed to the storage, although we flushed it + // manually!!! CE has interim cache, we cannot influence. + QTest::qWait(5000); +#endif + info3.refresh(); + QVERIFY(privateInfo->data != privateInfo3->data); + QVERIFY(privateInfo2->data != privateInfo3->data); + QCOMPARE(privateInfo->data, privateInfo2->data); + + +} + tst_QFileInfo::tst_QFileInfo() { } -- cgit v0.12 From a66525c2e4c760f8ceda344cd7252431ed263654 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 29 May 2009 11:16:20 +0200 Subject: Use a linked list for the senders list inside QObject Speed up the disconnection and object destruction Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 67 +++++++++++++++++++++++------------------- src/corelib/kernel/qobject_p.h | 5 +++- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 5e33a71..e953bcb 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -123,7 +123,7 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) } QObjectPrivate::QObjectPrivate(int version) - : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0) + : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0), senders(0) { if (version != QObjectPrivateVersion) qFatal("Cannot mix incompatible Qt libraries"); @@ -287,8 +287,8 @@ QObjectList QObjectPrivate::senderList() const { QObjectList returnValue; QMutexLocker locker(signalSlotLock(q_func())); - for (int i = 0; i < senders.count(); ++i) - returnValue << senders.at(i)->sender; + for (Connection *c = senders; c; c = c->next) + returnValue << c->sender; return returnValue; } @@ -756,8 +756,10 @@ QObject::~QObject() QMutex *m = signalSlotLock(c->receiver); bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); c = connectionList[i]; - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -774,29 +776,25 @@ QObject::~QObject() } // disconnect all senders - for (int i = 0; i < d->senders.count(); ) { - QObjectPrivate::Connection *s = d->senders[i]; - - QMutex *m = signalSlotLock(s->sender); + QObjectPrivate::Connection *node = d->senders; + while (node) { + QMutex *m = signalSlotLock(node->sender); + node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); - if (m < locker.mutex()) { - if (i >= d->senders.count() || s != d->senders[i]) { - if (needToUnlock) - m->unlock(); - continue; - } + //the node has maybe been removed while the mutex was unlocked in relock? + if (!node || signalSlotLock(node->sender) != m) { + m->unlock(); + continue; } - s->receiver = 0; - QObjectConnectionListVector *senderLists = s->sender->d_func()->connectionLists; + node->receiver = 0; + QObjectConnectionListVector *senderLists = node->sender->d_func()->connectionLists; if (senderLists) senderLists->dirty = true; if (needToUnlock) m->unlock(); - ++i; + node = node->next; } - - d->senders.clear(); } if (d->pendTimer) { @@ -2281,8 +2279,8 @@ QObject *QObject::sender() const // Return 0 if d->currentSender isn't in d->senders bool found = false; - for (int i = 0; !found && i < d->senders.count(); ++i) - found = (d->senders.at(i)->sender == d->currentSender->sender); + for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next) + found = (c->sender == d->currentSender->sender); if (!found) return 0; return d->currentSender->sender; @@ -2799,9 +2797,13 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, c->method = method_index; c->connectionType = type; c->argumentTypes = types; + c->prev = &r->d_func()->senders; + c->next = *c->prev; + *c->prev = c; + if (c->next) + c->next->prev = &c->next; s->d_func()->addConnection(signal_index, c); - r->d_func()->senders.append(c); if (signal_index < 0) sender->d_func()->connectedSignals = ~0u; @@ -2851,8 +2853,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); c = connectionList[i]; } - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -2878,8 +2882,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); c = connectionList[i]; } - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -3417,9 +3423,8 @@ void QObject::dumpObjectInfo() // now look for connections where this object is the receiver qDebug(" SIGNALS IN"); - if (!d->senders.isEmpty()) { - for (int i = 0; i < d->senders.count(); ++i) { - const QObjectPrivate::Connection *s = d->senders.at(i); + if (d->senders) { + for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) const QMetaMethod slot = metaObject()->method(s->method); qDebug(" <-- %s::%s %s", s->sender->metaObject()->className(), @@ -3427,7 +3432,7 @@ void QObject::dumpObjectInfo() slot.signature()); } } else { - qDebug(" "); + qDebug(" "); } #endif } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 96d79af..d699061 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -152,6 +152,9 @@ public: int method; uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking QBasicAtomicPointer argumentTypes; + //senders linked list + Connection *next; + Connection **prev; ~Connection(); }; typedef QList ConnectionList; @@ -160,7 +163,7 @@ public: void addConnection(int signal, Connection *c); void cleanConnectionLists(); - ConnectionList senders; + Connection *senders; //linked list; static Sender *setCurrentSender(QObject *receiver, Sender *sender); -- cgit v0.12 From 1a5e7171b9da383ca5f6be92b7cb6e502fd79fc4 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 3 Jun 2009 20:47:06 +0200 Subject: Avoid locking and search on the global hash if there is no QPointer As less than 10% of the object have QPointers, we can avoid locking if we know there is no QPointer. And keeping track of which object has a QPointer is easy. Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 22 +++++++++++++++++++--- src/corelib/kernel/qobject.h | 3 ++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index e953bcb..a095e0a 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -143,6 +143,7 @@ QObjectPrivate::QObjectPrivate(int version) inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; + hasGuards = false; } QObjectPrivate::~QObjectPrivate() @@ -359,6 +360,7 @@ void QMetaObject::addGuard(QObject **ptr) return; } QMutexLocker locker(guardHashLock()); + QObjectPrivate::get(*ptr)->hasGuards = true; hash->insert(*ptr, ptr); } @@ -374,12 +376,17 @@ void QMetaObject::removeGuard(QObject **ptr) QMutexLocker locker(guardHashLock()); GuardHash::iterator it = hash->find(*ptr); const GuardHash::iterator end = hash->end(); + bool more = false; //if the QObject has more pointer attached to it. for (; it.key() == *ptr && it != end; ++it) { if (it.value() == ptr) { - (void) hash->erase(it); + it = hash->erase(it); + if (!more) more = (it != end && it.key() == *ptr); break; } + more = true; } + if (!more) + QObjectPrivate::get(*ptr)->hasGuards = false; } /*!\internal @@ -393,24 +400,33 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) } QMutexLocker locker(guardHashLock()); if (*ptr) { + bool more = false; //if the QObject has more pointer attached to it. GuardHash::iterator it = hash->find(*ptr); const GuardHash::iterator end = hash->end(); for (; it.key() == *ptr && it != end; ++it) { if (it.value() == ptr) { - (void) hash->erase(it); + it = hash->erase(it); + if (!more) more = (it != end && it.key() == *ptr); break; } + more = true; } + if (!more) + QObjectPrivate::get(*ptr)->hasGuards = false; } *ptr = o; - if (*ptr) + if (*ptr) { hash->insert(*ptr, ptr); + QObjectPrivate::get(*ptr)->hasGuards = true; + } } /*! \internal */ void QObjectPrivate::clearGuards(QObject *object) { + if (!QObjectPrivate::get(object)->hasGuards) + return; GuardHash *hash = guardHash(); if (hash) { QMutexLocker locker(guardHashLock()); diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index dbec0a6..b1f41ad 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -106,7 +106,8 @@ public: uint receiveChildEvents : 1; uint inEventHandler : 1; uint inThreadChangeEvent : 1; - uint unused : 23; + uint hasGuards : 1; //true iff there is one or more QPointer attached to this object + uint unused : 22; int postedEvents; }; -- cgit v0.12 From dd3ee408148368a6f900844afc68fff9d86c2e8c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 10 Jun 2009 15:44:11 +0200 Subject: Compile with debug enabled --- src/corelib/kernel/qobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a095e0a..55d70c1 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3440,7 +3440,7 @@ void QObject::dumpObjectInfo() qDebug(" SIGNALS IN"); if (d->senders) { - for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) + for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) { const QMetaMethod slot = metaObject()->method(s->method); qDebug(" <-- %s::%s %s", s->sender->metaObject()->className(), -- cgit v0.12 From 09faf56a2e44b4dfa1b341ced75803100483834f Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 9 Jun 2009 23:44:32 +0300 Subject: Added QAbstractItemModelPrivate::canConvertToDouble(). And changed QTreeWidgetItem::operator<() and QTableWidgetItem::operator<() to use it Merge-request: 631 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qabstractitemmodel.cpp | 17 +++++++++++++++++ src/corelib/kernel/qabstractitemmodel_p.h | 1 + src/gui/itemviews/qtablewidget.cpp | 20 +------------------- src/gui/itemviews/qtablewidget_p.h | 1 - src/gui/itemviews/qtreewidget.cpp | 25 +------------------------ src/gui/itemviews/qtreewidget_p.h | 1 - 6 files changed, 20 insertions(+), 45 deletions(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 935c0aa..0a84ddb 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,6 +467,23 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +bool QAbstractItemModelPrivate::canConvertToDouble(const QVariant &value) +{ + switch (value.type()) { + case QVariant::Bool: + case QVariant::Int: + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Double: + case QVariant::Char: + return true; + default: + return false; + } + return false; +} + void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data) { if (data->index.isValid()) { diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index 27f1b28..70c35cb 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -89,6 +89,7 @@ public: void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last); void columnsRemoved(const QModelIndex &parent, int first, int last); static QAbstractItemModel *staticEmptyModel(); + static bool canConvertToDouble(const QVariant &value); inline QModelIndex createIndex(int row, int column, void *data = 0) const { return q_func()->createIndex(row, column, data); diff --git a/src/gui/itemviews/qtablewidget.cpp b/src/gui/itemviews/qtablewidget.cpp index 8cb2e55..072e435 100644 --- a/src/gui/itemviews/qtablewidget.cpp +++ b/src/gui/itemviews/qtablewidget.cpp @@ -530,24 +530,6 @@ void QTableModel::sort(int column, Qt::SortOrder order) emit layoutChanged(); } -bool QTableModel::canConvertToDouble(const QVariant &value) -{ - switch (value.type()) { - case QVariant::Bool: - case QVariant::Int: - case QVariant::UInt: - case QVariant::LongLong: - case QVariant::ULongLong: - case QVariant::Double: - case QVariant::Char: - return true; - default: - return false; - } - return false; -} - - /* \internal @@ -1410,7 +1392,7 @@ QVariant QTableWidgetItem::data(int role) const bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const { const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole); - if (QTableModel::canConvertToDouble(v1) && QTableModel::canConvertToDouble(v2)) + if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2)) return v1.toDouble() < v2.toDouble(); return v1.toString() < v2.toString(); } diff --git a/src/gui/itemviews/qtablewidget_p.h b/src/gui/itemviews/qtablewidget_p.h index 2e1dab6..d8bfcc5 100644 --- a/src/gui/itemviews/qtablewidget_p.h +++ b/src/gui/itemviews/qtablewidget_p.h @@ -144,7 +144,6 @@ public: const QPair &right); static bool itemGreaterThan(const QPair &left, const QPair &right); - static bool canConvertToDouble(const QVariant &value); void ensureSorted(int column, Qt::SortOrder order, int start, int end); QVector columnItems(int column) const; diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp index 1c87580..5604f8d 100644 --- a/src/gui/itemviews/qtreewidget.cpp +++ b/src/gui/itemviews/qtreewidget.cpp @@ -695,29 +695,6 @@ bool QTreeModel::itemGreaterThan(const QPair &left, } /*! - \internal - - Returns true if the type of the variant \a value - can be casted as double. -*/ -bool QTreeModel::canConvertToDouble(const QVariant &value) -{ - switch (value.type()) { - case QVariant::Bool: - case QVariant::Int: - case QVariant::UInt: - case QVariant::LongLong: - case QVariant::ULongLong: - case QVariant::Double: - case QVariant::Char: - return true; - default: - return false; - } - return false; -} - -/*! \internal */ QList::iterator QTreeModel::sortedInsertionIterator( @@ -1812,7 +1789,7 @@ bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const int column = view ? view->sortColumn() : 0; const QVariant v1 = data(column, Qt::DisplayRole); const QVariant v2 = other.data(column, Qt::DisplayRole); - if (QTreeModel::canConvertToDouble(v1) && QTreeModel::canConvertToDouble(v2)) + if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2)) return v1.toDouble() < v2.toDouble(); return v1.toString() < v2.toString(); } diff --git a/src/gui/itemviews/qtreewidget_p.h b/src/gui/itemviews/qtreewidget_p.h index 96f734d..a089cf5 100644 --- a/src/gui/itemviews/qtreewidget_p.h +++ b/src/gui/itemviews/qtreewidget_p.h @@ -116,7 +116,6 @@ public: const QPair &right); static bool itemGreaterThan(const QPair &left, const QPair &right); - static bool canConvertToDouble(const QVariant &value); static QList::iterator sortedInsertionIterator( const QList::iterator &begin, const QList::iterator &end, -- cgit v0.12 From 3e2ee19553c2423e1e76264f3c3eb088cd31747a Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 9 Jun 2009 23:52:27 +0300 Subject: Made QListWidgetItem::operator<() check if the data is numerical when comparing. Merge-request: 631 Reviewed-by: Olivier Goffart --- src/gui/itemviews/qlistwidget.cpp | 5 +++- tests/auto/qlistwidget/tst_qlistwidget.cpp | 39 +++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp index e1e509d..504908f 100644 --- a/src/gui/itemviews/qlistwidget.cpp +++ b/src/gui/itemviews/qlistwidget.cpp @@ -687,7 +687,10 @@ QVariant QListWidgetItem::data(int role) const */ bool QListWidgetItem::operator<(const QListWidgetItem &other) const { - return text() < other.text(); + const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole); + if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2)) + return v1.toDouble() < v2.toDouble(); + return v1.toString() < v2.toString(); } #ifndef QT_NO_DATASTREAM diff --git a/tests/auto/qlistwidget/tst_qlistwidget.cpp b/tests/auto/qlistwidget/tst_qlistwidget.cpp index 8d15aa4..8468cf3 100644 --- a/tests/auto/qlistwidget/tst_qlistwidget.cpp +++ b/tests/auto/qlistwidget/tst_qlistwidget.cpp @@ -883,31 +883,46 @@ void tst_QListWidget::itemStreaming() void tst_QListWidget::sortItems_data() { QTest::addColumn("order"); - QTest::addColumn("initialList"); - QTest::addColumn("expectedList"); + QTest::addColumn("initialList"); + QTest::addColumn("expectedList"); QTest::addColumn("expectedRows"); - QTest::newRow("ascending order") + QTest::newRow("ascending strings") << static_cast(Qt::AscendingOrder) - << (QStringList() << "c" << "d" << "a" << "b") - << (QStringList() << "a" << "b" << "c" << "d") + << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b")) + << (QVariantList() << QString("a") << QString("b") << QString("c") << QString("d")) << (IntList() << 2 << 3 << 0 << 1); - QTest::newRow("descending order") + QTest::newRow("descending strings") << static_cast(Qt::DescendingOrder) - << (QStringList() << "c" << "d" << "a" << "b") - << (QStringList() << "d" << "c" << "b" << "a") + << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b")) + << (QVariantList() << QString("d") << QString("c") << QString("b") << QString("a")) << (IntList() << 1 << 0 << 3 << 2); + + QTest::newRow("ascending numbers") + << static_cast(Qt::AscendingOrder) + << (QVariantList() << 1 << 11 << 2 << 22) + << (QVariantList() << 1 << 2 << 11 << 22) + << (IntList() << 0 << 2 << 1 << 3); + + QTest::newRow("descending numbers") + << static_cast(Qt::DescendingOrder) + << (QVariantList() << 1 << 11 << 2 << 22) + << (QVariantList() << 22 << 11 << 2 << 1) + << (IntList() << 3 << 1 << 2 << 0); } void tst_QListWidget::sortItems() { QFETCH(int, order); - QFETCH(QStringList, initialList); - QFETCH(QStringList, expectedList); + QFETCH(QVariantList, initialList); + QFETCH(QVariantList, expectedList); QFETCH(IntList, expectedRows); - testWidget->addItems(initialList); + foreach (const QVariant &data, initialList) { + QListWidgetItem *item = new QListWidgetItem(testWidget); + item->setData(Qt::DisplayRole, data); + } QAbstractItemModel *model = testWidget->model(); QList persistent; @@ -918,7 +933,7 @@ void tst_QListWidget::sortItems() QCOMPARE(testWidget->count(), expectedList.count()); for (int i = 0; i < testWidget->count(); ++i) - QCOMPARE(testWidget->item(i)->text(), expectedList.at(i)); + QCOMPARE(testWidget->item(i)->text(), expectedList.at(i).toString()); for (int k = 0; k < testWidget->count(); ++k) QCOMPARE(persistent.at(k).row(), expectedRows.at(k)); -- cgit v0.12 From 188a4ab62c99dcb113cad1833a0701d84a886e65 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 10 Jun 2009 15:35:45 +0200 Subject: Internal documentation for QAbstractItemModelPrivate::canConvertToDouble Also add QMetaType types as list or recognized numerical types Reviewed-by: thierry --- src/corelib/kernel/qabstractitemmodel.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 0a84ddb..6d6caf5 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,9 +467,17 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +/*! + \internal + return true if \a value contains a numerical type + + This function is used by our Q{Tree,Widget,Table}WidgetModel classes to sort. + We cannot rely on QVariant::canConvert because this would take strings as double + and then not sort strings correctly +*/ bool QAbstractItemModelPrivate::canConvertToDouble(const QVariant &value) { - switch (value.type()) { + switch (value.userType()) { case QVariant::Bool: case QVariant::Int: case QVariant::UInt: @@ -477,6 +485,12 @@ bool QAbstractItemModelPrivate::canConvertToDouble(const QVariant &value) case QVariant::ULongLong: case QVariant::Double: case QVariant::Char: + case QMetaType::Float: + case QMetaType::Short: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::ULong: + case QMetaType::Long: return true; default: return false; -- cgit v0.12 From 32f32ee3e752a6cc03505ddaa48d2849eaedc2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 10 Jun 2009 14:31:20 +0200 Subject: QPainter::worldTransform() does not return identity matrix. QPainter::worldTransform() does not return identity matrix when created on a redirected widget. It should always be identity by default, and should only change as a result of QPainter::setWorldTransform. The reason it didn't return identity for redirected widgets, was that we translated the shared painter's world matrix directly. Since we cannot modify the world matrix directly, we have to store the shared painter's current world transform in a separate matrix (redirectedMatrix), reset the world transform to identity, and later combine the redirectedMatrix with world transforms set on the painter. Note that redirection_offset was in negative coordinates before, and that redirectionMatrix now is in positive coordinates, hence opposite signs around. Auto-test included. Reviewed-by: lars Reviewed-by: Samuel --- src/gui/painting/qpaintengineex.cpp | 3 +- src/gui/painting/qpainter.cpp | 47 ++++++++----------- src/gui/painting/qpainter_p.h | 2 +- tests/auto/qwidget/tst_qwidget.cpp | 94 +++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 31 deletions(-) diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 3cf5ff9..d2671c8 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -151,8 +151,7 @@ void QPaintEngineExPrivate::replayClipOperations() QTransform transform = q->state()->matrix; - QTransform redirection; - redirection.translate(-q->state()->redirection_offset.x(), -q->state()->redirection_offset.y()); + const QTransform &redirection = q->state()->redirectionMatrix; for (int i = 0; i < clipInfo.size(); ++i) { const QPainterClipInfo &info = clipInfo.at(i); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 4744f14..0ece498 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -281,10 +281,14 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height(); // Update matrix. - if (q->d_ptr->state->WxF) - q->d_ptr->state->worldMatrix.translate(-offset.x(), -offset.y()); - else - q->d_ptr->state->redirection_offset = offset; + if (q->d_ptr->state->WxF) { + q->d_ptr->state->redirectionMatrix *= q->d_ptr->state->worldMatrix; + q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y()); + q->d_ptr->state->worldMatrix = QTransform(); + q->d_ptr->state->WxF = false; + } else { + q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y()); + } q->d_ptr->updateMatrix(); QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func(); @@ -410,7 +414,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio bool old_txinv = txinv; QTransform old_invMatrix = invMatrix; txinv = true; - invMatrix = QTransform().translate(-state->redirection_offset.x(), -state->redirection_offset.y()); + invMatrix = state->redirectionMatrix; QPainterPath clipPath = q->clipPath(); QRectF r = clipPath.boundingRect().intersected(absPathRect); absPathRect = r.toAlignedRect(); @@ -634,20 +638,7 @@ void QPainterPrivate::updateMatrix() state->matrix *= viewTransform(); txinv = false; // no inverted matrix - if (!state->redirection_offset.isNull()) { - // We want to translate in dev space so we do the adding of the redirection - // offset manually. - if (state->matrix.isAffine()) { - state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(), - state->matrix.m21(), state->matrix.m22(), - state->matrix.dx()-state->redirection_offset.x(), - state->matrix.dy()-state->redirection_offset.y()); - } else { - QTransform temp; - temp.translate(-state->redirection_offset.x(), -state->redirection_offset.y()); - state->matrix *= temp; - } - } + state->matrix *= state->redirectionMatrix; if (extended) extended->transformChanged(); else @@ -1572,10 +1563,8 @@ void QPainter::restore() // replay the list of clip states, for (int i=0; istate->clipInfo.size(); ++i) { const QPainterClipInfo &info = d->state->clipInfo.at(i); - tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m13(), - info.matrix.m21(), info.matrix.m22(), info.matrix.m23(), - info.matrix.dx() - d->state->redirection_offset.x(), - info.matrix.dy() - d->state->redirection_offset.y(), info.matrix.m33()); + tmp->matrix = info.matrix; + tmp->matrix *= d->state->redirectionMatrix; tmp->clipOperation = info.operation; if (info.clipType == QPainterClipInfo::RectClip) { tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform; @@ -1689,7 +1678,7 @@ bool QPainter::begin(QPaintDevice *pd) d->state->painter = this; d->states.push_back(d->state); - d->state->redirection_offset = redirectionOffset; + d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y()); d->state->brushOrigin = QPointF(); if (!d->engine) { @@ -1723,7 +1712,8 @@ bool QPainter::begin(QPaintDevice *pd) // Adjust offset for alien widgets painting outside the paint event. if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId() && widget->testAttribute(Qt::WA_WState_Created)) { - d->state->redirection_offset -= widget->mapTo(widget->nativeParentWidget(), QPoint()); + const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint()); + d->state->redirectionMatrix.translate(offset.x(), offset.y()); } break; } @@ -1805,11 +1795,12 @@ bool QPainter::begin(QPaintDevice *pd) d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight); } - d->state->redirection_offset += d->engine->coordinateOffset(); + const QPoint coordinateOffset = d->engine->coordinateOffset(); + d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y()); Q_ASSERT(d->engine->isActive()); - if (!d->state->redirection_offset.isNull()) + if (!d->state->redirectionMatrix.isIdentity()) d->updateMatrix(); Q_ASSERT(d->engine->isActive()); @@ -7704,7 +7695,7 @@ QPainterState::QPainterState(const QPainterState *s) clipRegion(s->clipRegion), clipPath(s->clipPath), clipOperation(s->clipOperation), renderHints(s->renderHints), clipInfo(s->clipInfo), - worldMatrix(s->worldMatrix), matrix(s->matrix), redirection_offset(s->redirection_offset), + worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix), wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh), vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh), opacity(s->opacity), WxF(s->WxF), VxF(s->VxF), diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 6c8821a..8d4e6c5 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -158,7 +158,7 @@ public: QList clipInfo; // ### Make me smaller and faster to copy around... QTransform worldMatrix; // World transformation matrix, not window and viewport QTransform matrix; // Complete transformation matrix, - QPoint redirection_offset; + QTransform redirectionMatrix; int wx, wy, ww, wh; // window rectangle int vx, vy, vw, vh; // viewport rectangle qreal opacity; diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 041aa7a..85d7de1 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -288,6 +288,7 @@ private slots: void render_systemClip3_data(); void render_systemClip3(); void render_task252837(); + void render_worldTransform(); void setContentsMargins(); @@ -7151,6 +7152,99 @@ void tst_QWidget::render_task252837() // Please do not crash. widget.render(&painter); } + +void tst_QWidget::render_worldTransform() +{ + class MyWidget : public QWidget + { public: + void paintEvent(QPaintEvent *) + { + QPainter painter(this); + // Make sure world transform is identity. + QCOMPARE(painter.worldTransform(), QTransform()); + + // Make sure device transform is correct. + const QPoint widgetOffset = geometry().topLeft(); + QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5); + expectedDeviceTransform.rotate(90); + expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y()); + QCOMPARE(painter.deviceTransform(), expectedDeviceTransform); + + // Set new world transform. + QTransform newWorldTransform = QTransform::fromTranslate(10, 10); + newWorldTransform.rotate(90); + painter.setWorldTransform(newWorldTransform); + QCOMPARE(painter.worldTransform(), newWorldTransform); + + // Again, check device transform. + expectedDeviceTransform.translate(10, 10); + expectedDeviceTransform.rotate(90); + QCOMPARE(painter.deviceTransform(), expectedDeviceTransform); + + painter.fillRect(QRect(0, 0, 20, 10), Qt::green); + } + }; + + MyWidget widget; + widget.setFixedSize(100, 100); + widget.setPalette(Qt::red); + widget.setAutoFillBackground(true); + + MyWidget child; + child.setParent(&widget); + child.move(50, 50); + child.setFixedSize(50, 50); + child.setPalette(Qt::blue); + child.setAutoFillBackground(true); + + QImage image(QSize(110, 110), QImage::Format_RGB32); + image.fill(QColor(Qt::black).rgb()); + + QPainter painter(&image); + painter.translate(105, 5); + painter.rotate(90); + + const QTransform worldTransform = painter.worldTransform(); + const QTransform deviceTransform = painter.deviceTransform(); + + // Render widgets onto image. + widget.render(&painter); +#ifdef RENDER_DEBUG + image.save("render_worldTransform_image.png"); +#endif + + // Ensure the transforms are unchanged after render. + QCOMPARE(painter.worldTransform(), painter.worldTransform()); + QCOMPARE(painter.deviceTransform(), painter.deviceTransform()); + painter.end(); + + // Paint expected image. + QImage expected(QSize(110, 110), QImage::Format_RGB32); + expected.fill(QColor(Qt::black).rgb()); + + QPainter expectedPainter(&expected); + expectedPainter.translate(105, 5); + expectedPainter.rotate(90); + expectedPainter.save(); + expectedPainter.fillRect(widget.rect(),Qt::red); + expectedPainter.translate(10, 10); + expectedPainter.rotate(90); + expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green); + expectedPainter.restore(); + expectedPainter.translate(50, 50); + expectedPainter.fillRect(child.rect(),Qt::blue); + expectedPainter.translate(10, 10); + expectedPainter.rotate(90); + expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green); + expectedPainter.end(); + +#ifdef RENDER_DEBUG + expected.save("render_worldTransform_expected.png"); +#endif + + QCOMPARE(image, expected); +} + void tst_QWidget::setContentsMargins() { QLabel label("why does it always rain on me?"); -- cgit v0.12 From 4eda7463c9626ab47ef465a5174887250b7561d9 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 10 Jun 2009 17:10:44 +0200 Subject: qdoc: Fixed XML-level breakage. Reviewed-by: Trust Me --- tools/qdoc3/htmlgenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index cff8331..8df932e 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -2424,7 +2424,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section, QList >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { if (nameAlignment) - out() << "
  • "; + out() << "
  • "; else out() << "
  • "; out() << (*p).second << " "; @@ -2712,7 +2712,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section, { QList >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { - out() << "
  • "; + out() << "
  • "; out() << (*p).second << " "; if ((*p).second == 1) { out() << section.singularMember; -- cgit v0.12 From 7faaa967a4e872cc31f1bcb9e96fe08edbf639b3 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 11 Jun 2009 09:39:43 +1000 Subject: typo in my recent change --- src/declarative/fx/qfxblendedimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/fx/qfxblendedimage.cpp b/src/declarative/fx/qfxblendedimage.cpp index 1f805df..e216196 100644 --- a/src/declarative/fx/qfxblendedimage.cpp +++ b/src/declarative/fx/qfxblendedimage.cpp @@ -102,7 +102,7 @@ void QFxBlendedImage::setPrimaryUrl(const QUrl &url) return; if (!primUrl.isEmpty()) QFxPixmap::cancelGet(primUrl,this); - Q_ASSERT(!primUrl.isRelative()); + Q_ASSERT(!url.isRelative()); primUrl = url; if (!primUrl.isEmpty()) QFxPixmap::get(qmlEngine(this), primUrl,this,SLOT(primaryLoaded())); -- cgit v0.12 From ee66f86c529fd939b74589d8131b653ef5f799b5 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 11 Jun 2009 15:14:47 +1000 Subject: Use the most derived extension object, not the least derived --- src/declarative/qml/qmlproxymetaobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlproxymetaobject.cpp b/src/declarative/qml/qmlproxymetaobject.cpp index d24c5c4..686c6d7 100644 --- a/src/declarative/qml/qmlproxymetaobject.cpp +++ b/src/declarative/qml/qmlproxymetaobject.cpp @@ -50,7 +50,7 @@ QmlProxyMetaObject::QmlProxyMetaObject(QObject *obj, QList *mList) qWarning() << "QmlProxyMetaObject" << obj->metaObject()->className(); #endif - *static_cast(this) = *metaObjects->last().metaObject; + *static_cast(this) = *metaObjects->first().metaObject; QObjectPrivate *op = QObjectPrivate::get(obj); if (op->metaObject) -- cgit v0.12 From 2feffad511c2ea535e59221ae1b0b46c91bb8227 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 4 Jun 2009 14:32:43 +0200 Subject: qdoc: Mention that QML_DECLARE_TYPE only works for non-abstract classes --- doc/src/declarative/qmlforcpp.qdoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/src/declarative/qmlforcpp.qdoc b/doc/src/declarative/qmlforcpp.qdoc index 2898499..4095071 100644 --- a/doc/src/declarative/qmlforcpp.qdoc +++ b/doc/src/declarative/qmlforcpp.qdoc @@ -186,7 +186,8 @@ name \a QmlName. Of course there's nothing stopping you using the same name for both the C++ and the QML name! Any type can be added to the QML engine using these macros. The only - requirements are that \a T inherits QObject and that it has a default constructor. + requirements are that \a T inherits QObject, is not abstract, + and that it has a default constructor. \section1 Property Binding -- cgit v0.12 From e83bed831c80657221176b9c0e24962d9c9e7ca2 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 08:54:31 +0200 Subject: Introduce QGraphicsItem::ItemHasNoContents. This flag helps optimize the case where an item is used only as a transformation node in a scene graph, and where the item itself doesn't paint anything. This is the default for FxItem (the subclasses that do paint enable the HasContents flag). This lets Graphics View know whether there's any point in setting up the world transform, opacity and other things. Reviewed-by: Lars --- src/declarative/canvas/qsimplecanvasitem.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp index 7451a5f..cbdc324 100644 --- a/src/declarative/canvas/qsimplecanvasitem.cpp +++ b/src/declarative/canvas/qsimplecanvasitem.cpp @@ -1300,6 +1300,9 @@ void QSimpleCanvasItem::setOptions(Options options, bool set) d->options &= ~IsFocusRealm; } + if (d->graphicsItem) + d->graphicsItem->setFlag(QGraphicsItem::ItemHasNoContents, !(d->options & HasContents)); + if ((old & MouseFilter) != (d->options & MouseFilter)) { if (d->graphicsItem) { if (d->options & MouseFilter) @@ -1487,6 +1490,7 @@ void QSimpleCanvasItemPrivate::convertToGraphicsItem(QGraphicsItem *parent) Q_Q(QSimpleCanvasItem); Q_ASSERT(!graphicsItem); graphicsItem = new QSimpleGraphicsItem(q); + graphicsItem->setFlag(QGraphicsItem::ItemHasNoContents, !(q->options() & QSimpleCanvasItem::HasContents)); if (parent) graphicsItem->setParentItem(parent); -- cgit v0.12 From f88167c39259967912540cf50d3f9df9524da4b3 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 2 Jun 2009 21:31:31 +0200 Subject: make the setRotation code a little more efficient This doesn't give us much. The real fix here is to add support for rotation and transformationOrigin to QGraphicsItem. --- src/declarative/fx/qfxitem.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 09ec748..648b0fb 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -1490,9 +1490,8 @@ void QFxItem::setRotation(qreal rotation) trans.rotate(d->_rotation, 0, 0, 1); trans.translate(-to.x(), -to.y()); #else - QTransform trans; - QPointF to = transformOriginPoint(); - trans.translate(to.x(), to.y()); + QPointF to = d->transformOrigin(); + QTransform trans = QTransform::fromTranslate(to.x(), to.y()); trans.rotate(d->_rotation); trans.translate(-to.x(), -to.y()); #endif -- cgit v0.12 From 7d7c1da715474cefa5404df684d680c36e4b6b20 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 11 Jun 2009 10:46:43 +0200 Subject: Renamed the QML front-end. --- src/declarative/qml/parser/javascript.g | 2880 ------------------- src/declarative/qml/parser/javascriptast.cpp | 962 ------- src/declarative/qml/parser/javascriptast_p.h | 2544 ----------------- src/declarative/qml/parser/javascriptastfwd_p.h | 184 -- .../qml/parser/javascriptastvisitor.cpp | 58 - .../qml/parser/javascriptastvisitor_p.h | 328 --- src/declarative/qml/parser/javascriptengine_p.cpp | 191 -- src/declarative/qml/parser/javascriptengine_p.h | 145 - src/declarative/qml/parser/javascriptgrammar.cpp | 829 ------ src/declarative/qml/parser/javascriptgrammar_p.h | 200 -- src/declarative/qml/parser/javascriptlexer.cpp | 1196 -------- src/declarative/qml/parser/javascriptlexer_p.h | 269 -- .../qml/parser/javascriptmemorypool_p.h | 130 - src/declarative/qml/parser/javascriptnodepool_p.h | 138 - src/declarative/qml/parser/javascriptparser.cpp | 1717 ------------ src/declarative/qml/parser/javascriptparser_p.h | 208 -- .../qml/parser/javascriptprettypretty.cpp | 1334 --------- .../qml/parser/javascriptprettypretty_p.h | 329 --- src/declarative/qml/parser/parser.pri | 34 +- src/declarative/qml/parser/qmljs.g | 2881 ++++++++++++++++++++ src/declarative/qml/parser/qmljsast.cpp | 962 +++++++ src/declarative/qml/parser/qmljsast_p.h | 2544 +++++++++++++++++ src/declarative/qml/parser/qmljsastfwd_p.h | 184 ++ src/declarative/qml/parser/qmljsastvisitor.cpp | 58 + src/declarative/qml/parser/qmljsastvisitor_p.h | 328 +++ src/declarative/qml/parser/qmljsengine_p.cpp | 191 ++ src/declarative/qml/parser/qmljsengine_p.h | 145 + src/declarative/qml/parser/qmljsgrammar.cpp | 829 ++++++ src/declarative/qml/parser/qmljsgrammar_p.h | 200 ++ src/declarative/qml/parser/qmljslexer.cpp | 1196 ++++++++ src/declarative/qml/parser/qmljslexer_p.h | 269 ++ src/declarative/qml/parser/qmljsmemorypool_p.h | 130 + src/declarative/qml/parser/qmljsnodepool_p.h | 138 + src/declarative/qml/parser/qmljsparser.cpp | 1717 ++++++++++++ src/declarative/qml/parser/qmljsparser_p.h | 208 ++ src/declarative/qml/parser/qmljsprettypretty.cpp | 1334 +++++++++ src/declarative/qml/parser/qmljsprettypretty_p.h | 329 +++ src/declarative/qml/qmlbasicscript.cpp | 36 +- src/declarative/qml/qmlcompiler.cpp | 12 +- src/declarative/qml/qmlengine.cpp | 2 +- src/declarative/qml/qmlparser.cpp | 4 +- src/declarative/qml/qmlparser_p.h | 8 +- src/declarative/qml/qmlscriptparser.cpp | 16 +- src/declarative/qml/rewriter/rewriter.cpp | 8 +- src/declarative/qml/rewriter/rewriter_p.h | 6 +- src/declarative/qml/rewriter/textwriter.cpp | 2 +- src/declarative/qml/rewriter/textwriter_p.h | 4 +- tools/linguist/lupdate/qml.cpp | 14 +- 48 files changed, 13716 insertions(+), 13715 deletions(-) delete mode 100644 src/declarative/qml/parser/javascript.g delete mode 100644 src/declarative/qml/parser/javascriptast.cpp delete mode 100644 src/declarative/qml/parser/javascriptast_p.h delete mode 100644 src/declarative/qml/parser/javascriptastfwd_p.h delete mode 100644 src/declarative/qml/parser/javascriptastvisitor.cpp delete mode 100644 src/declarative/qml/parser/javascriptastvisitor_p.h delete mode 100644 src/declarative/qml/parser/javascriptengine_p.cpp delete mode 100644 src/declarative/qml/parser/javascriptengine_p.h delete mode 100644 src/declarative/qml/parser/javascriptgrammar.cpp delete mode 100644 src/declarative/qml/parser/javascriptgrammar_p.h delete mode 100644 src/declarative/qml/parser/javascriptlexer.cpp delete mode 100644 src/declarative/qml/parser/javascriptlexer_p.h delete mode 100644 src/declarative/qml/parser/javascriptmemorypool_p.h delete mode 100644 src/declarative/qml/parser/javascriptnodepool_p.h delete mode 100644 src/declarative/qml/parser/javascriptparser.cpp delete mode 100644 src/declarative/qml/parser/javascriptparser_p.h delete mode 100644 src/declarative/qml/parser/javascriptprettypretty.cpp delete mode 100644 src/declarative/qml/parser/javascriptprettypretty_p.h create mode 100644 src/declarative/qml/parser/qmljs.g create mode 100644 src/declarative/qml/parser/qmljsast.cpp create mode 100644 src/declarative/qml/parser/qmljsast_p.h create mode 100644 src/declarative/qml/parser/qmljsastfwd_p.h create mode 100644 src/declarative/qml/parser/qmljsastvisitor.cpp create mode 100644 src/declarative/qml/parser/qmljsastvisitor_p.h create mode 100644 src/declarative/qml/parser/qmljsengine_p.cpp create mode 100644 src/declarative/qml/parser/qmljsengine_p.h create mode 100644 src/declarative/qml/parser/qmljsgrammar.cpp create mode 100644 src/declarative/qml/parser/qmljsgrammar_p.h create mode 100644 src/declarative/qml/parser/qmljslexer.cpp create mode 100644 src/declarative/qml/parser/qmljslexer_p.h create mode 100644 src/declarative/qml/parser/qmljsmemorypool_p.h create mode 100644 src/declarative/qml/parser/qmljsnodepool_p.h create mode 100644 src/declarative/qml/parser/qmljsparser.cpp create mode 100644 src/declarative/qml/parser/qmljsparser_p.h create mode 100644 src/declarative/qml/parser/qmljsprettypretty.cpp create mode 100644 src/declarative/qml/parser/qmljsprettypretty_p.h diff --git a/src/declarative/qml/parser/javascript.g b/src/declarative/qml/parser/javascript.g deleted file mode 100644 index 884d814..0000000 --- a/src/declarative/qml/parser/javascript.g +++ /dev/null @@ -1,2880 +0,0 @@ ----------------------------------------------------------------------------- --- --- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). --- Contact: Qt Software Information (qt-info@nokia.com) --- --- This file is part of the QtScript module 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$ --- --- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE --- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. --- ----------------------------------------------------------------------------- - -%parser JavaScriptGrammar -%decl javascriptparser_p.h -%impl javascriptparser.cpp -%expect 2 -%expect-rr 2 - -%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" -%token T_BREAK "break" T_CASE "case" T_CATCH "catch" -%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue" -%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/" -%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "." -%token T_ELSE "else" T_EQ "=" T_EQ_EQ "==" -%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for" -%token T_FUNCTION "function" T_GE ">=" T_GT ">" -%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>" -%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if" -%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{" -%token T_LBRACKET "[" T_LE "<=" T_LPAREN "(" -%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<=" -%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--" -%token T_NEW "new" T_NOT "!" T_NOT_EQ "!=" -%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|" -%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+" -%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?" -%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%" -%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")" -%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*" -%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal" -%token T_PROPERTY "property" T_SIGNAL "signal" -%token T_SWITCH "switch" T_THIS "this" T_THROW "throw" -%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof" -%token T_VAR "var" T_VOID "void" T_WHILE "while" -%token T_WITH "with" T_XOR "^" T_XOR_EQ "^=" -%token T_NULL "null" T_TRUE "true" T_FALSE "false" -%token T_CONST "const" -%token T_DEBUGGER "debugger" -%token T_RESERVED_WORD "reserved word" -%token T_MULTILINE_STRING_LITERAL "multiline string literal" - ---- context keywords. -%token T_PUBLIC "public" -%token T_IMPORT "import" - -%nonassoc SHIFT_THERE -%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY -%nonassoc REDUCE_HERE - -%start UiProgram - -/. -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 - -#include - -#include "javascriptengine_p.h" -#include "javascriptlexer_p.h" -#include "javascriptast_p.h" -#include "javascriptnodepool_p.h" - -./ - -/: -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// -// This file is automatically generated from javascript.g. -// Changes will be lost. -// - -#ifndef JAVASCRIPTPARSER_P_H -#define JAVASCRIPTPARSER_P_H - -#include "javascriptgrammar_p.h" -#include "javascriptast_p.h" -#include "javascriptengine_p.h" - -#include - -QT_BEGIN_NAMESPACE - -class QString; - -namespace JavaScript { - -class Engine; -class NameId; - -class Parser: protected $table -{ -public: - union Value { - int ival; - double dval; - NameId *sval; - AST::ArgumentList *ArgumentList; - AST::CaseBlock *CaseBlock; - AST::CaseClause *CaseClause; - AST::CaseClauses *CaseClauses; - AST::Catch *Catch; - AST::DefaultClause *DefaultClause; - AST::ElementList *ElementList; - AST::Elision *Elision; - AST::ExpressionNode *Expression; - AST::Finally *Finally; - AST::FormalParameterList *FormalParameterList; - AST::FunctionBody *FunctionBody; - AST::FunctionDeclaration *FunctionDeclaration; - AST::Node *Node; - AST::PropertyName *PropertyName; - AST::PropertyNameAndValueList *PropertyNameAndValueList; - AST::SourceElement *SourceElement; - AST::SourceElements *SourceElements; - AST::Statement *Statement; - AST::StatementList *StatementList; - AST::Block *Block; - AST::VariableDeclaration *VariableDeclaration; - AST::VariableDeclarationList *VariableDeclarationList; - - AST::UiProgram *UiProgram; - AST::UiImportList *UiImportList; - AST::UiImport *UiImport; - AST::UiPublicMember *UiPublicMember; - AST::UiObjectDefinition *UiObjectDefinition; - AST::UiObjectInitializer *UiObjectInitializer; - AST::UiObjectBinding *UiObjectBinding; - AST::UiScriptBinding *UiScriptBinding; - AST::UiArrayBinding *UiArrayBinding; - AST::UiObjectMember *UiObjectMember; - AST::UiObjectMemberList *UiObjectMemberList; - AST::UiQualifiedId *UiQualifiedId; - }; - -public: - Parser(Engine *engine); - ~Parser(); - - bool parse(); - - AST::UiProgram *ast() - { return program; } - - QList diagnosticMessages() const - { return diagnostic_messages; } - - inline DiagnosticMessage diagnosticMessage() const - { - foreach (const DiagnosticMessage &d, diagnostic_messages) { - if (! d.kind == DiagnosticMessage::Warning) - return d; - } - - return DiagnosticMessage(); - } - - inline QString errorMessage() const - { return diagnosticMessage().message; } - - inline int errorLineNumber() const - { return diagnosticMessage().loc.startLine; } - - inline int errorColumnNumber() const - { return diagnosticMessage().loc.startColumn; } - -protected: - void reallocateStack(); - - inline Value &sym(int index) - { return sym_stack [tos + index - 1]; } - - inline AST::SourceLocation &loc(int index) - { return location_stack [tos + index - 1]; } - - AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); - -protected: - Engine *driver; - int tos; - int stack_size; - Value *sym_stack; - int *state_stack; - AST::SourceLocation *location_stack; - - AST::UiProgram *program; - - // error recovery - enum { TOKEN_BUFFER_SIZE = 3 }; - - struct SavedToken { - int token; - double dval; - AST::SourceLocation loc; - }; - - double yylval; - AST::SourceLocation yylloc; - AST::SourceLocation yyprevlloc; - - SavedToken token_buffer[TOKEN_BUFFER_SIZE]; - SavedToken *first_token; - SavedToken *last_token; - - QList diagnostic_messages; -}; - -} // end of namespace JavaScript - - -:/ - - -/. - -#include "javascriptparser_p.h" -#include - -// -// This file is automatically generated from javascript.g. -// Changes will be lost. -// - -using namespace JavaScript; - -QT_BEGIN_NAMESPACE - -void Parser::reallocateStack() -{ - if (! stack_size) - stack_size = 128; - else - stack_size <<= 1; - - sym_stack = reinterpret_cast (qRealloc(sym_stack, stack_size * sizeof(Value))); - state_stack = reinterpret_cast (qRealloc(state_stack, stack_size * sizeof(int))); - location_stack = reinterpret_cast (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); -} - -inline static bool automatic(Engine *driver, int token) -{ - return token == $table::T_RBRACE - || token == 0 - || driver->lexer()->prevTerminator(); -} - - -Parser::Parser(Engine *engine): - driver(engine), - tos(0), - stack_size(0), - sym_stack(0), - state_stack(0), - location_stack(0), - first_token(0), - last_token(0) -{ -} - -Parser::~Parser() -{ - if (stack_size) { - qFree(sym_stack); - qFree(state_stack); - qFree(location_stack); - } -} - -static inline AST::SourceLocation location(Lexer *lexer) -{ - AST::SourceLocation loc; - loc.offset = lexer->tokenOffset(); - loc.length = lexer->tokenLength(); - loc.startLine = lexer->startLineNo(); - loc.startColumn = lexer->startColumnNo(); - return loc; -} - -AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) -{ - QVarLengthArray nameIds; - QVarLengthArray locations; - - AST::ExpressionNode *it = expr; - while (AST::FieldMemberExpression *m = AST::cast(it)) { - nameIds.append(m->name); - locations.append(m->identifierToken); - it = m->base; - } - - if (AST::IdentifierExpression *idExpr = AST::cast(it)) { - AST::UiQualifiedId *q = makeAstNode(driver->nodePool(), idExpr->name); - q->identifierToken = idExpr->identifierToken; - - AST::UiQualifiedId *currentId = q; - for (int i = nameIds.size() - 1; i != -1; --i) { - currentId = makeAstNode(driver->nodePool(), currentId, nameIds[i]); - currentId->identifierToken = locations[i]; - } - - return currentId->finish(); - } - - return 0; -} - -bool Parser::parse() -{ - Lexer *lexer = driver->lexer(); - bool hadErrors = false; - int yytoken = -1; - int action = 0; - - first_token = last_token = 0; - - tos = -1; - program = 0; - - do { - if (++tos == stack_size) - reallocateStack(); - - state_stack[tos] = action; - - _Lcheck_token: - if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { - yyprevlloc = yylloc; - - if (first_token == last_token) { - yytoken = lexer->lex(); - yylval = lexer->dval(); - yylloc = location(lexer); - } else { - yytoken = first_token->token; - yylval = first_token->dval; - yylloc = first_token->loc; - ++first_token; - } - } - - action = t_action(action, yytoken); - if (action > 0) { - if (action != ACCEPT_STATE) { - yytoken = -1; - sym(1).dval = yylval; - loc(1) = yylloc; - } else { - --tos; - return ! hadErrors; - } - } else if (action < 0) { - const int r = -action - 1; - tos -= rhs[r]; - - switch (r) { -./ - --------------------------------------------------------------------------------------------------------- --- Declarative UI --------------------------------------------------------------------------------------------------------- - -UiProgram: UiImportListOpt UiRootMember ; -/. -case $rule_number: { - program = makeAstNode (driver->nodePool(), sym(1).UiImportList, - sym(2).UiObjectMemberList->finish()); - sym(1).UiProgram = program; -} break; -./ - -UiImportListOpt: Empty ; -UiImportListOpt: UiImportList ; -/. -case $rule_number: { - sym(1).Node = sym(1).UiImportList->finish(); -} break; -./ - -UiImportList: UiImport ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiImport); -} break; -./ - -UiImportList: UiImportList UiImport ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), - sym(1).UiImportList, sym(2).UiImport); -} break; -./ - -UiImport: T_IMPORT T_STRING_LITERAL T_AUTOMATIC_SEMICOLON; -UiImport: T_IMPORT T_STRING_LITERAL T_SEMICOLON; -/. -case $rule_number: { - AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).sval); - node->importToken = loc(1); - node->fileNameToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; -./ - -Empty: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -UiRootMember: UiObjectDefinition ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); -} break; -./ - -UiObjectMemberList: UiObjectMember ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); -} break; -./ - -UiObjectMemberList: UiObjectMemberList UiObjectMember ; -/. -case $rule_number: { - AST::UiObjectMemberList *node = makeAstNode (driver->nodePool(), - sym(1).UiObjectMemberList, sym(2).UiObjectMember); - sym(1).Node = node; -} break; -./ - -UiArrayMemberList: UiObjectDefinition ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); -} break; -./ - -UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; -/. -case $rule_number: { - AST::UiArrayMemberList *node = makeAstNode (driver->nodePool(), - sym(1).UiArrayMemberList, sym(3).UiObjectMember); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -UiObjectInitializer: T_LBRACE T_RBRACE ; -/. -case $rule_number: { - AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), (AST::UiObjectMemberList*)0); - node->lbraceToken = loc(1); - node->rbraceToken = loc(2); - sym(1).Node = node; -} break; -./ - -UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ; -/. -case $rule_number: { - AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), sym(2).UiObjectMemberList->finish()); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; -./ - -UiObjectDefinition: UiQualifiedId UiObjectInitializer ; -/. -case $rule_number: { - AST::UiObjectDefinition *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(2).UiObjectInitializer); - sym(1).Node = node; -} break; -./ - -UiObjectMember: UiObjectDefinition ; - -UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; -/. -case $rule_number: { - AST::UiArrayBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(4).UiArrayMemberList->finish()); - node->colonToken = loc(2); - node->lbracketToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; -./ - -UiMultilineStringLiteral: T_MULTILINE_STRING_LITERAL ; -/. -case $rule_number: { - AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; -./ - -UiMultilineStringStatement: UiMultilineStringLiteral T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -UiMultilineStringStatement: UiMultilineStringLiteral T_SEMICOLON ; -/. -case $rule_number: { - AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; -./ - - -UiObjectMember: UiQualifiedId T_COLON Expression UiObjectInitializer ; -/. -case $rule_number: { - if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { - AST::UiObjectBinding *node = makeAstNode (driver->nodePool(), - sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - sym(1).Node = node; - } else { - sym(1).Node = 0; - - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2), - QLatin1String("Expected a type name after token `:'"))); - - return false; // ### recover - } -} break; -./ - -UiObjectMember: UiQualifiedId T_COLON Block ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON EmptyStatement ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON DebuggerStatement ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON UiMultilineStringStatement ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding? -/.case $rule_number:./ - -/. -{ - AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(3).Statement); - node->colonToken = loc(2); - sym(1).Node = node; -} break; -./ - -UiPropertyType: T_VAR ; -/. -case $rule_number: -./ -UiPropertyType: T_RESERVED_WORD ; -/. -case $rule_number: { - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); - break; -} -./ - -UiPropertyType: T_IDENTIFIER ; - -UiObjectMember: T_SIGNAL T_IDENTIFIER ; -/. -case $rule_number: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); - node->type = AST::UiPublicMember::Signal; - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; -./ - -UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ; -/. -case $rule_number: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->semicolonToken = loc(4); - sym(1).Node = node; -} break; -./ - -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ; -/. -case $rule_number: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->semicolonToken = loc(5); - sym(1).Node = node; -} break; -./ - -UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ; -/. -case $rule_number: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, - sym(5).Expression); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->colonToken = loc(4); - node->semicolonToken = loc(6); - sym(1).Node = node; -} break; -./ - -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ; -/. -case $rule_number: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, - sym(6).Expression); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->colonToken = loc(5); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; -./ - -UiObjectMember: FunctionDeclaration ; -/. -case $rule_number: { - sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); -} break; -./ - -UiObjectMember: VariableStatement ; -/. -case $rule_number: { - sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); -} break; -./ - -UiQualifiedId: T_RESERVED_WORD ; -/.case $rule_number: ./ - -UiQualifiedId: T_RETURN ; -/. -case $rule_number: -{ - AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ - -JsIdentifier: T_IDENTIFIER; - -JsIdentifier: T_PROPERTY ; -/. -case $rule_number: { - QString s = QLatin1String(JavaScriptGrammar::spell[T_PROPERTY]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} -./ - -JsIdentifier: T_SIGNAL ; -/. -case $rule_number: { - QString s = QLatin1String(JavaScriptGrammar::spell[T_SIGNAL]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} -./ - --------------------------------------------------------------------------------------------------------- --- Expressions --------------------------------------------------------------------------------------------------------- - -PrimaryExpression: T_THIS ; -/. -case $rule_number: { - AST::ThisExpression *node = makeAstNode (driver->nodePool()); - node->thisToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: JsIdentifier ; -/. -case $rule_number: { - AST::IdentifierExpression *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_NULL ; -/. -case $rule_number: { - AST::NullExpression *node = makeAstNode (driver->nodePool()); - node->nullToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_TRUE ; -/. -case $rule_number: { - AST::TrueLiteral *node = makeAstNode (driver->nodePool()); - node->trueToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_FALSE ; -/. -case $rule_number: { - AST::FalseLiteral *node = makeAstNode (driver->nodePool()); - node->falseToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_NUMERIC_LITERAL ; -/. -case $rule_number: { - AST::NumericLiteral *node = makeAstNode (driver->nodePool(), sym(1).dval, lexer->flags); - node->literalToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_STRING_LITERAL ; -/. -case $rule_number: { - AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_DIVIDE_ ; -/: -#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number -:/ -/. -case $rule_number: { - bool rx = lexer->scanRegExp(Lexer::NoPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; // ### remove me - } - AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); - node->literalToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_DIVIDE_EQ ; -/: -#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number -:/ -/. -case $rule_number: { - bool rx = lexer->scanRegExp(Lexer::EqualPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; - } - AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); - node->literalToken = loc(1); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_LBRACKET T_RBRACKET ; -/. -case $rule_number: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), (AST::Elision *) 0); - node->lbracketToken = loc(1); - node->rbracketToken = loc(2); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; -/. -case $rule_number: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).Elision->finish()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ; -/. -case $rule_number: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish ()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; -/. -case $rule_number: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), - (AST::Elision *) 0); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; -/. -case $rule_number: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), - sym(4).Elision->finish()); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; -./ - --- PrimaryExpression: T_LBRACE T_RBRACE ; --- /. --- case $rule_number: { --- sym(1).Node = makeAstNode (driver->nodePool()); --- } break; --- ./ - -PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ; -/. -case $rule_number: { - AST::ObjectLiteral *node = 0; - if (sym(2).Node) - node = makeAstNode (driver->nodePool(), - sym(2).PropertyNameAndValueList->finish ()); - else - node = makeAstNode (driver->nodePool()); - node->lbraceToken = loc(1); - node->lbraceToken = loc(3); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ; -/. -case $rule_number: { - AST::ObjectLiteral *node = makeAstNode (driver->nodePool(), - sym(2).PropertyNameAndValueList->finish ()); - node->lbraceToken = loc(1); - node->lbraceToken = loc(4); - sym(1).Node = node; -} break; -./ - -PrimaryExpression: T_LPAREN Expression T_RPAREN ; -/. -case $rule_number: { - AST::NestedExpression *node = makeAstNode(driver->nodePool(), sym(2).Expression); - node->lparenToken = loc(1); - node->rparenToken = loc(3); - sym(1).Node = node; -} break; -./ - -UiQualifiedId: JsIdentifier ; -/. -case $rule_number: { - AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ - -UiQualifiedId: UiQualifiedId T_DOT JsIdentifier ; -/. -case $rule_number: { - AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; -./ - -ElementList: AssignmentExpression ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); -} break; -./ - -ElementList: Elision AssignmentExpression ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); -} break; -./ - -ElementList: ElementList T_COMMA AssignmentExpression ; -/. -case $rule_number: { - AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, - (AST::Elision *) 0, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -ElementList: ElementList T_COMMA Elision AssignmentExpression ; -/. -case $rule_number: { - AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), - sym(4).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -Elision: T_COMMA ; -/. -case $rule_number: { - AST::Elision *node = makeAstNode (driver->nodePool()); - node->commaToken = loc(1); - sym(1).Node = node; -} break; -./ - -Elision: Elision T_COMMA ; -/. -case $rule_number: { - AST::Elision *node = makeAstNode (driver->nodePool(), sym(1).Elision); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ; -/. -case $rule_number: { - AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), - sym(1).PropertyName, sym(3).Expression); - node->colonToken = loc(2); - sym(1).Node = node; -} break; -./ - -PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ; -/. -case $rule_number: { - AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), - sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); - node->commaToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; -./ - -PropertyName: T_IDENTIFIER %prec REDUCE_HERE ; -/. -case $rule_number: { - AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; -./ - -PropertyName: T_SIGNAL ; -/.case $rule_number:./ - -PropertyName: T_PROPERTY ; -/. -case $rule_number: { - AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; -./ - -PropertyName: T_STRING_LITERAL ; -/. -case $rule_number: { - AST::StringLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; -./ - -PropertyName: T_NUMERIC_LITERAL ; -/. -case $rule_number: { - AST::NumericLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).dval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; -./ - -PropertyName: ReservedIdentifier ; -/. -case $rule_number: { - AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; -./ - -ReservedIdentifier: T_BREAK ; -/. -case $rule_number: -./ -ReservedIdentifier: T_CASE ; -/. -case $rule_number: -./ -ReservedIdentifier: T_CATCH ; -/. -case $rule_number: -./ -ReservedIdentifier: T_CONTINUE ; -/. -case $rule_number: -./ -ReservedIdentifier: T_DEFAULT ; -/. -case $rule_number: -./ -ReservedIdentifier: T_DELETE ; -/. -case $rule_number: -./ -ReservedIdentifier: T_DO ; -/. -case $rule_number: -./ -ReservedIdentifier: T_ELSE ; -/. -case $rule_number: -./ -ReservedIdentifier: T_FALSE ; -/. -case $rule_number: -./ -ReservedIdentifier: T_FINALLY ; -/. -case $rule_number: -./ -ReservedIdentifier: T_FOR ; -/. -case $rule_number: -./ -ReservedIdentifier: T_FUNCTION ; -/. -case $rule_number: -./ -ReservedIdentifier: T_IF ; -/. -case $rule_number: -./ -ReservedIdentifier: T_IN ; -/. -case $rule_number: -./ -ReservedIdentifier: T_INSTANCEOF ; -/. -case $rule_number: -./ -ReservedIdentifier: T_NEW ; -/. -case $rule_number: -./ -ReservedIdentifier: T_NULL ; -/. -case $rule_number: -./ -ReservedIdentifier: T_RETURN ; -/. -case $rule_number: -./ -ReservedIdentifier: T_SWITCH ; -/. -case $rule_number: -./ -ReservedIdentifier: T_THIS ; -/. -case $rule_number: -./ -ReservedIdentifier: T_THROW ; -/. -case $rule_number: -./ -ReservedIdentifier: T_TRUE ; -/. -case $rule_number: -./ -ReservedIdentifier: T_TRY ; -/. -case $rule_number: -./ -ReservedIdentifier: T_TYPEOF ; -/. -case $rule_number: -./ -ReservedIdentifier: T_VAR ; -/. -case $rule_number: -./ -ReservedIdentifier: T_VOID ; -/. -case $rule_number: -./ -ReservedIdentifier: T_WHILE ; -/. -case $rule_number: -./ -ReservedIdentifier: T_CONST ; -/. -case $rule_number: -./ -ReservedIdentifier: T_DEBUGGER ; -/. -case $rule_number: -./ -ReservedIdentifier: T_RESERVED_WORD ; -/. -case $rule_number: -./ -ReservedIdentifier: T_WITH ; -/. -case $rule_number: -{ - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); -} break; -./ - -PropertyIdentifier: JsIdentifier ; -PropertyIdentifier: ReservedIdentifier ; - -MemberExpression: PrimaryExpression ; -MemberExpression: FunctionExpression ; - -MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ; -/. -case $rule_number: { - AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; -./ - -MemberExpression: MemberExpression T_DOT PropertyIdentifier ; -/. -case $rule_number: { - AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; -./ - -MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; -/. -case $rule_number: { - AST::NewMemberExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); - node->newToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - sym(1).Node = node; -} break; -./ - -NewExpression: MemberExpression ; - -NewExpression: T_NEW NewExpression ; -/. -case $rule_number: { - AST::NewExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->newToken = loc(1); - sym(1).Node = node; -} break; -./ - -CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; -/. -case $rule_number: { - AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; -./ - -CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ; -/. -case $rule_number: { - AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; -./ - -CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ; -/. -case $rule_number: { - AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; -./ - -CallExpression: CallExpression T_DOT PropertyIdentifier ; -/. -case $rule_number: { - AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; -./ - -ArgumentListOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -ArgumentListOpt: ArgumentList ; -/. -case $rule_number: { - sym(1).Node = sym(1).ArgumentList->finish(); -} break; -./ - -ArgumentList: AssignmentExpression ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Expression); -} break; -./ - -ArgumentList: ArgumentList T_COMMA AssignmentExpression ; -/. -case $rule_number: { - AST::ArgumentList *node = makeAstNode (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -LeftHandSideExpression: NewExpression ; -LeftHandSideExpression: CallExpression ; -PostfixExpression: LeftHandSideExpression ; - -PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ; -/. -case $rule_number: { - AST::PostIncrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->incrementToken = loc(2); - sym(1).Node = node; -} break; -./ - -PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ; -/. -case $rule_number: { - AST::PostDecrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->decrementToken = loc(2); - sym(1).Node = node; -} break; -./ - -UnaryExpression: PostfixExpression ; - -UnaryExpression: T_DELETE UnaryExpression ; -/. -case $rule_number: { - AST::DeleteExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->deleteToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_VOID UnaryExpression ; -/. -case $rule_number: { - AST::VoidExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->voidToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_TYPEOF UnaryExpression ; -/. -case $rule_number: { - AST::TypeOfExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->typeofToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_PLUS_PLUS UnaryExpression ; -/. -case $rule_number: { - AST::PreIncrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->incrementToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_MINUS_MINUS UnaryExpression ; -/. -case $rule_number: { - AST::PreDecrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->decrementToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_PLUS UnaryExpression ; -/. -case $rule_number: { - AST::UnaryPlusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->plusToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_MINUS UnaryExpression ; -/. -case $rule_number: { - AST::UnaryMinusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->minusToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_TILDE UnaryExpression ; -/. -case $rule_number: { - AST::TildeExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->tildeToken = loc(1); - sym(1).Node = node; -} break; -./ - -UnaryExpression: T_NOT UnaryExpression ; -/. -case $rule_number: { - AST::NotExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->notToken = loc(1); - sym(1).Node = node; -} break; -./ - -MultiplicativeExpression: UnaryExpression ; - -MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Mul, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Div, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Mod, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -AdditiveExpression: MultiplicativeExpression ; - -AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Add, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Sub, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -ShiftExpression: AdditiveExpression ; - -ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::LShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::RShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::URShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpression: ShiftExpression ; - -RelationalExpression: RelationalExpression T_LT ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpression: RelationalExpression T_GT ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpression: RelationalExpression T_LE ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpression: RelationalExpression T_GE ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpression: RelationalExpression T_IN ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::In, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpressionNotIn: ShiftExpression ; - -RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpression: RelationalExpression ; - -EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpressionNotIn: RelationalExpressionNotIn ; - -EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -BitwiseANDExpression: EqualityExpression ; - -BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -BitwiseANDExpressionNotIn: EqualityExpressionNotIn ; - -BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -BitwiseXORExpression: BitwiseANDExpression ; - -BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ; - -BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -BitwiseORExpression: BitwiseXORExpression ; - -BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ; - -BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -LogicalANDExpression: BitwiseORExpression ; - -LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ; - -LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -LogicalORExpression: LogicalANDExpression ; - -LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -LogicalORExpressionNotIn: LogicalANDExpressionNotIn ; - -LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -ConditionalExpression: LogicalORExpression ; - -ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ; -/. -case $rule_number: { - AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; -./ - -ConditionalExpressionNotIn: LogicalORExpressionNotIn ; - -ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ; -/. -case $rule_number: { - AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; -./ - -AssignmentExpression: ConditionalExpression ; - -AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -AssignmentExpressionNotIn: ConditionalExpressionNotIn ; - -AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ; -/. -case $rule_number: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; -./ - -AssignmentOperator: T_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::Assign; -} break; -./ - -AssignmentOperator: T_STAR_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceMul; -} break; -./ - -AssignmentOperator: T_DIVIDE_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceDiv; -} break; -./ - -AssignmentOperator: T_REMAINDER_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceMod; -} break; -./ - -AssignmentOperator: T_PLUS_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceAdd; -} break; -./ - -AssignmentOperator: T_MINUS_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceSub; -} break; -./ - -AssignmentOperator: T_LT_LT_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceLeftShift; -} break; -./ - -AssignmentOperator: T_GT_GT_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceRightShift; -} break; -./ - -AssignmentOperator: T_GT_GT_GT_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceURightShift; -} break; -./ - -AssignmentOperator: T_AND_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceAnd; -} break; -./ - -AssignmentOperator: T_XOR_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceXor; -} break; -./ - -AssignmentOperator: T_OR_EQ ; -/. -case $rule_number: { - sym(1).ival = QSOperator::InplaceOr; -} break; -./ - -Expression: AssignmentExpression ; - -Expression: Expression T_COMMA AssignmentExpression ; -/. -case $rule_number: { - AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -ExpressionOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -ExpressionOpt: Expression ; - -ExpressionNotIn: AssignmentExpressionNotIn ; - -ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ; -/. -case $rule_number: { - AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -ExpressionNotInOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -ExpressionNotInOpt: ExpressionNotIn ; - -Statement: Block ; -Statement: VariableStatement ; -Statement: EmptyStatement ; -Statement: ExpressionStatement ; -Statement: IfStatement ; -Statement: IterationStatement ; -Statement: ContinueStatement ; -Statement: BreakStatement ; -Statement: ReturnStatement ; -Statement: WithStatement ; -Statement: LabelledStatement ; -Statement: SwitchStatement ; -Statement: ThrowStatement ; -Statement: TryStatement ; -Statement: DebuggerStatement ; - - -Block: T_LBRACE StatementListOpt T_RBRACE ; -/. -case $rule_number: { - AST::Block *node = makeAstNode (driver->nodePool(), sym(2).StatementList); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; -./ - -StatementList: Statement ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); -} break; -./ - -StatementList: StatementList Statement ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).StatementList, sym(2).Statement); -} break; -./ - -StatementListOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -StatementListOpt: StatementList ; -/. -case $rule_number: { - sym(1).Node = sym(1).StatementList->finish (); -} break; -./ - -VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ; -/. -case $rule_number: { - AST::VariableStatement *node = makeAstNode (driver->nodePool(), - sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); - node->declarationKindToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; -./ - -VariableDeclarationKind: T_CONST ; -/. -case $rule_number: { - sym(1).ival = T_CONST; -} break; -./ - -VariableDeclarationKind: T_VAR ; -/. -case $rule_number: { - sym(1).ival = T_VAR; -} break; -./ - -VariableDeclarationList: VariableDeclaration ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); -} break; -./ - -VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ; -/. -case $rule_number: { - AST::VariableDeclarationList *node = makeAstNode (driver->nodePool(), - sym(1).VariableDeclarationList, sym(3).VariableDeclaration); - node->commaToken = loc(2); - sym(1).Node = node; -} break; -./ - -VariableDeclarationListNotIn: VariableDeclarationNotIn ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); -} break; -./ - -VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); -} break; -./ - -VariableDeclaration: JsIdentifier InitialiserOpt ; -/. -case $rule_number: { - AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ - -VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ; -/. -case $rule_number: { - AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ - -Initialiser: T_EQ AssignmentExpression ; -/. -case $rule_number: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; -./ - -InitialiserOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -InitialiserOpt: Initialiser ; - -InitialiserNotIn: T_EQ AssignmentExpressionNotIn ; -/. -case $rule_number: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; -./ - -InitialiserNotInOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -InitialiserNotInOpt: InitialiserNotIn ; - -EmptyStatement: T_SEMICOLON ; -/. -case $rule_number: { - AST::EmptyStatement *node = makeAstNode (driver->nodePool()); - node->semicolonToken = loc(1); - sym(1).Node = node; -} break; -./ - -ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ExpressionStatement: Expression T_SEMICOLON ; -/. -case $rule_number: { - AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; -./ - -IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ; -/. -case $rule_number: { - AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - node->elseToken = loc(5); - sym(1).Node = node; -} break; -./ - -IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ; -/. -case $rule_number: { - AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; -./ - - -IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ; -/. -case $rule_number: { - AST::DoWhileStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(5).Expression); - node->doToken = loc(1); - node->whileToken = loc(3); - node->lparenToken = loc(4); - node->rparenToken = loc(6); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; -./ - -IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ; -/. -case $rule_number: { - AST::WhileStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); - node->whileToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; -./ - -IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; -/. -case $rule_number: { - AST::ForStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, - sym(5).Expression, sym(7).Expression, sym(9).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->firstSemicolonToken = loc(4); - node->secondSemicolonToken = loc(6); - node->rparenToken = loc(8); - sym(1).Node = node; -} break; -./ - -IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; -/. -case $rule_number: { - AST::LocalForStatement *node = makeAstNode (driver->nodePool(), - sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, - sym(8).Expression, sym(10).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->firstSemicolonToken = loc(5); - node->secondSemicolonToken = loc(7); - node->rparenToken = loc(9); - sym(1).Node = node; -} break; -./ - -IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ; -/. -case $rule_number: { - AST:: ForEachStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, - sym(5).Expression, sym(7).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->inToken = loc(4); - node->rparenToken = loc(6); - sym(1).Node = node; -} break; -./ - -IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ; -/. -case $rule_number: { - AST::LocalForEachStatement *node = makeAstNode (driver->nodePool(), - sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->inToken = loc(5); - node->rparenToken = loc(7); - sym(1).Node = node; -} break; -./ - -ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ContinueStatement: T_CONTINUE T_SEMICOLON ; -/. -case $rule_number: { - AST::ContinueStatement *node = makeAstNode (driver->nodePool()); - node->continueToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; -./ - -ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ; -/. -case $rule_number: { - AST::ContinueStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); - node->continueToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; -./ - -BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -BreakStatement: T_BREAK T_SEMICOLON ; -/. -case $rule_number: { - AST::BreakStatement *node = makeAstNode (driver->nodePool()); - node->breakToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; -./ - -BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ; -/. -case $rule_number: { - AST::BreakStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); - node->breakToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; -./ - -ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ; -/. -case $rule_number: { - AST::ReturnStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->returnToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; -./ - -WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ; -/. -case $rule_number: { - AST::WithStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); - node->withToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; -./ - -SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ; -/. -case $rule_number: { - AST::SwitchStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); - node->switchToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; -./ - -CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ; -/. -case $rule_number: { - AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; -./ - -CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ; -/. -case $rule_number: { - AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(5); - sym(1).Node = node; -} break; -./ - -CaseClauses: CaseClause ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClause); -} break; -./ - -CaseClauses: CaseClauses CaseClause ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); -} break; -./ - -CaseClausesOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -CaseClausesOpt: CaseClauses ; -/. -case $rule_number: { - sym(1).Node = sym(1).CaseClauses->finish (); -} break; -./ - -CaseClause: T_CASE Expression T_COLON StatementListOpt ; -/. -case $rule_number: { - AST::CaseClause *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).StatementList); - node->caseToken = loc(1); - node->colonToken = loc(3); - sym(1).Node = node; -} break; -./ - -DefaultClause: T_DEFAULT T_COLON StatementListOpt ; -/. -case $rule_number: { - AST::DefaultClause *node = makeAstNode (driver->nodePool(), sym(3).StatementList); - node->defaultToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; -./ - -LabelledStatement: T_SIGNAL T_COLON Statement ; -/.case $rule_number:./ - -LabelledStatement: T_PROPERTY T_COLON Statement ; -/. -case $rule_number: { - AST::LabelledStatement *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); - node->identifierToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; -./ - -LabelledStatement: T_IDENTIFIER T_COLON Statement ; -/. -case $rule_number: { - AST::LabelledStatement *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(3).Statement); - node->identifierToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; -./ - -ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ThrowStatement: T_THROW Expression T_SEMICOLON ; -/. -case $rule_number: { - AST::ThrowStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->throwToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; -./ - -TryStatement: T_TRY Block Catch ; -/. -case $rule_number: { - AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch); - node->tryToken = loc(1); - sym(1).Node = node; -} break; -./ - -TryStatement: T_TRY Block Finally ; -/. -case $rule_number: { - AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; -./ - -TryStatement: T_TRY Block Catch Finally ; -/. -case $rule_number: { - AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; -./ - -Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ; -/. -case $rule_number: { - AST::Catch *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(5).Block); - node->catchToken = loc(1); - node->lparenToken = loc(2); - node->identifierToken = loc(3); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; -./ - -Finally: T_FINALLY Block ; -/. -case $rule_number: { - AST::Finally *node = makeAstNode (driver->nodePool(), sym(2).Block); - node->finallyToken = loc(1); - sym(1).Node = node; -} break; -./ - -DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -DebuggerStatement: T_DEBUGGER T_SEMICOLON ; -/. -case $rule_number: { - AST::DebuggerStatement *node = makeAstNode (driver->nodePool()); - node->debuggerToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; -./ - -FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; -/. -case $rule_number: { - AST::FunctionDeclaration *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; -./ - -FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; -/. -case $rule_number: { - AST::FunctionExpression *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - if (sym(2).sval) - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; -./ - -FormalParameterList: JsIdentifier ; -/. -case $rule_number: { - AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ - -FormalParameterList: FormalParameterList T_COMMA JsIdentifier ; -/. -case $rule_number: { - AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); - node->commaToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; -./ - -FormalParameterListOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -FormalParameterListOpt: FormalParameterList ; -/. -case $rule_number: { - sym(1).Node = sym(1).FormalParameterList->finish (); -} break; -./ - -FunctionBodyOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -FunctionBodyOpt: FunctionBody ; - -FunctionBody: SourceElements ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); -} break; -./ - ---JavaScriptProgram: SourceElements ; ---/. ---case $rule_number: { --- sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); --- driver->changeAbstractSyntaxTree(sym(1).Node); ---} break; ---./ - -SourceElements: SourceElement ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElement); -} break; -./ - -SourceElements: SourceElements SourceElement ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); -} break; -./ - -SourceElement: Statement ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); -} break; -./ - -SourceElement: FunctionDeclaration ; -/. -case $rule_number: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).FunctionDeclaration); -} break; -./ - -IdentifierOpt: ; -/. -case $rule_number: { - sym(1).sval = 0; -} break; -./ - -IdentifierOpt: JsIdentifier ; - -PropertyNameAndValueListOpt: ; -/. -case $rule_number: { - sym(1).Node = 0; -} break; -./ - -PropertyNameAndValueListOpt: PropertyNameAndValueList ; - -/. - } // switch - action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); - } // if - } while (action != 0); - - if (first_token == last_token) { - const int errorState = state_stack[tos]; - - // automatic insertion of `;' - if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { - SavedToken &tk = token_buffer[0]; - tk.token = yytoken; - tk.dval = yylval; - tk.loc = yylloc; - - yylloc = yyprevlloc; - yylloc.offset += yylloc.length; - yylloc.startColumn += yylloc.length; - yylloc.length = 0; - - //const QString msg = QString::fromUtf8("Missing `;'"); - //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); - - first_token = &token_buffer[0]; - last_token = &token_buffer[1]; - - yytoken = T_SEMICOLON; - yylval = 0; - - action = errorState; - - goto _Lcheck_token; - } - - hadErrors = true; - - token_buffer[0].token = yytoken; - token_buffer[0].dval = yylval; - token_buffer[0].loc = yylloc; - - token_buffer[1].token = yytoken = lexer->lex(); - token_buffer[1].dval = yylval = lexer->dval(); - token_buffer[1].loc = yylloc = location(lexer); - - if (t_action(errorState, yytoken)) { - const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - action = errorState; - goto _Lcheck_token; - } - - static int tokens[] = { - T_PLUS, - T_EQ, - - T_COMMA, - T_COLON, - T_SEMICOLON, - - T_RPAREN, T_RBRACKET, T_RBRACE, - - T_NUMERIC_LITERAL, - T_IDENTIFIER, - - T_LPAREN, T_LBRACKET, T_LBRACE, - - EOF_SYMBOL - }; - - for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { - int a = t_action(errorState, *tk); - if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - yytoken = *tk; - yylval = 0; - yylloc = token_buffer[0].loc; - yylloc.length = 0; - - first_token = &token_buffer[0]; - last_token = &token_buffer[2]; - - action = errorState; - goto _Lcheck_token; - } - } - - for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { - if (tk == T_AUTOMATIC_SEMICOLON) - continue; - - int a = t_action(errorState, tk); - if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - yytoken = tk; - yylval = 0; - yylloc = token_buffer[0].loc; - yylloc.length = 0; - - action = errorState; - goto _Lcheck_token; - } - } - - const QString msg = QString::fromUtf8("Syntax error"); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - } - - return false; -} - -QT_END_NAMESPACE - - -./ -/: -QT_END_NAMESPACE - - - -#endif // JAVASCRIPTPARSER_P_H -:/ diff --git a/src/declarative/qml/parser/javascriptast.cpp b/src/declarative/qml/parser/javascriptast.cpp deleted file mode 100644 index ada19d5..0000000 --- a/src/declarative/qml/parser/javascriptast.cpp +++ /dev/null @@ -1,962 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 "javascriptast_p.h" - - - -#include "javascriptastvisitor_p.h" - -QT_BEGIN_NAMESPACE - -namespace JavaScript { namespace AST { - -int NumericLiteral::suffixLength[] = { - 0, // noSuffix - 2, // emSuffix - 2, // exSuffix - 2, // pxSuffix - 2, // cmSuffix - 2, // mmSuffix - 2, // inSuffix - 2, // ptSuffix - 2, // pcSuffix - 3, // degSuffix - 3, // radSuffix - 4, // gradSuffix - 2, // msSuffix - 1, // sSuffix - 2, // hzSuffix - 3 // khzSuffix -}; - -const char *const NumericLiteral::suffixSpell[] = { - "", - "em", - "ex", - "px", - "cm", - "mm", - "in", - "pt", - "pc", - "deg", - "rad", - "grad", - "ms", - "s", - "hz", - "khz" -}; - -ExpressionNode *Node::expressionCast() -{ - return 0; -} - -BinaryExpression *Node::binaryExpressionCast() -{ - return 0; -} - -Statement *Node::statementCast() -{ - return 0; -} - -ExpressionNode *ExpressionNode::expressionCast() -{ - return this; -} - -BinaryExpression *BinaryExpression::binaryExpressionCast() -{ - return this; -} - -Statement *Statement::statementCast() -{ - return this; -} - -void NestedExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - visitor->endVisit(this); -} - -void ThisExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void IdentifierExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void NullExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void TrueLiteral::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void FalseLiteral::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void StringLiteral::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void NumericLiteral::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void RegExpLiteral::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void ArrayLiteral::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(elements, visitor); - acceptChild(elision, visitor); - } - - visitor->endVisit(this); -} - -void ObjectLiteral::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(properties, visitor); - } - - visitor->endVisit(this); -} - -void ElementList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - ElementList *it = this; - do { - acceptChild(it->elision, visitor); - acceptChild(it->expression, visitor); - it = it->next; - } while (it); - } - - visitor->endVisit(this); -} - -void Elision::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - // ### - } - - visitor->endVisit(this); -} - -void PropertyNameAndValueList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - PropertyNameAndValueList *it = this; - do { - acceptChild(it->name, visitor); - acceptChild(it->value, visitor); - it = it->next; - } while (it); - } - - visitor->endVisit(this); -} - -void IdentifierPropertyName::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void StringLiteralPropertyName::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void NumericLiteralPropertyName::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void ArrayMemberExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(base, visitor); - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void FieldMemberExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(base, visitor); - } - - visitor->endVisit(this); -} - -void NewMemberExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(base, visitor); - acceptChild(arguments, visitor); - } - - visitor->endVisit(this); -} - -void NewExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void CallExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(base, visitor); - acceptChild(arguments, visitor); - } - - visitor->endVisit(this); -} - -void ArgumentList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - ArgumentList *it = this; - do { - acceptChild(it->expression, visitor); - it = it->next; - } while (it); - } - - visitor->endVisit(this); -} - -void PostIncrementExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(base, visitor); - } - - visitor->endVisit(this); -} - -void PostDecrementExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(base, visitor); - } - - visitor->endVisit(this); -} - -void DeleteExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void VoidExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void TypeOfExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void PreIncrementExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void PreDecrementExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void UnaryPlusExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void UnaryMinusExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void TildeExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void NotExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void BinaryExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(left, visitor); - acceptChild(right, visitor); - } - - visitor->endVisit(this); -} - -void ConditionalExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - acceptChild(ok, visitor); - acceptChild(ko, visitor); - } - - visitor->endVisit(this); -} - -void Expression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(left, visitor); - acceptChild(right, visitor); - } - - visitor->endVisit(this); -} - -void Block::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statements, visitor); - } - - visitor->endVisit(this); -} - -void StatementList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - StatementList *it = this; - do { - acceptChild(it->statement, visitor); - it = it->next; - } while (it); - } - - visitor->endVisit(this); -} - -void VariableStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(declarations, visitor); - } - - visitor->endVisit(this); -} - -void VariableDeclarationList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - VariableDeclarationList *it = this; - do { - acceptChild(it->declaration, visitor); - it = it->next; - } while (it); - } - - visitor->endVisit(this); -} - -void VariableDeclaration::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void EmptyStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void ExpressionStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void IfStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - acceptChild(ok, visitor); - acceptChild(ko, visitor); - } - - visitor->endVisit(this); -} - -void DoWhileStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statement, visitor); - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void WhileStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void ForStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(initialiser, visitor); - acceptChild(condition, visitor); - acceptChild(expression, visitor); - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void LocalForStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(declarations, visitor); - acceptChild(condition, visitor); - acceptChild(expression, visitor); - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void ForEachStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(initialiser, visitor); - acceptChild(expression, visitor); - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void LocalForEachStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(declaration, visitor); - acceptChild(expression, visitor); - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void ContinueStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void BreakStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void ReturnStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void WithStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void SwitchStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - acceptChild(block, visitor); - } - - visitor->endVisit(this); -} - -void CaseBlock::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(clauses, visitor); - acceptChild(defaultClause, visitor); - acceptChild(moreClauses, visitor); - } - - visitor->endVisit(this); -} - -void CaseClauses::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - CaseClauses *it = this; - do { - acceptChild(it->clause, visitor); - it = it->next; - } while (it); - } - - visitor->endVisit(this); -} - -void CaseClause::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - acceptChild(statements, visitor); - } - - visitor->endVisit(this); -} - -void DefaultClause::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statements, visitor); - } - - visitor->endVisit(this); -} - -void LabelledStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void ThrowStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void TryStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statement, visitor); - acceptChild(catchExpression, visitor); - acceptChild(finallyExpression, visitor); - } - - visitor->endVisit(this); -} - -void Catch::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void Finally::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void FunctionDeclaration::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(formals, visitor); - acceptChild(body, visitor); - } - - visitor->endVisit(this); -} - -void FunctionExpression::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(formals, visitor); - acceptChild(body, visitor); - } - - visitor->endVisit(this); -} - -void FormalParameterList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - // ### - } - - visitor->endVisit(this); -} - -void FunctionBody::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(elements, visitor); - } - - visitor->endVisit(this); -} - -void Program::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(elements, visitor); - } - - visitor->endVisit(this); -} - -void SourceElements::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - SourceElements *it = this; - do { - acceptChild(it->element, visitor); - it = it->next; - } while (it); - } - - visitor->endVisit(this); -} - -void FunctionSourceElement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(declaration, visitor); - } - - visitor->endVisit(this); -} - -void StatementSourceElement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void DebuggerStatement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - - -void UiProgram::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - for (UiObjectMemberList *it = members; it; it = it->next) - acceptChild(it->member, visitor); - } - - visitor->endVisit(this); -} - -void UiPublicMember::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(expression, visitor); - } - - visitor->endVisit(this); -} - -void UiObjectDefinition::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(qualifiedTypeNameId, visitor); - acceptChild(initializer, visitor); - } - - visitor->endVisit(this); -} - -void UiObjectInitializer::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - for (UiObjectMemberList *it = members; it; it = it->next) - acceptChild(it->member, visitor); - } - - visitor->endVisit(this); -} - -void UiObjectBinding::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(qualifiedId, visitor); - acceptChild(qualifiedTypeNameId, visitor); - acceptChild(initializer, visitor); - } - - visitor->endVisit(this); -} - -void UiScriptBinding::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(qualifiedId, visitor); - acceptChild(statement, visitor); - } - - visitor->endVisit(this); -} - -void UiArrayBinding::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(qualifiedId, visitor); - for (UiArrayMemberList *it = members; it; it = it->next) - acceptChild(it->member, visitor); - } - - visitor->endVisit(this); -} - -void UiObjectMemberList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - for (UiObjectMemberList *it = this; it; it = it->next) - acceptChild(it->member, visitor); - } - - visitor->endVisit(this); -} - -void UiArrayMemberList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - for (UiArrayMemberList *it = this; it; it = it->next) - acceptChild(it->member, visitor); - } - - visitor->endVisit(this); -} - -void UiQualifiedId::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void UiImport::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - } - - visitor->endVisit(this); -} - -void UiImportList::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(import, visitor); - acceptChild(next, visitor); - } - - visitor->endVisit(this); -} - -void UiSourceElement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - acceptChild(sourceElement, visitor); - } - - visitor->endVisit(this); -} - -} } // namespace JavaScript::AST - -QT_END_NAMESPACE - - diff --git a/src/declarative/qml/parser/javascriptast_p.h b/src/declarative/qml/parser/javascriptast_p.h deleted file mode 100644 index 8c1e2bc..0000000 --- a/src/declarative/qml/parser/javascriptast_p.h +++ /dev/null @@ -1,2544 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 JAVASCRIPTAST_P_H -#define JAVASCRIPTAST_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "javascriptastvisitor_p.h" -#include - -QT_BEGIN_NAMESPACE - -#define JAVASCRIPT_DECLARE_AST_NODE(name) \ - enum { K = Kind_##name }; - -namespace QSOperator // ### rename -{ - -enum Op { - Add, - And, - InplaceAnd, - Assign, - BitAnd, - BitOr, - BitXor, - InplaceSub, - Div, - InplaceDiv, - Equal, - Ge, - Gt, - In, - InplaceAdd, - InstanceOf, - Le, - LShift, - InplaceLeftShift, - Lt, - Mod, - InplaceMod, - Mul, - InplaceMul, - NotEqual, - Or, - InplaceOr, - RShift, - InplaceRightShift, - StrictEqual, - StrictNotEqual, - Sub, - URShift, - InplaceURightShift, - InplaceXor -}; - -} // namespace QSOperator - -namespace JavaScript { -class NameId; -namespace AST { - -template -_T1 cast(_T2 *ast) -{ - if (ast && ast->kind == static_cast<_T1>(0)->K) - return static_cast<_T1>(ast); - - return 0; -} - -class Node -{ -public: - enum Kind { - Kind_Undefined, - - Kind_ArgumentList, - Kind_ArrayLiteral, - Kind_ArrayMemberExpression, - Kind_BinaryExpression, - Kind_Block, - Kind_BreakStatement, - Kind_CallExpression, - Kind_CaseBlock, - Kind_CaseClause, - Kind_CaseClauses, - Kind_Catch, - Kind_ConditionalExpression, - Kind_ContinueStatement, - Kind_DebuggerStatement, - Kind_DefaultClause, - Kind_DeleteExpression, - Kind_DoWhileStatement, - Kind_ElementList, - Kind_Elision, - Kind_EmptyStatement, - Kind_Expression, - Kind_ExpressionStatement, - Kind_FalseLiteral, - Kind_FieldMemberExpression, - Kind_Finally, - Kind_ForEachStatement, - Kind_ForStatement, - Kind_FormalParameterList, - Kind_FunctionBody, - Kind_FunctionDeclaration, - Kind_FunctionExpression, - Kind_FunctionSourceElement, - Kind_IdentifierExpression, - Kind_IdentifierPropertyName, - Kind_IfStatement, - Kind_LabelledStatement, - Kind_LocalForEachStatement, - Kind_LocalForStatement, - Kind_NewExpression, - Kind_NewMemberExpression, - Kind_NotExpression, - Kind_NullExpression, - Kind_NumericLiteral, - Kind_NumericLiteralPropertyName, - Kind_ObjectLiteral, - Kind_PostDecrementExpression, - Kind_PostIncrementExpression, - Kind_PreDecrementExpression, - Kind_PreIncrementExpression, - Kind_Program, - Kind_PropertyName, - Kind_PropertyNameAndValueList, - Kind_RegExpLiteral, - Kind_ReturnStatement, - Kind_SourceElement, - Kind_SourceElements, - Kind_StatementList, - Kind_StatementSourceElement, - Kind_StringLiteral, - Kind_StringLiteralPropertyName, - Kind_SwitchStatement, - Kind_ThisExpression, - Kind_ThrowStatement, - Kind_TildeExpression, - Kind_TrueLiteral, - Kind_TryStatement, - Kind_TypeOfExpression, - Kind_UnaryMinusExpression, - Kind_UnaryPlusExpression, - Kind_VariableDeclaration, - Kind_VariableDeclarationList, - Kind_VariableStatement, - Kind_VoidExpression, - Kind_WhileStatement, - Kind_WithStatement, - Kind_NestedExpression, - - Kind_UiArrayBinding, - Kind_UiImport, - Kind_UiImportList, - Kind_UiObjectBinding, - Kind_UiObjectDefinition, - Kind_UiObjectInitializer, - Kind_UiObjectMemberList, - Kind_UiArrayMemberList, - Kind_UiProgram, - Kind_UiPublicMember, - Kind_UiQualifiedId, - Kind_UiScriptBinding, - Kind_UiSourceElement - }; - - inline Node() - : kind(Kind_Undefined) {} - - virtual ~Node() {} - - virtual ExpressionNode *expressionCast(); - virtual BinaryExpression *binaryExpressionCast(); - virtual Statement *statementCast(); - - inline void accept(Visitor *visitor) - { - if (visitor->preVisit(this)) { - accept0(visitor); - visitor->postVisit(this); - } - } - - static void acceptChild(Node *node, Visitor *visitor) - { - if (node) - node->accept(visitor); - } - - virtual void accept0(Visitor *visitor) = 0; - -// attributes - int kind; -}; - -class ExpressionNode: public Node -{ -public: - ExpressionNode() {} - virtual ~ExpressionNode() {} - - virtual ExpressionNode *expressionCast(); - - virtual SourceLocation firstSourceLocation() const = 0; - virtual SourceLocation lastSourceLocation() const = 0; -}; - -class Statement: public Node -{ -public: - Statement() {} - virtual ~Statement() {} - - virtual Statement *statementCast(); - - virtual SourceLocation firstSourceLocation() const = 0; - virtual SourceLocation lastSourceLocation() const = 0; -}; - -class NestedExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(NestedExpression) - - NestedExpression(ExpressionNode *expression) - : expression(expression) - { kind = K; } - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return lparenToken; } - - virtual SourceLocation lastSourceLocation() const - { return rparenToken; } - -// attributes - ExpressionNode *expression; - SourceLocation lparenToken; - SourceLocation rparenToken; -}; - -class ThisExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ThisExpression) - - ThisExpression() { kind = K; } - virtual ~ThisExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return thisToken; } - - virtual SourceLocation lastSourceLocation() const - { return thisToken; } - -// attributes - SourceLocation thisToken; -}; - -class IdentifierExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(IdentifierExpression) - - IdentifierExpression(NameId *n): - name (n) { kind = K; } - - virtual ~IdentifierExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return identifierToken; } - - virtual SourceLocation lastSourceLocation() const - { return identifierToken; } - -// attributes - NameId *name; - SourceLocation identifierToken; -}; - -class NullExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(NullExpression) - - NullExpression() { kind = K; } - virtual ~NullExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return nullToken; } - - virtual SourceLocation lastSourceLocation() const - { return nullToken; } - -// attributes - SourceLocation nullToken; -}; - -class TrueLiteral: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(TrueLiteral) - - TrueLiteral() { kind = K; } - virtual ~TrueLiteral() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return trueToken; } - - virtual SourceLocation lastSourceLocation() const - { return trueToken; } - -// attributes - SourceLocation trueToken; -}; - -class FalseLiteral: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(FalseLiteral) - - FalseLiteral() { kind = K; } - virtual ~FalseLiteral() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return falseToken; } - - virtual SourceLocation lastSourceLocation() const - { return falseToken; } - -// attributes - SourceLocation falseToken; -}; - -class NumericLiteral: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(NumericLiteral) - - enum Suffix { // ### keep it in sync with the Suffix enum in javascriptlexer_p.h - noSuffix, - emSuffix, - exSuffix, - pxSuffix, - cmSuffix, - mmSuffix, - inSuffix, - ptSuffix, - pcSuffix, - degSuffix, - radSuffix, - gradSuffix, - msSuffix, - sSuffix, - hzSuffix, - khzSuffix - }; - - static int suffixLength[]; - static const char *const suffixSpell[]; - - NumericLiteral(double v, int suffix): - value(v), suffix(suffix) { kind = K; } - virtual ~NumericLiteral() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return literalToken; } - - virtual SourceLocation lastSourceLocation() const - { return literalToken; } - -// attributes: - double value; - int suffix; - SourceLocation literalToken; -}; - -class StringLiteral: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(StringLiteral) - - StringLiteral(NameId *v): - value (v) { kind = K; } - - virtual ~StringLiteral() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return literalToken; } - - virtual SourceLocation lastSourceLocation() const - { return literalToken; } - -// attributes: - NameId *value; - SourceLocation literalToken; -}; - -class RegExpLiteral: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(RegExpLiteral) - - RegExpLiteral(NameId *p, int f): - pattern (p), flags (f) { kind = K; } - - virtual ~RegExpLiteral() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return literalToken; } - - virtual SourceLocation lastSourceLocation() const - { return literalToken; } - -// attributes: - NameId *pattern; - int flags; - SourceLocation literalToken; -}; - -class ArrayLiteral: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ArrayLiteral) - - ArrayLiteral(Elision *e): - elements (0), elision (e) - { kind = K; } - - ArrayLiteral(ElementList *elts): - elements (elts), elision (0) - { kind = K; } - - ArrayLiteral(ElementList *elts, Elision *e): - elements (elts), elision (e) - { kind = K; } - - virtual ~ArrayLiteral() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return lbracketToken; } - - virtual SourceLocation lastSourceLocation() const - { return rbracketToken; } - -// attributes - ElementList *elements; - Elision *elision; - SourceLocation lbracketToken; - SourceLocation commaToken; - SourceLocation rbracketToken; -}; - -class ObjectLiteral: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ObjectLiteral) - - ObjectLiteral(): - properties (0) { kind = K; } - - ObjectLiteral(PropertyNameAndValueList *plist): - properties (plist) { kind = K; } - - virtual ~ObjectLiteral() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return lbraceToken; } - - virtual SourceLocation lastSourceLocation() const - { return rbraceToken; } - -// attributes - PropertyNameAndValueList *properties; - SourceLocation lbraceToken; - SourceLocation rbraceToken; -}; - -class ElementList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ElementList) - - ElementList(Elision *e, ExpressionNode *expr): - elision (e), expression (expr), next (this) - { kind = K; } - - ElementList(ElementList *previous, Elision *e, ExpressionNode *expr): - elision (e), expression (expr) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~ElementList() {} - - inline ElementList *finish () - { - ElementList *front = next; - next = 0; - return front; - } - - virtual void accept0(Visitor *visitor); - -// attributes - Elision *elision; - ExpressionNode *expression; - ElementList *next; - SourceLocation commaToken; -}; - -class Elision: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(Elision) - - Elision(): - next (this) { kind = K; } - - Elision(Elision *previous) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~Elision() {} - - virtual void accept0(Visitor *visitor); - - inline Elision *finish () - { - Elision *front = next; - next = 0; - return front; - } - -// attributes - Elision *next; - SourceLocation commaToken; -}; - -class PropertyNameAndValueList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(PropertyNameAndValueList) - - PropertyNameAndValueList(PropertyName *n, ExpressionNode *v): - name (n), value (v), next (this) - { kind = K; } - - PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v): - name (n), value (v) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~PropertyNameAndValueList() {} - - virtual void accept0(Visitor *visitor); - - inline PropertyNameAndValueList *finish () - { - PropertyNameAndValueList *front = next; - next = 0; - return front; - } - -// attributes - PropertyName *name; - ExpressionNode *value; - PropertyNameAndValueList *next; - SourceLocation colonToken; - SourceLocation commaToken; -}; - -class PropertyName: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(PropertyName) - - PropertyName() { kind = K; } - virtual ~PropertyName() {} - -// attributes - SourceLocation propertyNameToken; -}; - -class IdentifierPropertyName: public PropertyName -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(IdentifierPropertyName) - - IdentifierPropertyName(NameId *n): - id (n) { kind = K; } - - virtual ~IdentifierPropertyName() {} - - virtual void accept0(Visitor *visitor); - -// attributes - NameId *id; -}; - -class StringLiteralPropertyName: public PropertyName -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(StringLiteralPropertyName) - - StringLiteralPropertyName(NameId *n): - id (n) { kind = K; } - virtual ~StringLiteralPropertyName() {} - - virtual void accept0(Visitor *visitor); - -// attributes - NameId *id; -}; - -class NumericLiteralPropertyName: public PropertyName -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(NumericLiteralPropertyName) - - NumericLiteralPropertyName(double n): - id (n) { kind = K; } - virtual ~NumericLiteralPropertyName() {} - - virtual void accept0(Visitor *visitor); - -// attributes - double id; -}; - -class ArrayMemberExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ArrayMemberExpression) - - ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e): - base (b), expression (e) - { kind = K; } - - virtual ~ArrayMemberExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return base->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return rbracketToken; } - -// attributes - ExpressionNode *base; - ExpressionNode *expression; - SourceLocation lbracketToken; - SourceLocation rbracketToken; -}; - -class FieldMemberExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(FieldMemberExpression) - - FieldMemberExpression(ExpressionNode *b, NameId *n): - base (b), name (n) - { kind = K; } - - virtual ~FieldMemberExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return base->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return identifierToken; } - - // attributes - ExpressionNode *base; - NameId *name; - SourceLocation dotToken; - SourceLocation identifierToken; -}; - -class NewMemberExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(NewMemberExpression) - - NewMemberExpression(ExpressionNode *b, ArgumentList *a): - base (b), arguments (a) - { kind = K; } - - virtual ~NewMemberExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return newToken; } - - virtual SourceLocation lastSourceLocation() const - { return rparenToken; } - - // attributes - ExpressionNode *base; - ArgumentList *arguments; - SourceLocation newToken; - SourceLocation lparenToken; - SourceLocation rparenToken; -}; - -class NewExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(NewExpression) - - NewExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~NewExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return newToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation newToken; -}; - -class CallExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(CallExpression) - - CallExpression(ExpressionNode *b, ArgumentList *a): - base (b), arguments (a) - { kind = K; } - - virtual ~CallExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return base->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return rparenToken; } - -// attributes - ExpressionNode *base; - ArgumentList *arguments; - SourceLocation lparenToken; - SourceLocation rparenToken; -}; - -class ArgumentList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ArgumentList) - - ArgumentList(ExpressionNode *e): - expression (e), next (this) - { kind = K; } - - ArgumentList(ArgumentList *previous, ExpressionNode *e): - expression (e) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~ArgumentList() {} - - virtual void accept0(Visitor *visitor); - - inline ArgumentList *finish () - { - ArgumentList *front = next; - next = 0; - return front; - } - -// attributes - ExpressionNode *expression; - ArgumentList *next; - SourceLocation commaToken; -}; - -class PostIncrementExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(PostIncrementExpression) - - PostIncrementExpression(ExpressionNode *b): - base (b) { kind = K; } - - virtual ~PostIncrementExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return base->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return incrementToken; } - -// attributes - ExpressionNode *base; - SourceLocation incrementToken; -}; - -class PostDecrementExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(PostDecrementExpression) - - PostDecrementExpression(ExpressionNode *b): - base (b) { kind = K; } - - virtual ~PostDecrementExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return base->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return decrementToken; } - -// attributes - ExpressionNode *base; - SourceLocation decrementToken; -}; - -class DeleteExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(DeleteExpression) - - DeleteExpression(ExpressionNode *e): - expression (e) { kind = K; } - virtual ~DeleteExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return deleteToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation deleteToken; -}; - -class VoidExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(VoidExpression) - - VoidExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~VoidExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return voidToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation voidToken; -}; - -class TypeOfExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(TypeOfExpression) - - TypeOfExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~TypeOfExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return typeofToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation typeofToken; -}; - -class PreIncrementExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(PreIncrementExpression) - - PreIncrementExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~PreIncrementExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return incrementToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation incrementToken; -}; - -class PreDecrementExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(PreDecrementExpression) - - PreDecrementExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~PreDecrementExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return decrementToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation decrementToken; -}; - -class UnaryPlusExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UnaryPlusExpression) - - UnaryPlusExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~UnaryPlusExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return plusToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation plusToken; -}; - -class UnaryMinusExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UnaryMinusExpression) - - UnaryMinusExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~UnaryMinusExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return minusToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation minusToken; -}; - -class TildeExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(TildeExpression) - - TildeExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~TildeExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return tildeToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation tildeToken; -}; - -class NotExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(NotExpression) - - NotExpression(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~NotExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return notToken; } - - virtual SourceLocation lastSourceLocation() const - { return expression->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - SourceLocation notToken; -}; - -class BinaryExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(BinaryExpression) - - BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r): - left (l), op (o), right (r) - { kind = K; } - - virtual ~BinaryExpression() {} - - virtual BinaryExpression *binaryExpressionCast(); - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return left->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return right->lastSourceLocation(); } - -// attributes - ExpressionNode *left; - int op; - ExpressionNode *right; - SourceLocation operatorToken; -}; - -class ConditionalExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ConditionalExpression) - - ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f): - expression (e), ok (t), ko (f) - { kind = K; } - - virtual ~ConditionalExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return expression->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return ko->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - ExpressionNode *ok; - ExpressionNode *ko; - SourceLocation questionToken; - SourceLocation colonToken; -}; - -class Expression: public ExpressionNode // ### rename -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(Expression) - - Expression(ExpressionNode *l, ExpressionNode *r): - left (l), right (r) { kind = K; } - - virtual ~Expression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return left->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return right->lastSourceLocation(); } - -// attributes - ExpressionNode *left; - ExpressionNode *right; - SourceLocation commaToken; -}; - -class Block: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(Block) - - Block(StatementList *slist): - statements (slist) { kind = K; } - - virtual ~Block() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return lbraceToken; } - - virtual SourceLocation lastSourceLocation() const - { return rbraceToken; } - - // attributes - StatementList *statements; - SourceLocation lbraceToken; - SourceLocation rbraceToken; -}; - -class StatementList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(StatementList) - - StatementList(Statement *stmt): - statement (stmt), next (this) - { kind = K; } - - StatementList(StatementList *previous, Statement *stmt): - statement (stmt) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~StatementList() {} - - virtual void accept0(Visitor *visitor); - - inline StatementList *finish () - { - StatementList *front = next; - next = 0; - return front; - } - -// attributes - Statement *statement; - StatementList *next; -}; - -class VariableStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(VariableStatement) - - VariableStatement(VariableDeclarationList *vlist): - declarations (vlist) - { kind = K; } - - virtual ~VariableStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return declarationKindToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - -// attributes - VariableDeclarationList *declarations; - SourceLocation declarationKindToken; - SourceLocation semicolonToken; -}; - -class VariableDeclaration: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(VariableDeclaration) - - VariableDeclaration(NameId *n, ExpressionNode *e): - name (n), expression (e), readOnly(false) - { kind = K; } - - virtual ~VariableDeclaration() {} - - virtual void accept0(Visitor *visitor); - -// attributes - NameId *name; - ExpressionNode *expression; - bool readOnly; - SourceLocation identifierToken; -}; - -class VariableDeclarationList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(VariableDeclarationList) - - VariableDeclarationList(VariableDeclaration *decl): - declaration (decl), next (this) - { kind = K; } - - VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl): - declaration (decl) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~VariableDeclarationList() {} - - virtual void accept0(Visitor *visitor); - - inline VariableDeclarationList *finish (bool readOnly) - { - VariableDeclarationList *front = next; - next = 0; - if (readOnly) { - VariableDeclarationList *vdl; - for (vdl = front; vdl != 0; vdl = vdl->next) - vdl->declaration->readOnly = true; - } - return front; - } - -// attributes - VariableDeclaration *declaration; - VariableDeclarationList *next; - SourceLocation commaToken; -}; - -class EmptyStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(EmptyStatement) - - EmptyStatement() { kind = K; } - virtual ~EmptyStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return semicolonToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - -// attributes - SourceLocation semicolonToken; -}; - -class ExpressionStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ExpressionStatement) - - ExpressionStatement(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~ExpressionStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return expression->firstSourceLocation(); } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - -// attributes - ExpressionNode *expression; - SourceLocation semicolonToken; -}; - -class IfStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(IfStatement) - - IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0): - expression (e), ok (t), ko (f) - { kind = K; } - - virtual ~IfStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return ifToken; } - - virtual SourceLocation lastSourceLocation() const - { - if (ko) - return ko->lastSourceLocation(); - - return ok->lastSourceLocation(); - } - -// attributes - ExpressionNode *expression; - Statement *ok; - Statement *ko; - SourceLocation ifToken; - SourceLocation lparenToken; - SourceLocation rparenToken; - SourceLocation elseToken; -}; - -class DoWhileStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(DoWhileStatement) - - DoWhileStatement(Statement *stmt, ExpressionNode *e): - statement (stmt), expression (e) - { kind = K; } - - virtual ~DoWhileStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return doToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - -// attributes - Statement *statement; - ExpressionNode *expression; - SourceLocation doToken; - SourceLocation whileToken; - SourceLocation lparenToken; - SourceLocation rparenToken; - SourceLocation semicolonToken; -}; - -class WhileStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(WhileStatement) - - WhileStatement(ExpressionNode *e, Statement *stmt): - expression (e), statement (stmt) - { kind = K; } - - virtual ~WhileStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return whileToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - Statement *statement; - SourceLocation whileToken; - SourceLocation lparenToken; - SourceLocation rparenToken; -}; - -class ForStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ForStatement) - - ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt): - initialiser (i), condition (c), expression (e), statement (stmt) - { kind = K; } - - virtual ~ForStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return forToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - -// attributes - ExpressionNode *initialiser; - ExpressionNode *condition; - ExpressionNode *expression; - Statement *statement; - SourceLocation forToken; - SourceLocation lparenToken; - SourceLocation firstSemicolonToken; - SourceLocation secondSemicolonToken; - SourceLocation rparenToken; -}; - -class LocalForStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(LocalForStatement) - - LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt): - declarations (vlist), condition (c), expression (e), statement (stmt) - { kind = K; } - - virtual ~LocalForStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return forToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - -// attributes - VariableDeclarationList *declarations; - ExpressionNode *condition; - ExpressionNode *expression; - Statement *statement; - SourceLocation forToken; - SourceLocation lparenToken; - SourceLocation varToken; - SourceLocation firstSemicolonToken; - SourceLocation secondSemicolonToken; - SourceLocation rparenToken; -}; - -class ForEachStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ForEachStatement) - - ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt): - initialiser (i), expression (e), statement (stmt) - { kind = K; } - - virtual ~ForEachStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return forToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - -// attributes - ExpressionNode *initialiser; - ExpressionNode *expression; - Statement *statement; - SourceLocation forToken; - SourceLocation lparenToken; - SourceLocation inToken; - SourceLocation rparenToken; -}; - -class LocalForEachStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(LocalForEachStatement) - - LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt): - declaration (v), expression (e), statement (stmt) - { kind = K; } - - virtual ~LocalForEachStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return forToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - -// attributes - VariableDeclaration *declaration; - ExpressionNode *expression; - Statement *statement; - SourceLocation forToken; - SourceLocation lparenToken; - SourceLocation varToken; - SourceLocation inToken; - SourceLocation rparenToken; -}; - -class ContinueStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ContinueStatement) - - ContinueStatement(NameId *l = 0): - label (l) { kind = K; } - - virtual ~ContinueStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return continueToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - -// attributes - NameId *label; - SourceLocation continueToken; - SourceLocation identifierToken; - SourceLocation semicolonToken; -}; - -class BreakStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(BreakStatement) - - BreakStatement(NameId *l = 0): - label (l) { kind = K; } - - virtual ~BreakStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return breakToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - - // attributes - NameId *label; - SourceLocation breakToken; - SourceLocation identifierToken; - SourceLocation semicolonToken; -}; - -class ReturnStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ReturnStatement) - - ReturnStatement(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~ReturnStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return returnToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - -// attributes - ExpressionNode *expression; - SourceLocation returnToken; - SourceLocation semicolonToken; -}; - -class WithStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(WithStatement) - - WithStatement(ExpressionNode *e, Statement *stmt): - expression (e), statement (stmt) - { kind = K; } - - virtual ~WithStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return withToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - -// attributes - ExpressionNode *expression; - Statement *statement; - SourceLocation withToken; - SourceLocation lparenToken; - SourceLocation rparenToken; -}; - -class CaseBlock: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(CaseBlock) - - CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0): - clauses (c), defaultClause (d), moreClauses (r) - { kind = K; } - - virtual ~CaseBlock() {} - - virtual void accept0(Visitor *visitor); - -// attributes - CaseClauses *clauses; - DefaultClause *defaultClause; - CaseClauses *moreClauses; - SourceLocation lbraceToken; - SourceLocation rbraceToken; -}; - -class SwitchStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(SwitchStatement) - - SwitchStatement(ExpressionNode *e, CaseBlock *b): - expression (e), block (b) - { kind = K; } - - virtual ~SwitchStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return switchToken; } - - virtual SourceLocation lastSourceLocation() const - { return block->rbraceToken; } - -// attributes - ExpressionNode *expression; - CaseBlock *block; - SourceLocation switchToken; - SourceLocation lparenToken; - SourceLocation rparenToken; -}; - -class CaseClauses: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(CaseClauses) - - CaseClauses(CaseClause *c): - clause (c), next (this) - { kind = K; } - - CaseClauses(CaseClauses *previous, CaseClause *c): - clause (c) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~CaseClauses() {} - - virtual void accept0(Visitor *visitor); - - inline CaseClauses *finish () - { - CaseClauses *front = next; - next = 0; - return front; - } - -//attributes - CaseClause *clause; - CaseClauses *next; -}; - -class CaseClause: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(CaseClause) - - CaseClause(ExpressionNode *e, StatementList *slist): - expression (e), statements (slist) - { kind = K; } - - virtual ~CaseClause() {} - - virtual void accept0(Visitor *visitor); - -// attributes - ExpressionNode *expression; - StatementList *statements; - SourceLocation caseToken; - SourceLocation colonToken; -}; - -class DefaultClause: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(DefaultClause) - - DefaultClause(StatementList *slist): - statements (slist) - { kind = K; } - - virtual ~DefaultClause() {} - - virtual void accept0(Visitor *visitor); - -// attributes - StatementList *statements; - SourceLocation defaultToken; - SourceLocation colonToken; -}; - -class LabelledStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(LabelledStatement) - - LabelledStatement(NameId *l, Statement *stmt): - label (l), statement (stmt) - { kind = K; } - - virtual ~LabelledStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return identifierToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - -// attributes - NameId *label; - Statement *statement; - SourceLocation identifierToken; - SourceLocation colonToken; -}; - -class ThrowStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(ThrowStatement) - - ThrowStatement(ExpressionNode *e): - expression (e) { kind = K; } - - virtual ~ThrowStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return throwToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - - // attributes - ExpressionNode *expression; - SourceLocation throwToken; - SourceLocation semicolonToken; -}; - -class Catch: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(Catch) - - Catch(NameId *n, Block *stmt): - name (n), statement (stmt) - { kind = K; } - - virtual ~Catch() {} - - virtual void accept0(Visitor *visitor); - -// attributes - NameId *name; - Block *statement; - SourceLocation catchToken; - SourceLocation lparenToken; - SourceLocation identifierToken; - SourceLocation rparenToken; -}; - -class Finally: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(Finally) - - Finally(Block *stmt): - statement (stmt) - { kind = K; } - - virtual ~Finally() {} - - virtual void accept0(Visitor *visitor); - -// attributes - Block *statement; - SourceLocation finallyToken; -}; - -class TryStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(TryStatement) - - TryStatement(Statement *stmt, Catch *c, Finally *f): - statement (stmt), catchExpression (c), finallyExpression (f) - { kind = K; } - - TryStatement(Statement *stmt, Finally *f): - statement (stmt), catchExpression (0), finallyExpression (f) - { kind = K; } - - TryStatement(Statement *stmt, Catch *c): - statement (stmt), catchExpression (c), finallyExpression (0) - { kind = K; } - - virtual ~TryStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return tryToken; } - - virtual SourceLocation lastSourceLocation() const - { - if (finallyExpression) - return finallyExpression->statement->rbraceToken; - else if (catchExpression) - return catchExpression->statement->rbraceToken; - - return statement->lastSourceLocation(); - } - -// attributes - Statement *statement; - Catch *catchExpression; - Finally *finallyExpression; - SourceLocation tryToken; -}; - -class FunctionExpression: public ExpressionNode -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(FunctionExpression) - - FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b): - name (n), formals (f), body (b) - { kind = K; } - - virtual ~FunctionExpression() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return functionToken; } - - virtual SourceLocation lastSourceLocation() const - { return rbraceToken; } - -// attributes - NameId *name; - FormalParameterList *formals; - FunctionBody *body; - SourceLocation functionToken; - SourceLocation identifierToken; - SourceLocation lparenToken; - SourceLocation rparenToken; - SourceLocation lbraceToken; - SourceLocation rbraceToken; -}; - -class FunctionDeclaration: public FunctionExpression -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(FunctionDeclaration) - - FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b): - FunctionExpression(n, f, b) - { kind = K; } - - virtual ~FunctionDeclaration() {} - - virtual void accept0(Visitor *visitor); -}; - -class FormalParameterList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(FormalParameterList) - - FormalParameterList(NameId *n): - name (n), next (this) - { kind = K; } - - FormalParameterList(FormalParameterList *previous, NameId *n): - name (n) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~FormalParameterList() {} - - virtual void accept0(Visitor *visitor); - - inline FormalParameterList *finish () - { - FormalParameterList *front = next; - next = 0; - return front; - } - -// attributes - NameId *name; - FormalParameterList *next; - SourceLocation commaToken; - SourceLocation identifierToken; -}; - -class FunctionBody: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(FunctionBody) - - FunctionBody(SourceElements *elts): - elements (elts) - { kind = K; } - - virtual ~FunctionBody() {} - - virtual void accept0(Visitor *visitor); - -// attributes - SourceElements *elements; -}; - -class Program: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(Program) - - Program(SourceElements *elts): - elements (elts) - { kind = K; } - - virtual ~Program() {} - - virtual void accept0(Visitor *visitor); - -// attributes - SourceElements *elements; -}; - -class SourceElements: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(SourceElements) - - SourceElements(SourceElement *elt): - element (elt), next (this) - { kind = K; } - - SourceElements(SourceElements *previous, SourceElement *elt): - element (elt) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~SourceElements() {} - - virtual void accept0(Visitor *visitor); - - inline SourceElements *finish () - { - SourceElements *front = next; - next = 0; - return front; - } - -// attributes - SourceElement *element; - SourceElements *next; -}; - -class SourceElement: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(SourceElement) - - inline SourceElement() - { kind = K; } - - virtual ~SourceElement() {} -}; - -class FunctionSourceElement: public SourceElement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(FunctionSourceElement) - - FunctionSourceElement(FunctionDeclaration *f): - declaration (f) - { kind = K; } - - virtual ~FunctionSourceElement() {} - - virtual void accept0(Visitor *visitor); - -// attributes - FunctionDeclaration *declaration; -}; - -class StatementSourceElement: public SourceElement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(StatementSourceElement) - - StatementSourceElement(Statement *stmt): - statement (stmt) - { kind = K; } - - virtual ~StatementSourceElement() {} - - virtual void accept0(Visitor *visitor); - -// attributes - Statement *statement; -}; - -class DebuggerStatement: public Statement -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(DebuggerStatement) - - DebuggerStatement() - { kind = K; } - - virtual ~DebuggerStatement() {} - - virtual void accept0(Visitor *visitor); - - virtual SourceLocation firstSourceLocation() const - { return debuggerToken; } - - virtual SourceLocation lastSourceLocation() const - { return semicolonToken; } - -// attributes - SourceLocation debuggerToken; - SourceLocation semicolonToken; -}; - -class UiProgram: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiProgram) - - UiProgram(UiImportList *imports, UiObjectMemberList *members) - : imports(imports), members(members) - { kind = K; } - - virtual void accept0(Visitor *visitor); - -// attributes - UiImportList *imports; - UiObjectMemberList *members; -}; - -class UiQualifiedId: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiQualifiedId) - - UiQualifiedId(NameId *name) - : next(this), name(name) - { kind = K; } - - UiQualifiedId(UiQualifiedId *previous, NameId *name) - : name(name) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual ~UiQualifiedId() {} - - UiQualifiedId *finish() - { - UiQualifiedId *head = next; - next = 0; - return head; - } - - virtual void accept0(Visitor *visitor); - -// attributes - UiQualifiedId *next; - NameId *name; - SourceLocation identifierToken; -}; - -class UiImport: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiImport) - - UiImport(NameId *fileName) - : fileName(fileName) - { kind = K; } - - virtual void accept0(Visitor *visitor); - -// attributes - NameId *fileName; - SourceLocation importToken; - SourceLocation fileNameToken; - SourceLocation semicolonToken; -}; - -class UiImportList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiImportList) - - UiImportList(UiImport *import) - : import(import), - next(this) - { kind = K; } - - UiImportList(UiImportList *previous, UiImport *import) - : import(import) - { - kind = K; - next = previous->next; - previous->next = this; - } - - UiImportList *finish() - { - UiImportList *head = next; - next = 0; - return head; - } - - virtual void accept0(Visitor *visitor); - -// attributes - UiImport *import; - UiImportList *next; -}; - -class UiObjectMember: public Node -{ -public: - virtual SourceLocation firstSourceLocation() const = 0; - virtual SourceLocation lastSourceLocation() const = 0; -}; - -class UiObjectMemberList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiObjectMemberList) - - UiObjectMemberList(UiObjectMember *member) - : next(this), member(member) - { kind = K; } - - UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member) - : member(member) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual void accept0(Visitor *visitor); - - UiObjectMemberList *finish() - { - UiObjectMemberList *head = next; - next = 0; - return head; - } - -// attributes - UiObjectMemberList *next; - UiObjectMember *member; -}; - -class UiArrayMemberList: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiArrayMemberList) - - UiArrayMemberList(UiObjectMember *member) - : next(this), member(member) - { kind = K; } - - UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member) - : member(member) - { - kind = K; - next = previous->next; - previous->next = this; - } - - virtual void accept0(Visitor *visitor); - - UiArrayMemberList *finish() - { - UiArrayMemberList *head = next; - next = 0; - return head; - } - -// attributes - UiArrayMemberList *next; - UiObjectMember *member; - SourceLocation commaToken; -}; - -class UiObjectInitializer: public Node -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiObjectInitializer) - - UiObjectInitializer(UiObjectMemberList *members) - : members(members) - { kind = K; } - - virtual void accept0(Visitor *visitor); - -// attributes - SourceLocation lbraceToken; - UiObjectMemberList *members; - SourceLocation rbraceToken; -}; - -class UiPublicMember: public UiObjectMember -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiPublicMember) - - UiPublicMember(NameId *memberType, - NameId *name) - : type(Property), memberType(memberType), name(name), expression(0), isDefaultMember(false) - { kind = K; } - - UiPublicMember(NameId *memberType, - NameId *name, - ExpressionNode *expression) - : type(Property), memberType(memberType), name(name), expression(expression), isDefaultMember(false) - { kind = K; } - - virtual SourceLocation firstSourceLocation() const - { - if (defaultToken.isValid()) - return defaultToken; - - return propertyToken; - } - - virtual SourceLocation lastSourceLocation() const - { - return semicolonToken; - } - - virtual void accept0(Visitor *visitor); - -// attributes - enum { Signal, Property } type; - NameId *memberType; - NameId *name; - ExpressionNode *expression; - bool isDefaultMember; - SourceLocation defaultToken; - SourceLocation propertyToken; - SourceLocation typeToken; - SourceLocation identifierToken; - SourceLocation colonToken; - SourceLocation semicolonToken; -}; - -class UiObjectDefinition: public UiObjectMember -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiObjectDefinition) - - UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId, - UiObjectInitializer *initializer) - : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) - { kind = K; } - - virtual SourceLocation firstSourceLocation() const - { return qualifiedTypeNameId->identifierToken; } - - virtual SourceLocation lastSourceLocation() const - { return initializer->rbraceToken; } - - virtual void accept0(Visitor *visitor); - -// attributes - UiQualifiedId *qualifiedTypeNameId; - UiObjectInitializer *initializer; -}; - -class UiSourceElement: public UiObjectMember -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiSourceElement) - - UiSourceElement(Node *sourceElement) - : sourceElement(sourceElement) - { kind = K; } - - virtual SourceLocation firstSourceLocation() const - { - if (FunctionDeclaration *funDecl = cast(sourceElement)) - return funDecl->firstSourceLocation(); - else if (VariableStatement *varStmt = cast(sourceElement)) - return varStmt->firstSourceLocation(); - - return SourceLocation(); - } - - virtual SourceLocation lastSourceLocation() const - { - if (FunctionDeclaration *funDecl = cast(sourceElement)) - return funDecl->lastSourceLocation(); - else if (VariableStatement *varStmt = cast(sourceElement)) - return varStmt->lastSourceLocation(); - - return SourceLocation(); - } - - - virtual void accept0(Visitor *visitor); - -// attributes - Node *sourceElement; -}; - -class UiObjectBinding: public UiObjectMember -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiObjectBinding) - - UiObjectBinding(UiQualifiedId *qualifiedId, - UiQualifiedId *qualifiedTypeNameId, - UiObjectInitializer *initializer) - : qualifiedId(qualifiedId), - qualifiedTypeNameId(qualifiedTypeNameId), - initializer(initializer) - { kind = K; } - - virtual SourceLocation firstSourceLocation() const - { return qualifiedId->identifierToken; } - - virtual SourceLocation lastSourceLocation() const - { return initializer->rbraceToken; } - - virtual void accept0(Visitor *visitor); - -// attributes - UiQualifiedId *qualifiedId; - UiQualifiedId *qualifiedTypeNameId; - UiObjectInitializer *initializer; - SourceLocation colonToken; -}; - -class UiScriptBinding: public UiObjectMember -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiScriptBinding) - - UiScriptBinding(UiQualifiedId *qualifiedId, - Statement *statement) - : qualifiedId(qualifiedId), - statement(statement) - { kind = K; } - - virtual SourceLocation firstSourceLocation() const - { return qualifiedId->identifierToken; } - - virtual SourceLocation lastSourceLocation() const - { return statement->lastSourceLocation(); } - - virtual void accept0(Visitor *visitor); - -// attributes - UiQualifiedId *qualifiedId; - Statement *statement; - SourceLocation colonToken; -}; - -class UiArrayBinding: public UiObjectMember -{ -public: - JAVASCRIPT_DECLARE_AST_NODE(UiArrayBinding) - - UiArrayBinding(UiQualifiedId *qualifiedId, - UiArrayMemberList *members) - : qualifiedId(qualifiedId), - members(members) - { kind = K; } - - virtual SourceLocation firstSourceLocation() const - { return lbracketToken; } - - virtual SourceLocation lastSourceLocation() const - { return rbracketToken; } - - virtual void accept0(Visitor *visitor); - -// attributes - UiQualifiedId *qualifiedId; - UiArrayMemberList *members; - SourceLocation colonToken; - SourceLocation lbracketToken; - SourceLocation rbracketToken; -}; - -} } // namespace AST - - - -QT_END_NAMESPACE - -#endif diff --git a/src/declarative/qml/parser/javascriptastfwd_p.h b/src/declarative/qml/parser/javascriptastfwd_p.h deleted file mode 100644 index 23270e5..0000000 --- a/src/declarative/qml/parser/javascriptastfwd_p.h +++ /dev/null @@ -1,184 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 JAVASCRIPTAST_FWD_P_H -#define JAVASCRIPTAST_FWD_P_H - -#include - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -QT_BEGIN_NAMESPACE - -namespace JavaScript { namespace AST { - -class SourceLocation -{ -public: - SourceLocation(quint32 offset = 0, quint32 length = 0) - : offset(offset), length(length), - startLine(0), startColumn(0) - { } - - bool isValid() const { return length != 0; } - - quint32 begin() const { return offset; } - quint32 end() const { return offset + length; } - -// attributes - // ### encode - quint32 offset; - quint32 length; - quint32 startLine; - quint32 startColumn; -}; - -class Visitor; -class Node; -class ExpressionNode; -class Statement; -class ThisExpression; -class IdentifierExpression; -class NullExpression; -class TrueLiteral; -class FalseLiteral; -class NumericLiteral; -class StringLiteral; -class RegExpLiteral; -class ArrayLiteral; -class ObjectLiteral; -class ElementList; -class Elision; -class PropertyNameAndValueList; -class PropertyName; -class IdentifierPropertyName; -class StringLiteralPropertyName; -class NumericLiteralPropertyName; -class ArrayMemberExpression; -class FieldMemberExpression; -class NewMemberExpression; -class NewExpression; -class CallExpression; -class ArgumentList; -class PostIncrementExpression; -class PostDecrementExpression; -class DeleteExpression; -class VoidExpression; -class TypeOfExpression; -class PreIncrementExpression; -class PreDecrementExpression; -class UnaryPlusExpression; -class UnaryMinusExpression; -class TildeExpression; -class NotExpression; -class BinaryExpression; -class ConditionalExpression; -class Expression; // ### rename -class Block; -class StatementList; -class VariableStatement; -class VariableDeclarationList; -class VariableDeclaration; -class EmptyStatement; -class ExpressionStatement; -class IfStatement; -class DoWhileStatement; -class WhileStatement; -class ForStatement; -class LocalForStatement; -class ForEachStatement; -class LocalForEachStatement; -class ContinueStatement; -class BreakStatement; -class ReturnStatement; -class WithStatement; -class SwitchStatement; -class CaseBlock; -class CaseClauses; -class CaseClause; -class DefaultClause; -class LabelledStatement; -class ThrowStatement; -class TryStatement; -class Catch; -class Finally; -class FunctionDeclaration; -class FunctionExpression; -class FormalParameterList; -class FunctionBody; -class Program; -class SourceElements; -class SourceElement; -class FunctionSourceElement; -class StatementSourceElement; -class DebuggerStatement; -class NestedExpression; - -// ui elements -class UiProgram; -class UiImportList; -class UiImport; -class UiPublicMember; -class UiObjectDefinition; -class UiObjectInitializer; -class UiObjectBinding; -class UiScriptBinding; -class UiSourceElement; -class UiArrayBinding; -class UiObjectMember; -class UiObjectMemberList; -class UiArrayMemberList; -class UiQualifiedId; - -} } // namespace AST - -QT_END_NAMESPACE - -#endif diff --git a/src/declarative/qml/parser/javascriptastvisitor.cpp b/src/declarative/qml/parser/javascriptastvisitor.cpp deleted file mode 100644 index eac291d..0000000 --- a/src/declarative/qml/parser/javascriptastvisitor.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 "javascriptastvisitor_p.h" - -QT_BEGIN_NAMESPACE - -namespace JavaScript { namespace AST { - -Visitor::Visitor() -{ -} - -Visitor::~Visitor() -{ -} - -} } // namespace JavaScript::AST - -QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/javascriptastvisitor_p.h b/src/declarative/qml/parser/javascriptastvisitor_p.h deleted file mode 100644 index 7c73e43..0000000 --- a/src/declarative/qml/parser/javascriptastvisitor_p.h +++ /dev/null @@ -1,328 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 JAVASCRIPTASTVISITOR_P_H -#define JAVASCRIPTASTVISITOR_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "javascriptastfwd_p.h" - -QT_BEGIN_NAMESPACE - -namespace JavaScript { namespace AST { - -class Visitor -{ -public: - Visitor(); - virtual ~Visitor(); - - virtual bool preVisit(Node *) { return true; } - virtual void postVisit(Node *) {} - - // Ui - virtual bool visit(UiProgram *) { return true; } - virtual bool visit(UiImportList *) { return true; } - virtual bool visit(UiImport *) { return true; } - virtual bool visit(UiPublicMember *) { return true; } - virtual bool visit(UiSourceElement *) { return true; } - virtual bool visit(UiObjectDefinition *) { return true; } - virtual bool visit(UiObjectInitializer *) { return true; } - virtual bool visit(UiObjectBinding *) { return true; } - virtual bool visit(UiScriptBinding *) { return true; } - virtual bool visit(UiArrayBinding *) { return true; } - virtual bool visit(UiObjectMemberList *) { return true; } - virtual bool visit(UiArrayMemberList *) { return true; } - virtual bool visit(UiQualifiedId *) { return true; } - - virtual void endVisit(UiProgram *) {} - virtual void endVisit(UiImportList *) {} - virtual void endVisit(UiImport *) {} - virtual void endVisit(UiPublicMember *) {} - virtual void endVisit(UiSourceElement *) {} - virtual void endVisit(UiObjectDefinition *) {} - virtual void endVisit(UiObjectInitializer *) {} - virtual void endVisit(UiObjectBinding *) {} - virtual void endVisit(UiScriptBinding *) {} - virtual void endVisit(UiArrayBinding *) {} - virtual void endVisit(UiObjectMemberList *) {} - virtual void endVisit(UiArrayMemberList *) {} - virtual void endVisit(UiQualifiedId *) {} - - // JavaScript - virtual bool visit(ThisExpression *) { return true; } - virtual void endVisit(ThisExpression *) {} - - virtual bool visit(IdentifierExpression *) { return true; } - virtual void endVisit(IdentifierExpression *) {} - - virtual bool visit(NullExpression *) { return true; } - virtual void endVisit(NullExpression *) {} - - virtual bool visit(TrueLiteral *) { return true; } - virtual void endVisit(TrueLiteral *) {} - - virtual bool visit(FalseLiteral *) { return true; } - virtual void endVisit(FalseLiteral *) {} - - virtual bool visit(StringLiteral *) { return true; } - virtual void endVisit(StringLiteral *) {} - - virtual bool visit(NumericLiteral *) { return true; } - virtual void endVisit(NumericLiteral *) {} - - virtual bool visit(RegExpLiteral *) { return true; } - virtual void endVisit(RegExpLiteral *) {} - - virtual bool visit(ArrayLiteral *) { return true; } - virtual void endVisit(ArrayLiteral *) {} - - virtual bool visit(ObjectLiteral *) { return true; } - virtual void endVisit(ObjectLiteral *) {} - - virtual bool visit(ElementList *) { return true; } - virtual void endVisit(ElementList *) {} - - virtual bool visit(Elision *) { return true; } - virtual void endVisit(Elision *) {} - - virtual bool visit(PropertyNameAndValueList *) { return true; } - virtual void endVisit(PropertyNameAndValueList *) {} - - virtual bool visit(NestedExpression *) { return true; } - virtual void endVisit(NestedExpression *) {} - - virtual bool visit(IdentifierPropertyName *) { return true; } - virtual void endVisit(IdentifierPropertyName *) {} - - virtual bool visit(StringLiteralPropertyName *) { return true; } - virtual void endVisit(StringLiteralPropertyName *) {} - - virtual bool visit(NumericLiteralPropertyName *) { return true; } - virtual void endVisit(NumericLiteralPropertyName *) {} - - virtual bool visit(ArrayMemberExpression *) { return true; } - virtual void endVisit(ArrayMemberExpression *) {} - - virtual bool visit(FieldMemberExpression *) { return true; } - virtual void endVisit(FieldMemberExpression *) {} - - virtual bool visit(NewMemberExpression *) { return true; } - virtual void endVisit(NewMemberExpression *) {} - - virtual bool visit(NewExpression *) { return true; } - virtual void endVisit(NewExpression *) {} - - virtual bool visit(CallExpression *) { return true; } - virtual void endVisit(CallExpression *) {} - - virtual bool visit(ArgumentList *) { return true; } - virtual void endVisit(ArgumentList *) {} - - virtual bool visit(PostIncrementExpression *) { return true; } - virtual void endVisit(PostIncrementExpression *) {} - - virtual bool visit(PostDecrementExpression *) { return true; } - virtual void endVisit(PostDecrementExpression *) {} - - virtual bool visit(DeleteExpression *) { return true; } - virtual void endVisit(DeleteExpression *) {} - - virtual bool visit(VoidExpression *) { return true; } - virtual void endVisit(VoidExpression *) {} - - virtual bool visit(TypeOfExpression *) { return true; } - virtual void endVisit(TypeOfExpression *) {} - - virtual bool visit(PreIncrementExpression *) { return true; } - virtual void endVisit(PreIncrementExpression *) {} - - virtual bool visit(PreDecrementExpression *) { return true; } - virtual void endVisit(PreDecrementExpression *) {} - - virtual bool visit(UnaryPlusExpression *) { return true; } - virtual void endVisit(UnaryPlusExpression *) {} - - virtual bool visit(UnaryMinusExpression *) { return true; } - virtual void endVisit(UnaryMinusExpression *) {} - - virtual bool visit(TildeExpression *) { return true; } - virtual void endVisit(TildeExpression *) {} - - virtual bool visit(NotExpression *) { return true; } - virtual void endVisit(NotExpression *) {} - - virtual bool visit(BinaryExpression *) { return true; } - virtual void endVisit(BinaryExpression *) {} - - virtual bool visit(ConditionalExpression *) { return true; } - virtual void endVisit(ConditionalExpression *) {} - - virtual bool visit(Expression *) { return true; } - virtual void endVisit(Expression *) {} - - virtual bool visit(Block *) { return true; } - virtual void endVisit(Block *) {} - - virtual bool visit(StatementList *) { return true; } - virtual void endVisit(StatementList *) {} - - virtual bool visit(VariableStatement *) { return true; } - virtual void endVisit(VariableStatement *) {} - - virtual bool visit(VariableDeclarationList *) { return true; } - virtual void endVisit(VariableDeclarationList *) {} - - virtual bool visit(VariableDeclaration *) { return true; } - virtual void endVisit(VariableDeclaration *) {} - - virtual bool visit(EmptyStatement *) { return true; } - virtual void endVisit(EmptyStatement *) {} - - virtual bool visit(ExpressionStatement *) { return true; } - virtual void endVisit(ExpressionStatement *) {} - - virtual bool visit(IfStatement *) { return true; } - virtual void endVisit(IfStatement *) {} - - virtual bool visit(DoWhileStatement *) { return true; } - virtual void endVisit(DoWhileStatement *) {} - - virtual bool visit(WhileStatement *) { return true; } - virtual void endVisit(WhileStatement *) {} - - virtual bool visit(ForStatement *) { return true; } - virtual void endVisit(ForStatement *) {} - - virtual bool visit(LocalForStatement *) { return true; } - virtual void endVisit(LocalForStatement *) {} - - virtual bool visit(ForEachStatement *) { return true; } - virtual void endVisit(ForEachStatement *) {} - - virtual bool visit(LocalForEachStatement *) { return true; } - virtual void endVisit(LocalForEachStatement *) {} - - virtual bool visit(ContinueStatement *) { return true; } - virtual void endVisit(ContinueStatement *) {} - - virtual bool visit(BreakStatement *) { return true; } - virtual void endVisit(BreakStatement *) {} - - virtual bool visit(ReturnStatement *) { return true; } - virtual void endVisit(ReturnStatement *) {} - - virtual bool visit(WithStatement *) { return true; } - virtual void endVisit(WithStatement *) {} - - virtual bool visit(SwitchStatement *) { return true; } - virtual void endVisit(SwitchStatement *) {} - - virtual bool visit(CaseBlock *) { return true; } - virtual void endVisit(CaseBlock *) {} - - virtual bool visit(CaseClauses *) { return true; } - virtual void endVisit(CaseClauses *) {} - - virtual bool visit(CaseClause *) { return true; } - virtual void endVisit(CaseClause *) {} - - virtual bool visit(DefaultClause *) { return true; } - virtual void endVisit(DefaultClause *) {} - - virtual bool visit(LabelledStatement *) { return true; } - virtual void endVisit(LabelledStatement *) {} - - virtual bool visit(ThrowStatement *) { return true; } - virtual void endVisit(ThrowStatement *) {} - - virtual bool visit(TryStatement *) { return true; } - virtual void endVisit(TryStatement *) {} - - virtual bool visit(Catch *) { return true; } - virtual void endVisit(Catch *) {} - - virtual bool visit(Finally *) { return true; } - virtual void endVisit(Finally *) {} - - virtual bool visit(FunctionDeclaration *) { return true; } - virtual void endVisit(FunctionDeclaration *) {} - - virtual bool visit(FunctionExpression *) { return true; } - virtual void endVisit(FunctionExpression *) {} - - virtual bool visit(FormalParameterList *) { return true; } - virtual void endVisit(FormalParameterList *) {} - - virtual bool visit(FunctionBody *) { return true; } - virtual void endVisit(FunctionBody *) {} - - virtual bool visit(Program *) { return true; } - virtual void endVisit(Program *) {} - - virtual bool visit(SourceElements *) { return true; } - virtual void endVisit(SourceElements *) {} - - virtual bool visit(FunctionSourceElement *) { return true; } - virtual void endVisit(FunctionSourceElement *) {} - - virtual bool visit(StatementSourceElement *) { return true; } - virtual void endVisit(StatementSourceElement *) {} - - virtual bool visit(DebuggerStatement *) { return true; } - virtual void endVisit(DebuggerStatement *) {} -}; - -} } // namespace AST - -QT_END_NAMESPACE - -#endif // JAVASCRIPTASTVISITOR_P_H diff --git a/src/declarative/qml/parser/javascriptengine_p.cpp b/src/declarative/qml/parser/javascriptengine_p.cpp deleted file mode 100644 index d893a90..0000000 --- a/src/declarative/qml/parser/javascriptengine_p.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** 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. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -**************************************************************************/ - -#include "javascriptengine_p.h" -#include "javascriptnodepool_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -namespace JavaScript { - -uint qHash(const JavaScript::NameId &id) -{ return qHash(id.asString()); } - -QString numberToString(double value) -{ return QString::number(value); } - -int Ecma::RegExp::flagFromChar(const QChar &ch) -{ - static QHash flagsHash; - if (flagsHash.isEmpty()) { - flagsHash[QLatin1Char('g')] = Global; - flagsHash[QLatin1Char('i')] = IgnoreCase; - flagsHash[QLatin1Char('m')] = Multiline; - } - QHash::const_iterator it; - it = flagsHash.constFind(ch); - if (it == flagsHash.constEnd()) - return 0; - return it.value(); -} - -QString Ecma::RegExp::flagsToString(int flags) -{ - QString result; - if (flags & Global) - result += QLatin1Char('g'); - if (flags & IgnoreCase) - result += QLatin1Char('i'); - if (flags & Multiline) - result += QLatin1Char('m'); - return result; -} - -NodePool::NodePool(const QString &fileName, Engine *engine) - : m_fileName(fileName), m_engine(engine) -{ - m_engine->setNodePool(this); -} - -NodePool::~NodePool() -{ -} - -Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &) -{ - Q_ASSERT(0); - return 0; -} - -static int toDigit(char c) -{ - if ((c >= '0') && (c <= '9')) - return c - '0'; - else if ((c >= 'a') && (c <= 'z')) - return 10 + c - 'a'; - else if ((c >= 'A') && (c <= 'Z')) - return 10 + c - 'A'; - return -1; -} - -double integerFromString(const char *buf, int size, int radix) -{ - if (size == 0) - return qSNaN(); - - double sign = 1.0; - int i = 0; - if (buf[0] == '+') { - ++i; - } else if (buf[0] == '-') { - sign = -1.0; - ++i; - } - - if (((size-i) >= 2) && (buf[i] == '0')) { - if (((buf[i+1] == 'x') || (buf[i+1] == 'X')) - && (radix < 34)) { - if ((radix != 0) && (radix != 16)) - return 0; - radix = 16; - i += 2; - } else { - if (radix == 0) { - radix = 8; - ++i; - } - } - } else if (radix == 0) { - radix = 10; - } - - int j = i; - for ( ; i < size; ++i) { - int d = toDigit(buf[i]); - if ((d == -1) || (d >= radix)) - break; - } - double result; - if (j == i) { - if (!qstrcmp(buf, "Infinity")) - result = qInf(); - else - result = qSNaN(); - } else { - result = 0; - double multiplier = 1; - for (--i ; i >= j; --i, multiplier *= radix) - result += toDigit(buf[i]) * multiplier; - } - result *= sign; - return result; -} - -double integerFromString(const QString &str, int radix) -{ - QByteArray ba = str.trimmed().toUtf8(); - return integerFromString(ba.constData(), ba.size(), radix); -} - - -Engine::Engine() - : _lexer(0), _nodePool(0) -{ } - -Engine::~Engine() -{ } - -QSet Engine::literals() const -{ return _literals; } - -NameId *Engine::intern(const QChar *u, int s) -{ return const_cast(&*_literals.insert(NameId(u, s))); } - -QString Engine::toString(NameId *id) -{ return id->asString(); } - -Lexer *Engine::lexer() const -{ return _lexer; } - -void Engine::setLexer(Lexer *lexer) -{ _lexer = lexer; } - -NodePool *Engine::nodePool() const -{ return _nodePool; } - -void Engine::setNodePool(NodePool *nodePool) -{ _nodePool = nodePool; } - - - -} // end of namespace JavaScript - -QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/javascriptengine_p.h b/src/declarative/qml/parser/javascriptengine_p.h deleted file mode 100644 index 3bd924a..0000000 --- a/src/declarative/qml/parser/javascriptengine_p.h +++ /dev/null @@ -1,145 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** 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. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -**************************************************************************/ - -#ifndef JAVASCRIPTENGINE_P_H -#define JAVASCRIPTENGINE_P_H - -#include -#include - -#include "javascriptastfwd_p.h" - -QT_BEGIN_NAMESPACE - -namespace JavaScript { -class NameId -{ - QString _text; - -public: - NameId(const QChar *u, int s) - : _text(u, s) - { } - - const QString asString() const - { return _text; } - - bool operator == (const NameId &other) const - { return _text == other._text; } - - bool operator != (const NameId &other) const - { return _text != other._text; } - - bool operator < (const NameId &other) const - { return _text < other._text; } -}; - -uint qHash(const JavaScript::NameId &id); - -} // end of namespace JavaScript - -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 -//this ensures that code outside JavaScript can use the hash function -//it also a workaround for some compilers -inline uint qHash(const JavaScript::NameId &nameId) { return JavaScript::qHash(nameId); } -#endif - -namespace JavaScript { - -class Lexer; -class NodePool; - -namespace Ecma { - -class RegExp -{ -public: - enum RegExpFlag { - Global = 0x01, - IgnoreCase = 0x02, - Multiline = 0x04 - }; - -public: - static int flagFromChar(const QChar &); - static QString flagsToString(int flags); -}; - -} // end of namespace Ecma - -class DiagnosticMessage -{ -public: - enum Kind { Warning, Error }; - - DiagnosticMessage() - : kind(Error) {} - - DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) - : kind(kind), loc(loc), message(message) {} - - bool isWarning() const - { return kind == Warning; } - - bool isError() const - { return kind == Error; } - - Kind kind; - AST::SourceLocation loc; - QString message; -}; - -class Engine -{ - Lexer *_lexer; - NodePool *_nodePool; - QSet _literals; - -public: - Engine(); - ~Engine(); - - QSet literals() const; - - NameId *intern(const QChar *u, int s); - - static QString toString(NameId *id); - - Lexer *lexer() const; - void setLexer(Lexer *lexer); - - NodePool *nodePool() const; - void setNodePool(NodePool *nodePool); -}; - -} // end of namespace JavaScript - -QT_END_NAMESPACE - -#endif // JAVASCRIPTENGINE_P_H diff --git a/src/declarative/qml/parser/javascriptgrammar.cpp b/src/declarative/qml/parser/javascriptgrammar.cpp deleted file mode 100644 index a879bfe..0000000 --- a/src/declarative/qml/parser/javascriptgrammar.cpp +++ /dev/null @@ -1,829 +0,0 @@ -// This file was generated by qlalr - DO NOT EDIT! -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module 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 "javascriptgrammar_p.h" - -const char *const JavaScriptGrammar::spell [] = { - "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue", - "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", - "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier", - "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=", - "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=", - "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return", - ")", ";", 0, "*", "*=", "string literal", "property", "signal", "switch", "this", - "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=", - "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "public", "import", 0, - 0}; - -const int JavaScriptGrammar::lhs [] = { - 91, 92, 92, 95, 95, 96, 96, 94, 93, 98, - 98, 100, 100, 101, 101, 97, 99, 99, 103, 104, - 104, 99, 99, 99, 99, 99, 99, 99, 111, 111, - 111, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 102, 102, 114, 114, 114, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 102, 102, 117, 117, 117, 117, - 116, 116, 119, 119, 121, 121, 121, 121, 121, 121, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 123, 123, 124, 124, 124, 124, 124, 127, 127, - 128, 128, 128, 128, 126, 126, 129, 129, 130, 130, - 131, 131, 131, 132, 132, 132, 132, 132, 132, 132, - 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, - 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, - 136, 137, 137, 137, 137, 137, 137, 138, 138, 138, - 138, 138, 139, 139, 139, 139, 139, 140, 140, 141, - 141, 142, 142, 143, 143, 144, 144, 145, 145, 146, - 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, - 151, 120, 120, 152, 152, 153, 153, 153, 153, 153, - 153, 153, 153, 153, 153, 153, 153, 105, 105, 154, - 154, 155, 155, 156, 156, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 106, 168, 168, 167, 167, 113, 113, 169, 169, 170, - 170, 172, 172, 171, 173, 176, 174, 174, 177, 175, - 175, 107, 108, 108, 110, 110, 158, 158, 158, 158, - 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, - 160, 161, 161, 162, 164, 178, 178, 181, 181, 179, - 179, 182, 180, 163, 163, 163, 165, 165, 166, 166, - 166, 183, 184, 109, 109, 112, 125, 188, 188, 185, - 185, 186, 186, 189, 190, 190, 191, 191, 187, 187, - 118, 118, 192}; - -const int JavaScriptGrammar:: rhs[] = { - 2, 1, 1, 1, 2, 3, 3, 0, 1, 1, - 2, 1, 3, 2, 3, 2, 1, 5, 1, 2, - 2, 4, 3, 3, 3, 3, 3, 3, 1, 1, - 1, 2, 4, 4, 5, 5, 6, 6, 7, 7, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, - 5, 3, 4, 3, 1, 3, 1, 2, 3, 4, - 1, 2, 3, 5, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 4, 3, 5, 1, 2, - 4, 4, 4, 3, 0, 1, 1, 3, 1, 1, - 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, - 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, - 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, - 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, - 5, 1, 3, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, - 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 2, 0, 1, 3, 3, 1, 1, 1, - 3, 1, 3, 2, 2, 2, 0, 1, 2, 0, - 1, 1, 2, 2, 7, 5, 7, 7, 5, 9, - 10, 7, 8, 2, 2, 3, 3, 2, 2, 3, - 3, 3, 3, 5, 5, 3, 5, 1, 2, 0, - 1, 4, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 5, 2, 2, 2, 8, 8, 1, 3, 0, - 1, 0, 1, 1, 1, 2, 1, 1, 0, 1, - 0, 1, 2}; - -const int JavaScriptGrammar::action_default [] = { - 8, 2, 0, 4, 3, 0, 0, 0, 6, 7, - 5, 65, 45, 46, 43, 44, 47, 9, 0, 1, - 0, 0, 16, 66, 41, 248, 0, 0, 46, 14, - 47, 249, 17, 10, 0, 0, 0, 42, 0, 31, - 30, 29, 0, 0, 35, 0, 36, 151, 218, 182, - 190, 186, 130, 202, 178, 0, 115, 49, 131, 194, - 198, 119, 148, 129, 134, 114, 168, 155, 0, 55, - 56, 52, 319, 321, 0, 0, 0, 0, 0, 0, - 50, 53, 0, 0, 54, 48, 0, 51, 0, 0, - 144, 0, 0, 131, 150, 133, 132, 0, 0, 0, - 146, 147, 145, 149, 0, 179, 0, 0, 0, 0, - 169, 0, 0, 0, 0, 0, 0, 159, 0, 0, - 0, 153, 154, 152, 157, 161, 160, 158, 156, 171, - 170, 172, 0, 187, 0, 183, 0, 0, 125, 112, - 124, 113, 81, 82, 83, 108, 84, 109, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 110, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 111, 0, 0, 123, 219, 126, 0, 127, - 0, 128, 122, 39, 40, 0, 215, 208, 206, 213, - 214, 212, 211, 217, 210, 209, 207, 216, 203, 0, - 191, 0, 0, 195, 0, 0, 199, 0, 0, 125, - 117, 0, 116, 0, 121, 135, 0, 320, 310, 311, - 0, 308, 0, 309, 0, 312, 226, 233, 232, 240, - 228, 0, 229, 313, 0, 318, 230, 231, 236, 234, - 315, 314, 317, 237, 0, 0, 0, 0, 0, 319, - 45, 0, 321, 46, 220, 262, 47, 0, 0, 0, - 0, 0, 238, 239, 227, 235, 263, 264, 307, 316, - 0, 278, 279, 280, 281, 0, 274, 275, 276, 277, - 304, 305, 0, 0, 0, 0, 0, 267, 268, 224, - 222, 184, 192, 188, 204, 180, 225, 0, 131, 196, - 200, 173, 162, 0, 0, 181, 0, 0, 0, 0, - 174, 0, 0, 0, 0, 0, 166, 164, 167, 165, - 163, 176, 175, 177, 0, 189, 0, 185, 0, 223, - 131, 0, 205, 220, 221, 0, 220, 0, 0, 270, - 0, 0, 0, 272, 0, 193, 0, 0, 197, 0, - 0, 201, 260, 0, 252, 261, 255, 0, 259, 0, - 220, 253, 0, 220, 0, 0, 271, 0, 0, 0, - 273, 320, 310, 0, 0, 312, 0, 306, 0, 296, - 0, 0, 0, 266, 0, 265, 0, 322, 0, 80, - 242, 245, 0, 81, 248, 84, 109, 86, 87, 52, - 91, 92, 45, 93, 96, 50, 53, 46, 220, 47, - 54, 99, 48, 101, 51, 103, 104, 249, 106, 107, - 111, 0, 73, 0, 0, 75, 79, 77, 63, 76, - 78, 0, 74, 62, 243, 241, 119, 120, 125, 0, - 118, 0, 295, 0, 282, 283, 0, 294, 0, 0, - 0, 285, 290, 288, 291, 0, 0, 289, 290, 0, - 286, 0, 287, 244, 293, 0, 244, 292, 0, 297, - 298, 0, 244, 299, 300, 0, 0, 301, 0, 0, - 0, 302, 303, 137, 136, 0, 0, 0, 269, 0, - 0, 0, 284, 67, 0, 0, 71, 57, 0, 59, - 69, 0, 60, 70, 72, 61, 68, 58, 0, 64, - 141, 139, 143, 140, 138, 142, 0, 0, 0, 33, - 0, 34, 0, 37, 38, 32, 15, 11, 0, 23, - 26, 24, 0, 25, 28, 244, 0, 19, 0, 27, - 22, 81, 248, 84, 109, 86, 87, 52, 91, 92, - 45, 93, 96, 50, 53, 46, 220, 47, 54, 99, - 48, 101, 51, 103, 104, 249, 106, 107, 111, 49, - 0, 12, 0, 18, 13, 20, 21, 257, 250, 0, - 258, 254, 0, 256, 246, 0, 247, 251, 323}; - -const int JavaScriptGrammar::goto_default [] = { - 6, 5, 19, 1, 4, 3, 32, 34, 33, 570, - 22, 18, 538, 539, 231, 226, 230, 232, 229, 236, - 517, 235, 264, 57, 65, 495, 494, 388, 387, 48, - 386, 389, 140, 61, 56, 178, 63, 52, 177, 58, - 64, 90, 62, 47, 67, 66, 301, 54, 295, 49, - 291, 51, 293, 50, 292, 59, 299, 60, 300, 53, - 294, 290, 331, 443, 296, 297, 390, 237, 228, 227, - 239, 265, 238, 243, 262, 263, 392, 391, 36, 579, - 578, 353, 354, 581, 356, 580, 355, 451, 455, 458, - 454, 453, 473, 474, 220, 234, 216, 219, 233, 241, - 240, 0}; - -const int JavaScriptGrammar::action_index [] = { - 8, -91, 14, -91, -15, 296, 67, 94, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, 109, -91, - 184, 408, -91, -91, -91, -91, 45, 125, 170, -91, - 46, -91, -91, -91, 429, 171, 130, -91, 120, -91, - -91, -91, -19, 169, -91, 733, -91, 72, -91, 22, - -26, -59, 173, -91, 278, 174, -91, -91, 574, 51, - 112, 183, 177, -91, -91, -91, 412, 214, 733, -91, - -91, -91, 161, 1566, 980, 733, 733, 733, 653, 733, - -91, -91, 733, 733, -91, -91, 733, -91, 733, 733, - -91, 733, 733, 98, 235, -91, -91, 733, 733, 733, - -91, -91, -91, 230, 733, 276, 733, 733, 733, 733, - 396, 733, 733, 733, 733, 733, 733, 288, 733, 733, - 733, 88, 87, 74, 288, 288, 288, 218, 221, 486, - 372, 362, 733, 4, 733, 76, 1479, 733, 733, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, -91, 102, 733, -91, -91, 60, 3, -91, - 733, -91, -91, -91, -91, 733, -91, -91, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, 733, - -6, 733, 733, 30, 32, 733, -91, 1479, 733, 733, - -91, 107, -91, -14, -91, -91, 69, -91, 191, 49, - 18, -91, 233, -91, 47, 1827, -91, -91, -91, -91, - -91, 204, -91, -91, 39, -91, -91, -91, -91, -91, - -91, 1827, -91, -91, 322, 281, 103, 1740, 50, 203, - 77, 40, 2001, 53, 733, -91, 52, 29, 733, 25, - 28, 35, -91, -91, -91, -91, -91, -91, -91, -91, - 113, -91, -91, -91, -91, 106, -91, -91, -91, -91, - -91, -91, 15, 68, 733, 135, 119, -91, -91, 897, - -91, 82, 58, 17, -91, 261, 84, 42, 494, 91, - 79, 304, 288, 208, 733, 245, 733, 733, 733, 733, - 418, 733, 733, 733, 733, 733, 288, 288, 288, 288, - 288, 343, 336, 279, 733, -57, 733, 19, 733, -91, - 574, 733, -91, 733, -7, -30, 733, -60, 1740, -91, - 733, 111, 1740, -91, 733, 2, 733, 733, 43, 37, - 733, -91, 34, 118, 23, -91, -91, 733, -91, 238, - 733, -91, -5, 733, -17, 1740, -91, 733, 133, 1740, - -91, -9, 194, -32, -8, 1827, -25, -91, 1740, -91, - 733, 100, 1740, 21, 1740, -91, 31, 26, -20, -91, - -91, 1740, -38, 283, 41, 291, 85, 733, 1740, -1, - -34, 252, 54, -27, 653, 9, 5, -91, 817, -91, - 6, -21, 7, 733, 11, -28, 733, 1, 733, -33, - -10, 733, -91, 1653, 33, -91, -91, -91, -91, -91, - -91, 733, -91, -91, -91, -91, 172, -91, 733, -24, - -91, 1740, -91, 73, -91, -91, 1740, -91, 733, 93, - 0, -91, 24, -91, 36, 122, 733, -91, 44, 48, - -91, -3, -91, 1740, -91, 110, 1740, -91, 192, -91, - -91, 124, 1740, 27, -91, -12, -29, -91, 155, -53, - -22, -91, -91, -91, -91, 733, 123, 1740, -91, 733, - 92, 1740, -91, -91, 105, 1229, -91, -91, 1146, -91, - -91, 1063, -91, -91, -91, -91, -91, -91, 90, -91, - -91, -91, -91, -91, -91, -91, 71, 70, 222, -91, - 733, -91, 164, -91, -91, -91, -91, -91, 1392, -91, - -91, -91, 268, -91, -91, 1914, 1312, -91, 75, -91, - -91, 350, 55, 303, 108, 733, 1740, 59, 38, 242, - 62, 40, 527, 63, 81, -91, 817, -91, 138, 29, - 65, 733, 78, 56, 733, 80, 733, 61, 66, 57, - 101, -91, 347, -91, -91, -91, -91, 64, -91, 140, - -91, -91, 733, -91, -91, 144, -91, -91, -91, - - -102, -102, -102, -102, 19, 103, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -4, 249, -102, -102, -102, -102, -102, -7, -102, -102, - -102, -102, -102, -102, 257, -102, -13, -102, -11, -102, - -102, -102, -102, -102, -102, -3, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -44, -102, - -102, -102, -102, -102, -102, -102, -102, -102, 141, -102, - -102, -102, -8, -102, 0, 16, 116, 122, 129, 119, - -102, -102, 90, 64, -102, -102, 94, -102, 91, 86, - -102, 71, 79, -102, -102, -102, -102, 159, 81, 76, - -102, -102, -102, -102, 98, -102, 67, 63, 47, 163, - -102, 160, 115, 104, 105, 127, 133, -102, 151, 144, - 130, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, 145, -102, 152, -102, 162, 31, 21, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, 23, -102, -102, -102, -102, -102, - 29, -102, -102, -102, -102, 34, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, 89, - -102, 68, 36, -102, -102, 42, -102, 235, 46, 49, - -102, -102, -102, -102, -102, -102, -102, -102, 33, -102, - -102, -102, 26, -102, -102, -18, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, 53, -102, -102, 8, 20, -102, -5, -102, 32, - -102, -102, -102, -102, 39, -102, -102, -102, 37, 73, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, 40, -102, -102, -102, -102, 97, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, 41, 213, -102, 186, 199, 203, 209, - -102, 50, 51, 38, 57, 60, -102, -102, -102, -102, - -102, -102, -102, -102, 212, -102, 174, -102, 166, -102, - -102, 168, -102, 125, -102, -102, 61, -102, 1, -102, - 45, -102, -9, -102, 172, -102, 184, 176, -102, -102, - 170, -102, -102, -102, -102, -102, -102, 215, -102, 124, - 132, -102, -102, 178, -102, -29, -102, 25, -102, 2, - -102, -102, 62, -102, -102, 102, -102, -102, -28, -102, - 22, -102, -31, -102, -33, -102, -102, -102, -102, -102, - -102, -34, -102, 17, -102, 18, -102, 111, -20, -102, - -102, 24, -102, -102, 153, -102, -102, -102, 30, -102, - -102, -102, -102, 28, -102, 73, 140, -102, 205, -102, - -102, 5, -102, 44, -102, -102, -102, -102, -102, -102, - -102, 43, -102, -102, -102, -102, -102, -102, 135, -102, - -102, 7, -102, -102, -102, -102, 4, -102, 55, -102, - -102, -102, -102, -102, -25, -102, 48, -102, 9, -102, - -102, -102, -102, -69, -102, -102, -70, -102, -102, -102, - -102, -102, -102, -92, -102, -102, -12, -102, -10, -102, - -1, -102, -102, -102, -102, 11, -102, -40, -102, 14, - -102, -39, -102, -102, -102, -17, -102, -102, 54, -102, - -102, -24, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - 3, -102, -102, -102, -102, -102, -102, -102, 267, -102, - -102, -102, 12, -102, -102, -102, 301, -102, -102, -102, - -102, -19, -102, -15, -102, 59, -64, -102, -102, -2, - -102, -102, 142, -102, -102, -102, -14, -102, -102, -102, - -102, 6, -102, 73, 52, -102, 75, -102, -102, -102, - -102, -102, 128, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -6, -102, -102, 58, -102, -102, -102}; - -const int JavaScriptGrammar::action_info [] = { - 338, 174, 289, 485, 472, 472, -89, 480, -105, 380, - 43, 472, -79, -78, -100, 448, -97, 435, -102, 134, - 304, 326, 132, 104, 478, 375, 489, 372, 374, 456, - 377, 336, 199, 452, 423, 433, 440, 384, 421, 205, - 431, 456, 132, 365, 350, 344, 214, 476, -108, 456, - 324, 357, 462, 199, 367, 463, 363, 222, 472, 446, - 441, -75, -108, 182, 485, 448, -89, 588, 180, -75, - -97, 489, -100, 2, 289, 525, 380, 104, 224, 7, - 225, 582, 134, 304, 378, -102, 289, -105, -79, 472, - -65, 283, 328, 344, 268, 326, 2, 485, 174, 518, - 174, 174, 489, 333, 284, 218, 324, 372, 174, 572, - 174, 38, 91, 498, 91, 174, 0, 466, 174, 174, - 0, 0, 0, 92, 20, 92, 359, 91, 91, 346, - 475, 174, 459, 347, 445, 444, 576, 575, 92, 92, - 95, 174, 21, 174, 476, -78, 281, 280, 585, 39, - 509, 96, 491, 450, 12, 9, 8, 573, 175, 12, - 382, 499, 201, 212, 281, 280, 202, 279, 278, 281, - 280, 342, 174, 12, 274, 273, 45, 460, 528, 360, - 288, 287, 174, 487, 12, 0, 20, 207, 136, 97, - 12, 13, 16, 369, 41, 286, 13, 16, 207, 39, - 174, 586, 584, 0, 21, 40, 208, 137, 438, 138, - 13, 16, 174, 12, 0, 0, 0, 208, 0, 209, - 12, 13, 16, 12, 0, 524, 523, 13, 16, 520, - 46, 44, 12, 0, 98, 184, 183, 12, 0, 118, - 99, 119, 97, 118, 41, 119, 118, 97, 119, 0, - 13, 16, 120, 470, 469, 40, 120, 13, 16, 120, - 13, 16, 12, 306, 307, 267, 266, 12, 0, 13, - 16, 12, 0, 0, 13, 16, 174, 0, -319, 306, - 307, 12, 0, 521, 519, 0, 0, 98, -319, 0, - 308, 309, 98, 99, 106, 107, 106, 107, 99, 13, - 16, 21, 311, 312, 13, 16, 308, 309, 13, 16, - 12, 313, 12, 118, 314, 119, 315, 0, 13, 16, - 12, 108, 109, 108, 109, 12, 120, 311, 312, 267, - 266, 0, 12, 0, 0, 0, 313, 0, 0, 314, - 0, 315, 277, 276, 272, 271, 0, 13, 16, 13, - 16, 12, 277, 276, 0, 15, 0, 13, 16, 311, - 312, 0, 13, 16, 277, 276, 311, 312, 313, 13, - 16, 314, 0, 315, 0, 313, 12, 0, 314, 12, - 315, 14, 0, 272, 271, 111, 112, 0, 13, 16, - 0, 0, 0, 113, 114, 111, 112, 115, 0, 116, - 0, 0, 0, 113, 114, 0, 15, 115, 0, 116, - 0, 272, 271, 13, 16, 0, 13, 16, 26, 111, - 112, 0, 0, 0, 0, 0, 0, 113, 114, 0, - 27, 115, 14, 116, 0, 111, 112, 12, 0, 26, - 0, 311, 312, 113, 114, 0, 0, 115, 0, 116, - 313, 27, 0, 314, 0, 315, 0, 0, 12, 0, - 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, - 0, 0, 0, 0, 28, 30, 0, 0, 0, 0, - 0, 0, 31, 0, 526, 0, 0, 0, 15, 0, - 0, 25, 0, 14, 0, 28, 30, 186, 0, 0, - 0, 0, 0, 31, 0, 0, 0, 187, 0, 111, - 112, 188, 25, 0, 14, 0, 0, 113, 114, 0, - 189, 115, 190, 116, 0, 340, 0, 0, 0, 0, - 0, 0, 0, 191, 0, 192, 95, 0, 0, 69, - 70, 0, 0, 193, 0, 0, 194, 96, 0, 72, - 0, 0, 195, 0, 0, 0, 12, 0, 196, 0, - 73, 74, 0, 75, 0, 0, 0, 0, 0, 0, - 78, 0, 0, 197, 81, 0, 0, 186, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 187, 0, 0, - 0, 188, 84, 13, 16, 0, 85, 0, 0, 0, - 189, 0, 190, 0, 0, 0, 0, 80, 87, 71, - 0, 0, 0, 191, 0, 192, 95, 0, 0, 0, - 0, 0, 0, 193, 0, 0, 194, 96, 0, 0, - 0, 0, 195, 0, 0, 0, 0, 0, 196, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 69, 70, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, - 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, - 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, - 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, - 16, 0, 85, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 69, 70, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, - 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, - 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, - 81, 0, 0, 0, 82, 0, 83, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, - 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, - 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, - 0, 0, 0, 0, -98, 0, 0, 0, 68, 69, - 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, - 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, - 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, - 88, 0, 89, 0, 0, 0, 0, 80, 87, 71, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 69, - 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, - 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, - 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, - 88, 303, 89, 0, 0, 0, 0, 80, 87, 71, - 0, 0, 0, 0, 0, 0, 0, 0, 496, 0, - 0, 68, 69, 70, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 0, 0, 0, 0, 0, 0, 12, - 0, 0, 0, 73, 74, 0, 75, 0, 0, 0, - 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, - 0, 82, 0, 83, 0, 0, 497, 0, 0, 0, - 0, 0, 0, 0, 0, 84, 13, 16, 0, 85, - 0, 86, 0, 88, 0, 89, 0, 0, 0, 0, - 80, 87, 71, 0, 0, 0, 0, 0, 0, 0, - 0, 504, 0, 0, 68, 69, 70, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, - 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, - 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, - 81, 0, 0, 0, 82, 0, 83, 0, 0, 505, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, - 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, - 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, - 0, 0, 0, 0, 496, 0, 0, 68, 69, 70, - 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, - 0, 0, 0, 0, 0, 12, 0, 0, 0, 73, - 74, 0, 75, 0, 0, 0, 76, 0, 77, 78, - 79, 0, 0, 81, 0, 0, 0, 82, 0, 83, - 0, 0, 502, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 13, 16, 0, 85, 0, 86, 0, 88, - 0, 89, 0, 0, 0, 0, 80, 87, 71, 0, - 0, 0, 0, 0, 0, 0, 0, 504, 0, 0, - 68, 69, 70, 0, 0, 0, 0, 0, 0, 0, - 0, 72, 0, 0, 0, 0, 0, 0, 12, 0, - 0, 0, 73, 74, 0, 75, 0, 0, 0, 76, - 0, 77, 78, 79, 0, 0, 81, 0, 0, 0, - 82, 0, 83, 0, 0, 507, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 13, 16, 0, 85, 0, - 86, 0, 88, 0, 89, 0, 0, 0, 0, 80, - 87, 71, 0, 0, 0, 0, 0, 0, 0, 0, - 496, 0, 0, 68, 69, 70, 0, 0, 0, 0, - 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, - 0, 12, 0, 0, 0, 73, 74, 0, 75, 0, - 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, - 0, 0, 0, 82, 0, 83, 0, 0, 497, 0, - 0, 15, 0, 0, 0, 0, 0, 84, 13, 16, - 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, - 0, 0, 80, 87, 71, 0, 0, 14, 0, 0, - 0, 0, 0, 68, 69, 70, 0, 0, 0, 0, - 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, - 0, 12, 251, 0, 0, 535, 536, 0, 75, 0, - 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, - 0, 0, 0, 82, 0, 83, 0, 0, 0, 0, - 0, 0, 0, 255, 0, 0, 0, 84, 13, 16, - 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, - 0, 0, 80, 87, 71, 0, 246, 0, 537, 0, - 0, 0, 0, 142, 143, 144, 0, 0, 146, 148, - 149, 0, 0, 150, 0, 151, 0, 0, 0, 153, - 154, 155, 0, 0, 0, 0, 0, 0, 12, 156, - 157, 158, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, - 0, 0, 0, 0, 0, 13, 16, 163, 164, 165, - 0, 167, 168, 169, 170, 171, 172, 0, 0, 160, - 166, 152, 145, 147, 161, 0, 0, 0, 0, 0, - 142, 143, 144, 0, 0, 146, 148, 149, 0, 0, - 150, 0, 151, 0, 0, 0, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 425, 156, 157, 158, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, - 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, - 0, 430, 427, 429, 163, 164, 165, 0, 167, 168, - 169, 170, 171, 172, 0, 0, 160, 166, 152, 145, - 147, 161, 0, 0, 0, 0, 0, 142, 143, 144, - 0, 0, 146, 148, 149, 0, 0, 150, 0, 151, - 0, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 425, 156, 157, 158, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, - 426, 0, 0, 0, 0, 0, 0, 0, 428, 0, - 0, 0, 162, 0, 0, 0, 0, 0, 430, 427, - 429, 163, 164, 165, 0, 167, 168, 169, 170, 171, - 172, 0, 0, 160, 166, 152, 145, 147, 161, 0, - 0, 0, 0, 0, 244, 0, 0, 0, 0, 245, - 0, 68, 69, 70, 247, 0, 0, 0, 0, 0, - 0, 248, 72, 0, 0, 0, 0, 0, 0, 250, - 251, 0, 0, 252, 74, 0, 75, 0, 0, 0, - 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, - 0, 82, 0, 83, 0, 0, 0, 0, 0, 254, - 0, 255, 0, 0, 0, 84, 253, 256, 257, 85, - 258, 86, 259, 88, 31, 89, 260, 261, 0, 0, - 80, 87, 71, 25, 246, 0, 0, 0, 0, 0, - 0, 244, 0, 0, 0, 0, 245, 0, 68, 69, - 70, 247, 0, 0, 0, 0, 0, 0, 248, 249, - 0, 0, 0, 0, 0, 0, 250, 251, 0, 0, - 252, 74, 0, 75, 0, 0, 0, 76, 0, 77, - 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, - 83, 0, 0, 0, 0, 0, 254, 0, 255, 0, - 0, 0, 84, 253, 256, 257, 85, 258, 86, 259, - 88, 31, 89, 260, 261, 0, 0, 80, 87, 71, - 25, 246, 0, 0, 0, 0, 0, 0, 541, 143, - 144, 0, 0, 543, 148, 545, 69, 70, 546, 0, - 151, 0, 0, 0, 153, 548, 549, 0, 0, 0, - 0, 0, 0, 550, 551, 157, 158, 252, 74, 0, - 75, 0, 0, 0, 76, 0, 77, 552, 79, 0, - 0, 554, 0, 0, 0, 82, 0, 83, 0, 0, - 0, 0, 0, 556, 0, 255, 0, 0, 0, 558, - 555, 557, 559, 560, 561, 86, 563, 564, 565, 566, - 567, 568, 0, 0, 553, 562, 547, 542, 544, 161, - 0, 0, 0, 0, 0, 393, 143, 144, 0, 0, - 395, 148, 397, 69, 70, 398, 0, 151, 0, 0, - 0, 153, 400, 401, 0, 0, 0, 0, 0, 0, - 402, 403, 157, 158, 252, 74, 0, 75, 0, 0, - 0, 76, 0, 77, 404, 79, 0, 0, 406, 0, - 0, 0, 82, 0, 83, 0, -244, 0, 0, 0, - 408, 0, 255, 0, 0, 0, 410, 407, 409, 411, - 412, 413, 86, 415, 416, 417, 418, 419, 420, 0, - 0, 405, 414, 399, 394, 396, 161, 0, 0, 0, - 0, 0, - - 334, 477, 282, 482, 270, 503, 467, 464, 275, 42, - 577, 55, 506, 479, 481, 217, 516, 522, 185, 23, - 468, 217, 540, 583, 10, 486, 488, 492, 490, 493, - 508, 270, 434, 385, 422, 383, 381, 366, 379, 368, - 270, 275, 468, 275, 334, 173, 282, 217, 242, 223, - 179, 468, 176, 334, 285, 371, 221, 343, 181, 341, - 211, 282, 465, 198, 352, 204, 457, 339, 370, 449, - 447, 206, 432, 442, 424, 334, 0, 93, 179, 501, - 0, 577, 318, 500, 213, 221, 93, 0, 471, 93, - 93, 93, 130, 483, 316, 317, 93, 461, 93, 93, - 215, 319, 93, 93, 320, 514, 93, 93, 129, 17, - 93, 0, 110, 94, 93, 93, 484, 102, 93, 242, - 93, 103, 101, 203, 337, 93, 11, 484, 93, 93, - 93, 513, 483, 93, 574, 515, 298, 93, 587, 334, - 0, 302, 200, 93, 93, 105, 334, 352, 125, 126, - 93, 11, 215, 269, 93, 93, 373, 510, 93, 124, - 512, 93, 436, 511, 179, 437, 93, 0, 242, 93, - 439, 127, 93, 123, 0, 436, 0, 128, 437, 93, - 93, 483, 215, 93, 93, 139, 436, 122, 335, 437, - 93, 93, 334, 141, 121, 362, 133, 376, 93, 93, - 100, 135, 93, 0, 117, 330, 361, 330, 131, 330, - 302, 93, 302, 93, 302, 330, 302, 0, 302, 0, - 302, 0, 0, 93, 327, 93, 345, 329, 302, 332, - 302, 351, 310, 0, 0, 0, 0, 349, 93, 0, - 348, 364, 93, 302, 93, 321, 484, 302, 93, 322, - 0, 93, 93, 302, 330, 323, 302, 302, 139, 302, - 35, 305, 0, 0, 325, 527, 141, 210, 35, 0, - 24, 37, 11, 0, 0, 0, 358, 0, 24, 37, - 11, 532, 529, 531, 533, 530, 534, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 569, 0, 0, 0, 0, 0, - 493, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0}; - -const int JavaScriptGrammar::action_check [] = { - 60, 8, 36, 36, 33, 33, 7, 60, 7, 36, - 29, 33, 7, 7, 7, 36, 7, 55, 7, 78, - 1, 78, 48, 1, 36, 33, 36, 36, 60, 5, - 55, 61, 2, 33, 8, 55, 60, 16, 7, 7, - 7, 5, 48, 60, 7, 2, 60, 20, 7, 5, - 48, 17, 55, 2, 31, 7, 61, 8, 33, 7, - 7, 7, 7, 60, 36, 36, 7, 0, 8, 7, - 7, 36, 7, 88, 36, 29, 36, 1, 60, 65, - 33, 17, 78, 1, 7, 7, 36, 7, 7, 33, - 33, 76, 8, 2, 55, 78, 88, 36, 8, 29, - 8, 8, 36, 61, 36, 36, 48, 36, 8, 8, - 8, 66, 40, 8, 40, 8, -1, 7, 8, 8, - -1, -1, -1, 51, 15, 51, 8, 40, 40, 50, - 6, 8, 10, 54, 61, 62, 61, 62, 51, 51, - 42, 8, 33, 8, 20, 7, 61, 62, 8, 29, - 60, 53, 60, 60, 29, 61, 62, 56, 56, 29, - 60, 56, 50, 56, 61, 62, 54, 61, 62, 61, - 62, 60, 8, 29, 61, 62, 7, 55, 7, 61, - 61, 62, 8, 60, 29, -1, 15, 15, 15, 12, - 29, 66, 67, 60, 74, 60, 66, 67, 15, 29, - 8, 61, 62, -1, 33, 85, 34, 34, 36, 36, - 66, 67, 8, 29, -1, -1, -1, 34, -1, 36, - 29, 66, 67, 29, -1, 61, 62, 66, 67, 7, - 61, 62, 29, -1, 57, 61, 62, 29, -1, 25, - 63, 27, 12, 25, 74, 27, 25, 12, 27, -1, - 66, 67, 38, 61, 62, 85, 38, 66, 67, 38, - 66, 67, 29, 18, 19, 61, 62, 29, -1, 66, - 67, 29, -1, -1, 66, 67, 8, -1, 36, 18, - 19, 29, -1, 61, 62, -1, -1, 57, 36, -1, - 45, 46, 57, 63, 18, 19, 18, 19, 63, 66, - 67, 33, 23, 24, 66, 67, 45, 46, 66, 67, - 29, 32, 29, 25, 35, 27, 37, -1, 66, 67, - 29, 45, 46, 45, 46, 29, 38, 23, 24, 61, - 62, -1, 29, -1, -1, -1, 32, -1, -1, 35, - -1, 37, 61, 62, 61, 62, -1, 66, 67, 66, - 67, 29, 61, 62, -1, 59, -1, 66, 67, 23, - 24, -1, 66, 67, 61, 62, 23, 24, 32, 66, - 67, 35, -1, 37, -1, 32, 29, -1, 35, 29, - 37, 85, -1, 61, 62, 23, 24, -1, 66, 67, - -1, -1, -1, 31, 32, 23, 24, 35, -1, 37, - -1, -1, -1, 31, 32, -1, 59, 35, -1, 37, - -1, 61, 62, 66, 67, -1, 66, 67, 10, 23, - 24, -1, -1, -1, -1, -1, -1, 31, 32, -1, - 22, 35, 85, 37, -1, 23, 24, 29, -1, 10, - -1, 23, 24, 31, 32, -1, -1, 35, -1, 37, - 32, 22, -1, 35, -1, 37, -1, -1, 29, -1, - -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, - -1, -1, -1, -1, 66, 67, -1, -1, -1, -1, - -1, -1, 74, -1, 55, -1, -1, -1, 59, -1, - -1, 83, -1, 85, -1, 66, 67, 3, -1, -1, - -1, -1, -1, 74, -1, -1, -1, 13, -1, 23, - 24, 17, 83, -1, 85, -1, -1, 31, 32, -1, - 26, 35, 28, 37, -1, 31, -1, -1, -1, -1, - -1, -1, -1, 39, -1, 41, 42, -1, -1, 12, - 13, -1, -1, 49, -1, -1, 52, 53, -1, 22, - -1, -1, 58, -1, -1, -1, 29, -1, 64, -1, - 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, - 43, -1, -1, 79, 47, -1, -1, 3, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, - -1, 17, 65, 66, 67, -1, 69, -1, -1, -1, - 26, -1, 28, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, 39, -1, 41, 42, -1, -1, -1, - -1, -1, -1, 49, -1, -1, 52, 53, -1, -1, - -1, -1, 58, -1, -1, -1, -1, -1, 64, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 79, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, -1, 69, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, - -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, - -1, -1, -1, -1, 7, -1, -1, -1, 11, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, - 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, - 73, 74, 75, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, - -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, - -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, - -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, - 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, - -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, - -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, - 80, 81, 82, -1, -1, -1, -1, -1, -1, -1, - -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, - -1, 75, -1, -1, -1, -1, 80, 81, 82, -1, - -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, - 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, - -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, - 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, - -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, - 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, - 81, 82, -1, -1, -1, -1, -1, -1, -1, -1, - 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, - -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, - -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, - -1, -1, 80, 81, 82, -1, -1, 85, -1, -1, - -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, - -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, - -1, -1, 80, 81, 82, -1, 84, -1, 86, -1, - -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, - 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, - 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, - 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, - -1, -1, -1, -1, -1, 66, 67, 68, 69, 70, - -1, 72, 73, 74, 75, 76, 77, -1, -1, 80, - 81, 82, 83, 84, 85, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, - -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, - 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, - 84, 85, -1, -1, -1, -1, -1, 4, 5, 6, - -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, - -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, - -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, - -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, - 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, - 77, -1, -1, 80, 81, 82, 83, 84, 85, -1, - -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, - -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, - -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, - 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, - 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, - -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, -1, -1, - 80, 81, 82, 83, 84, -1, -1, -1, -1, -1, - -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, - 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, - -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, - -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, - 83, 84, -1, -1, -1, -1, -1, -1, 4, 5, - 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, - 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, -1, -1, 80, 81, 82, 83, 84, 85, - -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, - 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, - -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, - 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, - -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, - -1, -1, 51, -1, 53, -1, 55, -1, -1, -1, - 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, -1, - -1, 80, 81, 82, 83, 84, 85, -1, -1, -1, - -1, -1, - - 14, 93, 66, 15, 23, 29, 76, 76, 23, 20, - 23, 14, 29, 23, 15, 23, 23, 14, 62, 23, - 14, 23, 10, 29, 5, 14, 66, 66, 14, 29, - 14, 23, 66, 66, 29, 66, 14, 66, 66, 14, - 23, 23, 14, 23, 14, 14, 66, 23, 66, 23, - 29, 14, 29, 14, 14, 23, 23, 66, 29, 14, - 14, 66, 14, 29, 23, 29, 91, 66, 66, 14, - 66, 29, 29, 66, 30, 14, -1, 39, 29, 25, - -1, 23, 44, 29, 35, 23, 39, -1, 15, 39, - 39, 39, 45, 41, 44, 44, 39, 88, 39, 39, - 41, 44, 39, 39, 44, 41, 39, 39, 45, 6, - 39, -1, 45, 42, 39, 39, 41, 41, 39, 66, - 39, 42, 41, 55, 63, 39, 23, 41, 39, 39, - 39, 41, 41, 39, 6, 41, 39, 39, 80, 14, - -1, 44, 53, 39, 39, 47, 14, 23, 44, 44, - 39, 23, 41, 100, 39, 39, 94, 41, 39, 44, - 41, 39, 33, 41, 29, 36, 39, -1, 66, 39, - 35, 44, 39, 43, -1, 33, -1, 44, 36, 39, - 39, 41, 41, 39, 39, 23, 33, 43, 63, 36, - 39, 39, 14, 31, 43, 63, 51, 95, 39, 39, - 41, 49, 39, -1, 44, 39, 82, 39, 45, 39, - 44, 39, 44, 39, 44, 39, 44, -1, 44, -1, - 44, -1, -1, 39, 50, 39, 54, 61, 44, 61, - 44, 61, 46, -1, -1, -1, -1, 61, 39, -1, - 56, 63, 39, 44, 39, 46, 41, 44, 39, 46, - -1, 39, 39, 44, 39, 46, 44, 44, 23, 44, - 11, 48, -1, -1, 52, 8, 31, 32, 11, -1, - 21, 22, 23, -1, -1, -1, 61, -1, 21, 22, - 23, 14, 15, 16, 17, 18, 19, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, - 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1}; - diff --git a/src/declarative/qml/parser/javascriptgrammar_p.h b/src/declarative/qml/parser/javascriptgrammar_p.h deleted file mode 100644 index 830f533..0000000 --- a/src/declarative/qml/parser/javascriptgrammar_p.h +++ /dev/null @@ -1,200 +0,0 @@ -// This file was generated by qlalr - DO NOT EDIT! -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef JAVASCRIPTGRAMMAR_P_H -#define JAVASCRIPTGRAMMAR_P_H - -class JavaScriptGrammar -{ -public: - enum { - EOF_SYMBOL = 0, - REDUCE_HERE = 90, - SHIFT_THERE = 89, - T_AND = 1, - T_AND_AND = 2, - T_AND_EQ = 3, - T_AUTOMATIC_SEMICOLON = 62, - T_BREAK = 4, - T_CASE = 5, - T_CATCH = 6, - T_COLON = 7, - T_COMMA = 8, - T_CONST = 83, - T_CONTINUE = 9, - T_DEBUGGER = 84, - T_DEFAULT = 10, - T_DELETE = 11, - T_DIVIDE_ = 12, - T_DIVIDE_EQ = 13, - T_DO = 14, - T_DOT = 15, - T_ELSE = 16, - T_EQ = 17, - T_EQ_EQ = 18, - T_EQ_EQ_EQ = 19, - T_FALSE = 82, - T_FINALLY = 20, - T_FOR = 21, - T_FUNCTION = 22, - T_GE = 23, - T_GT = 24, - T_GT_GT = 25, - T_GT_GT_EQ = 26, - T_GT_GT_GT = 27, - T_GT_GT_GT_EQ = 28, - T_IDENTIFIER = 29, - T_IF = 30, - T_IMPORT = 88, - T_IN = 31, - T_INSTANCEOF = 32, - T_LBRACE = 33, - T_LBRACKET = 34, - T_LE = 35, - T_LPAREN = 36, - T_LT = 37, - T_LT_LT = 38, - T_LT_LT_EQ = 39, - T_MINUS = 40, - T_MINUS_EQ = 41, - T_MINUS_MINUS = 42, - T_MULTILINE_STRING_LITERAL = 86, - T_NEW = 43, - T_NOT = 44, - T_NOT_EQ = 45, - T_NOT_EQ_EQ = 46, - T_NULL = 80, - T_NUMERIC_LITERAL = 47, - T_OR = 48, - T_OR_EQ = 49, - T_OR_OR = 50, - T_PLUS = 51, - T_PLUS_EQ = 52, - T_PLUS_PLUS = 53, - T_PROPERTY = 66, - T_PUBLIC = 87, - T_QUESTION = 54, - T_RBRACE = 55, - T_RBRACKET = 56, - T_REMAINDER = 57, - T_REMAINDER_EQ = 58, - T_RESERVED_WORD = 85, - T_RETURN = 59, - T_RPAREN = 60, - T_SEMICOLON = 61, - T_SIGNAL = 67, - T_STAR = 63, - T_STAR_EQ = 64, - T_STRING_LITERAL = 65, - T_SWITCH = 68, - T_THIS = 69, - T_THROW = 70, - T_TILDE = 71, - T_TRUE = 81, - T_TRY = 72, - T_TYPEOF = 73, - T_VAR = 74, - T_VOID = 75, - T_WHILE = 76, - T_WITH = 77, - T_XOR = 78, - T_XOR_EQ = 79, - - ACCEPT_STATE = 588, - RULE_COUNT = 323, - STATE_COUNT = 589, - TERMINAL_COUNT = 91, - NON_TERMINAL_COUNT = 102, - - GOTO_INDEX_OFFSET = 589, - GOTO_INFO_OFFSET = 2092, - GOTO_CHECK_OFFSET = 2092 - }; - - static const char *const spell []; - static const int lhs []; - static const int rhs []; - static const int goto_default []; - static const int action_default []; - static const int action_index []; - static const int action_info []; - static const int action_check []; - - static inline int nt_action (int state, int nt) - { - const int *const goto_index = &action_index [GOTO_INDEX_OFFSET]; - const int *const goto_check = &action_check [GOTO_CHECK_OFFSET]; - - const int yyn = goto_index [state] + nt; - - if (yyn < 0 || goto_check [yyn] != nt) - return goto_default [nt]; - - const int *const goto_info = &action_info [GOTO_INFO_OFFSET]; - return goto_info [yyn]; - } - - static inline int t_action (int state, int token) - { - const int yyn = action_index [state] + token; - - if (yyn < 0 || action_check [yyn] != token) - return - action_default [state]; - - return action_info [yyn]; - } -}; - - -#endif // JAVASCRIPTGRAMMAR_P_H - diff --git a/src/declarative/qml/parser/javascriptlexer.cpp b/src/declarative/qml/parser/javascriptlexer.cpp deleted file mode 100644 index ea36a7a..0000000 --- a/src/declarative/qml/parser/javascriptlexer.cpp +++ /dev/null @@ -1,1196 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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$ -** -****************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "javascriptengine_p.h" -#include "javascriptlexer_p.h" -#include "javascriptgrammar_p.h" - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -extern double qstrtod(const char *s00, char const **se, bool *ok); - -#define shiftWindowsLineBreak() \ - do { \ - if (((current == '\r') && (next1 == '\n')) \ - || ((current == '\n') && (next1 == '\r'))) { \ - shift(1); \ - } \ - } \ - while (0) - -namespace JavaScript { -extern double integerFromString(const char *buf, int size, int radix); -} - -using namespace JavaScript; - -Lexer::Lexer(Engine *eng) - : driver(eng), - yylineno(0), - done(false), - size8(128), size16(128), - pos8(0), pos16(0), - terminator(false), - restrKeyword(false), - delimited(false), - stackToken(-1), - state(Start), - pos(0), - code(0), length(0), - yycolumn(0), - startpos(0), - startlineno(0), startcolumn(0), - bol(true), - current(0), next1(0), next2(0), next3(0), - err(NoError), - wantRx(false), - check_reserved(true), - parenthesesState(IgnoreParentheses), - parenthesesCount(0), - prohibitAutomaticSemicolon(false) -{ - driver->setLexer(this); - // allocate space for read buffers - buffer8 = new char[size8]; - buffer16 = new QChar[size16]; - pattern = 0; - flags = 0; - -} - -Lexer::~Lexer() -{ - delete [] buffer8; - delete [] buffer16; -} - -void Lexer::setCode(const QString &c, int lineno) -{ - errmsg = QString(); - yylineno = lineno; - yycolumn = 1; - restrKeyword = false; - delimited = false; - stackToken = -1; - pos = 0; - code = c.unicode(); - length = c.length(); - bol = true; - - // read first characters - current = (length > 0) ? code[0].unicode() : 0; - next1 = (length > 1) ? code[1].unicode() : 0; - next2 = (length > 2) ? code[2].unicode() : 0; - next3 = (length > 3) ? code[3].unicode() : 0; -} - -void Lexer::shift(uint p) -{ - while (p--) { - ++pos; - ++yycolumn; - current = next1; - next1 = next2; - next2 = next3; - next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0; - } -} - -void Lexer::setDone(State s) -{ - state = s; - done = true; -} - -int Lexer::findReservedWord(const QChar *c, int size) const -{ - switch (size) { - case 2: { - if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')) - return JavaScriptGrammar::T_DO; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f')) - return JavaScriptGrammar::T_IF; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')) - return JavaScriptGrammar::T_IN; - } break; - - case 3: { - if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r')) - return JavaScriptGrammar::T_FOR; - else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w')) - return JavaScriptGrammar::T_NEW; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y')) - return JavaScriptGrammar::T_TRY; - else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r')) - return JavaScriptGrammar::T_VAR; - else if (check_reserved) { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 4: { - if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) - return JavaScriptGrammar::T_CASE; - else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) - return JavaScriptGrammar::T_ELSE; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s')) - return JavaScriptGrammar::T_THIS; - else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d')) - return JavaScriptGrammar::T_VOID; - else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h')) - return JavaScriptGrammar::T_WITH; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e')) - return JavaScriptGrammar::T_TRUE; - else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l')) - return JavaScriptGrammar::T_NULL; - else if (check_reserved) { - if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n') - && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 5: { - if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('k')) - return JavaScriptGrammar::T_BREAK; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c') - && c[4] == QLatin1Char('h')) - return JavaScriptGrammar::T_CATCH; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('w')) - return JavaScriptGrammar::T_THROW; - else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('e')) - return JavaScriptGrammar::T_WHILE; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s') - && c[4] == QLatin1Char('t')) - return JavaScriptGrammar::T_CONST; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s') - && c[4] == QLatin1Char('e')) - return JavaScriptGrammar::T_FALSE; - else if (check_reserved) { - if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r') - && c[4] == QLatin1Char('t')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('r')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('l')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s') - && c[4] == QLatin1Char('s')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('t')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 6: { - if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e')) - return JavaScriptGrammar::T_DELETE; - else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n')) - return JavaScriptGrammar::T_RETURN; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h')) - return JavaScriptGrammar::T_SWITCH; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f')) - return JavaScriptGrammar::T_TYPEOF; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) - return JavaScriptGrammar::T_IMPORT; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l')) - return JavaScriptGrammar::T_SIGNAL; - else if (check_reserved) { - if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b') - && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) - return JavaScriptGrammar::T_PUBLIC; - else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i') - && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 7: { - if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l') - && c[6] == QLatin1Char('t')) - return JavaScriptGrammar::T_DEFAULT; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l') - && c[6] == QLatin1Char('y')) - return JavaScriptGrammar::T_FINALLY; - else if (check_reserved) { - if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a') - && c[6] == QLatin1Char('n')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d') - && c[6] == QLatin1Char('s')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g') - && c[6] == QLatin1Char('e')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t') - && c[6] == QLatin1Char('e')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 8: { - if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n') - && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e')) - return JavaScriptGrammar::T_CONTINUE; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') - && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') - && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')) - return JavaScriptGrammar::T_FUNCTION; - else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u') - && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g') - && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r')) - return JavaScriptGrammar::T_DEBUGGER; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r') - && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y')) - return JavaScriptGrammar::T_PROPERTY; - else if (check_reserved) { - if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a') - && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') - && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 9: { - if (check_reserved) { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f') - && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c') - && c[8] == QLatin1Char('e')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n') - && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i') - && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') - && c[8] == QLatin1Char('t')) - return JavaScriptGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c') - && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e') - && c[8] == QLatin1Char('d')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 10: { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n') - && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e') - && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f')) - return JavaScriptGrammar::T_INSTANCEOF; - else if (check_reserved) { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m') - && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') - && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - case 12: { - if (check_reserved) { - if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') - && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r') - && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n') - && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z') - && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d')) - return JavaScriptGrammar::T_RESERVED_WORD; - } - } break; - - } // switch - - return -1; -} - -int Lexer::lex() -{ - int token = 0; - state = Start; - ushort stringType = 0; // either single or double quotes - bool multiLineString = false; - pos8 = pos16 = 0; - done = false; - terminator = false; - - // did we push a token on the stack previously ? - // (after an automatic semicolon insertion) - if (stackToken >= 0) { - setDone(Other); - token = stackToken; - stackToken = -1; - } - - while (!done) { - switch (state) { - case Start: - if (isWhiteSpace()) { - // do nothing - } else if (current == '/' && next1 == '/') { - recordStartPos(); - shift(1); - state = InSingleLineComment; - } else if (current == '/' && next1 == '*') { - recordStartPos(); - shift(1); - state = InMultiLineComment; - } else if (current == 0) { - syncProhibitAutomaticSemicolon(); - if (!terminator && !delimited && !prohibitAutomaticSemicolon) { - // automatic semicolon insertion if program incomplete - token = JavaScriptGrammar::T_SEMICOLON; - stackToken = 0; - setDone(Other); - } else { - setDone(Eof); - } - } else if (isLineTerminator()) { - shiftWindowsLineBreak(); - yylineno++; - yycolumn = 0; - bol = true; - terminator = true; - syncProhibitAutomaticSemicolon(); - if (restrKeyword) { - token = JavaScriptGrammar::T_SEMICOLON; - setDone(Other); - } - } else if (current == '"' || current == '\'') { - recordStartPos(); - state = InString; - multiLineString = false; - stringType = current; - } else if (isIdentLetter(current)) { - recordStartPos(); - record16(current); - state = InIdentifier; - } else if (current == '0') { - recordStartPos(); - record8(current); - state = InNum0; - } else if (isDecimalDigit(current)) { - recordStartPos(); - record8(current); - state = InNum; - } else if (current == '.' && isDecimalDigit(next1)) { - recordStartPos(); - record8(current); - state = InDecimal; - } else { - recordStartPos(); - token = matchPunctuator(current, next1, next2, next3); - if (token != -1) { - if (terminator && !delimited && !prohibitAutomaticSemicolon - && (token == JavaScriptGrammar::T_PLUS_PLUS - || token == JavaScriptGrammar::T_MINUS_MINUS)) { - // automatic semicolon insertion - stackToken = token; - token = JavaScriptGrammar::T_SEMICOLON; - } - setDone(Other); - } - else { - setDone(Bad); - err = IllegalCharacter; - errmsg = QLatin1String("Illegal character"); - } - } - break; - case InString: - if (current == stringType) { - shift(1); - setDone(String); - } else if (isLineTerminator()) { - multiLineString = true; - record16(current); - } else if (current == 0 || isLineTerminator()) { - setDone(Bad); - err = UnclosedStringLiteral; - errmsg = QLatin1String("Unclosed string at end of line"); - } else if (current == '\\') { - state = InEscapeSequence; - } else { - record16(current); - } - break; - // Escape Sequences inside of strings - case InEscapeSequence: - if (isOctalDigit(current)) { - if (current >= '0' && current <= '3' && - isOctalDigit(next1) && isOctalDigit(next2)) { - record16(convertOctal(current, next1, next2)); - shift(2); - state = InString; - } else if (isOctalDigit(current) && - isOctalDigit(next1)) { - record16(convertOctal('0', current, next1)); - shift(1); - state = InString; - } else if (isOctalDigit(current)) { - record16(convertOctal('0', '0', current)); - state = InString; - } else { - setDone(Bad); - err = IllegalEscapeSequence; - errmsg = QLatin1String("Illegal escape squence"); - } - } else if (current == 'x') - state = InHexEscape; - else if (current == 'u') - state = InUnicodeEscape; - else { - if (isLineTerminator()) { - shiftWindowsLineBreak(); - yylineno++; - yycolumn = 0; - bol = true; - } else { - record16(singleEscape(current)); - } - state = InString; - } - break; - case InHexEscape: - if (isHexDigit(current) && isHexDigit(next1)) { - state = InString; - record16(QLatin1Char(convertHex(current, next1))); - shift(1); - } else if (current == stringType) { - record16(QLatin1Char('x')); - shift(1); - setDone(String); - } else { - record16(QLatin1Char('x')); - record16(current); - state = InString; - } - break; - case InUnicodeEscape: - if (isHexDigit(current) && isHexDigit(next1) && - isHexDigit(next2) && isHexDigit(next3)) { - record16(convertUnicode(current, next1, next2, next3)); - shift(3); - state = InString; - } else if (current == stringType) { - record16(QLatin1Char('u')); - shift(1); - setDone(String); - } else { - setDone(Bad); - err = IllegalUnicodeEscapeSequence; - errmsg = QLatin1String("Illegal unicode escape sequence"); - } - break; - case InSingleLineComment: - if (isLineTerminator()) { - shiftWindowsLineBreak(); - yylineno++; - yycolumn = 0; - terminator = true; - bol = true; - if (restrKeyword) { - token = JavaScriptGrammar::T_SEMICOLON; - setDone(Other); - } else - state = Start; - } else if (current == 0) { - setDone(Eof); - } - break; - case InMultiLineComment: - if (current == 0) { - setDone(Bad); - err = UnclosedComment; - errmsg = QLatin1String("Unclosed comment at end of file"); - } else if (isLineTerminator()) { - shiftWindowsLineBreak(); - yylineno++; - } else if (current == '*' && next1 == '/') { - state = Start; - shift(1); - } - break; - case InIdentifier: - if (isIdentLetter(current) || isDecimalDigit(current)) { - record16(current); - break; - } - setDone(Identifier); - break; - case InNum0: - if (current == 'x' || current == 'X') { - record8(current); - state = InHex; - } else if (current == '.') { - record8(current); - state = InDecimal; - } else if (current == 'e' || current == 'E') { - record8(current); - state = InExponentIndicator; - } else if (isOctalDigit(current)) { - record8(current); - state = InOctal; - } else if (isDecimalDigit(current)) { - record8(current); - state = InDecimal; - } else { - setDone(Number); - } - break; - case InHex: - if (isHexDigit(current)) - record8(current); - else - setDone(Hex); - break; - case InOctal: - if (isOctalDigit(current)) { - record8(current); - } else if (isDecimalDigit(current)) { - record8(current); - state = InDecimal; - } else { - setDone(Octal); - } - break; - case InNum: - if (isDecimalDigit(current)) { - record8(current); - } else if (current == '.') { - record8(current); - state = InDecimal; - } else if (current == 'e' || current == 'E') { - record8(current); - state = InExponentIndicator; - } else { - setDone(Number); - } - break; - case InDecimal: - if (isDecimalDigit(current)) { - record8(current); - } else if (current == 'e' || current == 'E') { - record8(current); - state = InExponentIndicator; - } else { - setDone(Number); - } - break; - case InExponentIndicator: - if (current == '+' || current == '-') { - record8(current); - } else if (isDecimalDigit(current)) { - record8(current); - state = InExponent; - } else { - setDone(Bad); - err = IllegalExponentIndicator; - errmsg = QLatin1String("Illegal syntax for exponential number"); - } - break; - case InExponent: - if (isDecimalDigit(current)) { - record8(current); - } else { - setDone(Number); - } - break; - default: - Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement"); - } - - // move on to the next character - if (!done) - shift(1); - if (state != Start && state != InSingleLineComment) - bol = false; - } - - if (state == Number) { - // CSS-style suffix for numeric literals - - flags = noSuffix; - - const ushort c = QChar::toLower(current); - const ushort n1 = QChar::toLower(next1); - const ushort n2 = QChar::toLower(next2); - const ushort n3 = QChar::toLower(next3); - - if (c == 'e' && n1 == 'm') { - flags = emSuffix; - shift(2); - } else if (c == 'e' && n1 == 'x') { - flags = exSuffix; - shift(2); - } else if (c == 'p' && n1 == 'x') { - flags = pxSuffix; - shift(2); - } else if (c == 'c' && n1 == 'm') { - flags = cmSuffix; - shift(2); - } else if (c == 'm' && n1 == 'm') { - flags = mmSuffix; - shift(2); - } else if (c == 'i' && n1 == 'n') { - flags = inSuffix; - shift(2); - } else if (c == 'p' && n1 == 't') { - flags = ptSuffix; - shift(2); - } else if (c == 'p' && n1 == 'c') { - flags = pcSuffix; - shift(1); - } else if (c == 'd' && n1 == 'e' && n2 == 'g') { - flags = degSuffix; - shift(3); - } else if (c == 'r' && n1 == 'a' && n2 == 'd') { - flags = radSuffix; - shift(3); - } else if (c == 'g' && n1 == 'r' && n2 == 'a' && n3 == 'd') { - flags = gradSuffix; - shift(4); - } else if (c == 'm' && n1 == 's') { - flags = msSuffix; - shift(2); - } else if (c == 's') { - flags = sSuffix; - shift(1); - } else if (c == 'h' && n1 == 'z') { - flags = hzSuffix; - shift(2); - } else if (c == 'k' && n1 == 'h' && n2 == 'z') { - flags = khzSuffix; - shift(3); - } - } - - // no identifiers allowed directly after numeric literal, e.g. "3in" is bad - if ((state == Number || state == Octal || state == Hex) - && isIdentLetter(current)) { - state = Bad; - err = IllegalIdentifier; - errmsg = QLatin1String("Identifier cannot start with numeric literal"); - } - - // terminate string - buffer8[pos8] = '\0'; - - double dval = 0; - if (state == Number) { - dval = qstrtod(buffer8, 0, 0); - } else if (state == Hex) { // scan hex numbers - dval = integerFromString(buffer8, pos8, 16); - state = Number; - } else if (state == Octal) { // scan octal number - dval = integerFromString(buffer8, pos8, 8); - state = Number; - } - - restrKeyword = false; - delimited = false; - - switch (parenthesesState) { - case IgnoreParentheses: - break; - case CountParentheses: - if (token == JavaScriptGrammar::T_RPAREN) { - --parenthesesCount; - if (parenthesesCount == 0) - parenthesesState = BalancedParentheses; - } else if (token == JavaScriptGrammar::T_LPAREN) { - ++parenthesesCount; - } - break; - case BalancedParentheses: - parenthesesState = IgnoreParentheses; - break; - } - - switch (state) { - case Eof: - return 0; - case Other: - if (token == JavaScriptGrammar::T_RBRACE || token == JavaScriptGrammar::T_SEMICOLON) - delimited = true; - return token; - case Identifier: - if ((token = findReservedWord(buffer16, pos16)) < 0) { - /* TODO: close leak on parse error. same holds true for String */ - if (driver) - qsyylval.ustr = driver->intern(buffer16, pos16); - else - qsyylval.ustr = 0; - return JavaScriptGrammar::T_IDENTIFIER; - } - if (token == JavaScriptGrammar::T_CONTINUE || token == JavaScriptGrammar::T_BREAK - || token == JavaScriptGrammar::T_RETURN || token == JavaScriptGrammar::T_THROW) { - restrKeyword = true; - } else if (token == JavaScriptGrammar::T_IF || token == JavaScriptGrammar::T_FOR - || token == JavaScriptGrammar::T_WHILE || token == JavaScriptGrammar::T_WITH) { - parenthesesState = CountParentheses; - parenthesesCount = 0; - } else if (token == JavaScriptGrammar::T_DO) { - parenthesesState = BalancedParentheses; - } - return token; - case String: - if (driver) - qsyylval.ustr = driver->intern(buffer16, pos16); - else - qsyylval.ustr = 0; - return multiLineString?JavaScriptGrammar::T_MULTILINE_STRING_LITERAL:JavaScriptGrammar::T_STRING_LITERAL; - case Number: - qsyylval.dval = dval; - return JavaScriptGrammar::T_NUMERIC_LITERAL; - case Bad: - return -1; - default: - Q_ASSERT(!"unhandled numeration value in switch"); - return -1; - } -} - -bool Lexer::isWhiteSpace() const -{ - return (current == ' ' || current == '\t' || - current == 0x0b || current == 0x0c); -} - -bool Lexer::isLineTerminator() const -{ - return (current == '\n' || current == '\r'); -} - -bool Lexer::isIdentLetter(ushort c) -{ - /* TODO: allow other legitimate unicode chars */ - return ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || c == '$' - || c == '_'); -} - -bool Lexer::isDecimalDigit(ushort c) -{ - return (c >= '0' && c <= '9'); -} - -bool Lexer::isHexDigit(ushort c) const -{ - return ((c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f') - || (c >= 'A' && c <= 'F')); -} - -bool Lexer::isOctalDigit(ushort c) const -{ - return (c >= '0' && c <= '7'); -} - -int Lexer::matchPunctuator(ushort c1, ushort c2, - ushort c3, ushort c4) -{ - if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { - shift(4); - return JavaScriptGrammar::T_GT_GT_GT_EQ; - } else if (c1 == '=' && c2 == '=' && c3 == '=') { - shift(3); - return JavaScriptGrammar::T_EQ_EQ_EQ; - } else if (c1 == '!' && c2 == '=' && c3 == '=') { - shift(3); - return JavaScriptGrammar::T_NOT_EQ_EQ; - } else if (c1 == '>' && c2 == '>' && c3 == '>') { - shift(3); - return JavaScriptGrammar::T_GT_GT_GT; - } else if (c1 == '<' && c2 == '<' && c3 == '=') { - shift(3); - return JavaScriptGrammar::T_LT_LT_EQ; - } else if (c1 == '>' && c2 == '>' && c3 == '=') { - shift(3); - return JavaScriptGrammar::T_GT_GT_EQ; - } else if (c1 == '<' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_LE; - } else if (c1 == '>' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_GE; - } else if (c1 == '!' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_NOT_EQ; - } else if (c1 == '+' && c2 == '+') { - shift(2); - return JavaScriptGrammar::T_PLUS_PLUS; - } else if (c1 == '-' && c2 == '-') { - shift(2); - return JavaScriptGrammar::T_MINUS_MINUS; - } else if (c1 == '=' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_EQ_EQ; - } else if (c1 == '+' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_PLUS_EQ; - } else if (c1 == '-' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_MINUS_EQ; - } else if (c1 == '*' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_STAR_EQ; - } else if (c1 == '/' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_DIVIDE_EQ; - } else if (c1 == '&' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_AND_EQ; - } else if (c1 == '^' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_XOR_EQ; - } else if (c1 == '%' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_REMAINDER_EQ; - } else if (c1 == '|' && c2 == '=') { - shift(2); - return JavaScriptGrammar::T_OR_EQ; - } else if (c1 == '<' && c2 == '<') { - shift(2); - return JavaScriptGrammar::T_LT_LT; - } else if (c1 == '>' && c2 == '>') { - shift(2); - return JavaScriptGrammar::T_GT_GT; - } else if (c1 == '&' && c2 == '&') { - shift(2); - return JavaScriptGrammar::T_AND_AND; - } else if (c1 == '|' && c2 == '|') { - shift(2); - return JavaScriptGrammar::T_OR_OR; - } - - switch(c1) { - case '=': shift(1); return JavaScriptGrammar::T_EQ; - case '>': shift(1); return JavaScriptGrammar::T_GT; - case '<': shift(1); return JavaScriptGrammar::T_LT; - case ',': shift(1); return JavaScriptGrammar::T_COMMA; - case '!': shift(1); return JavaScriptGrammar::T_NOT; - case '~': shift(1); return JavaScriptGrammar::T_TILDE; - case '?': shift(1); return JavaScriptGrammar::T_QUESTION; - case ':': shift(1); return JavaScriptGrammar::T_COLON; - case '.': shift(1); return JavaScriptGrammar::T_DOT; - case '+': shift(1); return JavaScriptGrammar::T_PLUS; - case '-': shift(1); return JavaScriptGrammar::T_MINUS; - case '*': shift(1); return JavaScriptGrammar::T_STAR; - case '/': shift(1); return JavaScriptGrammar::T_DIVIDE_; - case '&': shift(1); return JavaScriptGrammar::T_AND; - case '|': shift(1); return JavaScriptGrammar::T_OR; - case '^': shift(1); return JavaScriptGrammar::T_XOR; - case '%': shift(1); return JavaScriptGrammar::T_REMAINDER; - case '(': shift(1); return JavaScriptGrammar::T_LPAREN; - case ')': shift(1); return JavaScriptGrammar::T_RPAREN; - case '{': shift(1); return JavaScriptGrammar::T_LBRACE; - case '}': shift(1); return JavaScriptGrammar::T_RBRACE; - case '[': shift(1); return JavaScriptGrammar::T_LBRACKET; - case ']': shift(1); return JavaScriptGrammar::T_RBRACKET; - case ';': shift(1); return JavaScriptGrammar::T_SEMICOLON; - - default: return -1; - } -} - -ushort Lexer::singleEscape(ushort c) const -{ - switch(c) { - case 'b': - return 0x08; - case 't': - return 0x09; - case 'n': - return 0x0A; - case 'v': - return 0x0B; - case 'f': - return 0x0C; - case 'r': - return 0x0D; - case '"': - return 0x22; - case '\'': - return 0x27; - case '\\': - return 0x5C; - default: - return c; - } -} - -ushort Lexer::convertOctal(ushort c1, ushort c2, - ushort c3) const -{ - return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); -} - -unsigned char Lexer::convertHex(ushort c) -{ - if (c >= '0' && c <= '9') - return (c - '0'); - else if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - else - return (c - 'A' + 10); -} - -unsigned char Lexer::convertHex(ushort c1, ushort c2) -{ - return ((convertHex(c1) << 4) + convertHex(c2)); -} - -QChar Lexer::convertUnicode(ushort c1, ushort c2, - ushort c3, ushort c4) -{ - return QChar((convertHex(c3) << 4) + convertHex(c4), - (convertHex(c1) << 4) + convertHex(c2)); -} - -void Lexer::record8(ushort c) -{ - Q_ASSERT(c <= 0xff); - - // enlarge buffer if full - if (pos8 >= size8 - 1) { - char *tmp = new char[2 * size8]; - memcpy(tmp, buffer8, size8 * sizeof(char)); - delete [] buffer8; - buffer8 = tmp; - size8 *= 2; - } - - buffer8[pos8++] = (char) c; -} - -void Lexer::record16(QChar c) -{ - // enlarge buffer if full - if (pos16 >= size16 - 1) { - QChar *tmp = new QChar[2 * size16]; - memcpy(tmp, buffer16, size16 * sizeof(QChar)); - delete [] buffer16; - buffer16 = tmp; - size16 *= 2; - } - - buffer16[pos16++] = c; -} - -void Lexer::recordStartPos() -{ - startpos = pos; - startlineno = yylineno; - startcolumn = yycolumn; -} - -bool Lexer::scanRegExp(RegExpBodyPrefix prefix) -{ - pos16 = 0; - bool lastWasEscape = false; - - if (prefix == EqualPrefix) - record16(QLatin1Char('=')); - - while (1) { - if (isLineTerminator() || current == 0) { - errmsg = QLatin1String("Unterminated regular expression literal"); - return false; - } - else if (current != '/' || lastWasEscape == true) - { - record16(current); - lastWasEscape = !lastWasEscape && (current == '\\'); - } - else { - if (driver) - pattern = driver->intern(buffer16, pos16); - else - pattern = 0; - pos16 = 0; - shift(1); - break; - } - shift(1); - } - - flags = 0; - while (isIdentLetter(current)) { - int flag = Ecma::RegExp::flagFromChar(current); - if (flag == 0) { - errmsg = QString::fromLatin1("Invalid regular expression flag '%0'") - .arg(QChar(current)); - return false; - } - flags |= flag; - record16(current); - shift(1); - } - - return true; -} - -void Lexer::syncProhibitAutomaticSemicolon() -{ - if (parenthesesState == BalancedParentheses) { - // we have seen something like "if (foo)", which means we should - // never insert an automatic semicolon at this point, since it would - // then be expanded into an empty statement (ECMA-262 7.9.1) - prohibitAutomaticSemicolon = true; - parenthesesState = IgnoreParentheses; - } else { - prohibitAutomaticSemicolon = false; - } -} - -QT_END_NAMESPACE - - diff --git a/src/declarative/qml/parser/javascriptlexer_p.h b/src/declarative/qml/parser/javascriptlexer_p.h deleted file mode 100644 index a47c1ae..0000000 --- a/src/declarative/qml/parser/javascriptlexer_p.h +++ /dev/null @@ -1,269 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 JAVASCRIPTLEXER_P_H -#define JAVASCRIPTLEXER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - - - -QT_BEGIN_NAMESPACE - -namespace JavaScript { - -class Engine; -class NameId; - -class Lexer -{ -public: - Lexer(Engine *eng); - ~Lexer(); - - void setCode(const QString &c, int lineno); - int lex(); - - int currentLineNo() const { return yylineno; } - int currentColumnNo() const { return yycolumn; } - - int tokenOffset() const { return startpos; } - int tokenLength() const { return pos - startpos; } - - int startLineNo() const { return startlineno; } - int startColumnNo() const { return startcolumn; } - - int endLineNo() const { return currentLineNo(); } - int endColumnNo() const - { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; } - - bool prevTerminator() const { return terminator; } - - enum State { Start, - Identifier, - InIdentifier, - InSingleLineComment, - InMultiLineComment, - InNum, - InNum0, - InHex, - InOctal, - InDecimal, - InExponentIndicator, - InExponent, - Hex, - Octal, - Number, - String, - Eof, - InString, - InEscapeSequence, - InHexEscape, - InUnicodeEscape, - Other, - Bad }; - - enum Suffix { - noSuffix, - emSuffix, - exSuffix, - pxSuffix, - cmSuffix, - mmSuffix, - inSuffix, - ptSuffix, - pcSuffix, - degSuffix, - radSuffix, - gradSuffix, - msSuffix, - sSuffix, - hzSuffix, - khzSuffix - }; - - enum Error { - NoError, - IllegalCharacter, - UnclosedStringLiteral, - IllegalEscapeSequence, - IllegalUnicodeEscapeSequence, - UnclosedComment, - IllegalExponentIndicator, - IllegalIdentifier - }; - - enum ParenthesesState { - IgnoreParentheses, - CountParentheses, - BalancedParentheses - }; - - enum RegExpBodyPrefix { - NoPrefix, - EqualPrefix - }; - - bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); - - NameId *pattern; - int flags; - - State lexerState() const - { return state; } - - QString errorMessage() const - { return errmsg; } - void setErrorMessage(const QString &err) - { errmsg = err; } - void setErrorMessage(const char *err) - { setErrorMessage(QString::fromLatin1(err)); } - - Error error() const - { return err; } - void clearError() - { err = NoError; } - -private: - Engine *driver; - int yylineno; - bool done; - char *buffer8; - QChar *buffer16; - uint size8, size16; - uint pos8, pos16; - bool terminator; - bool restrKeyword; - // encountered delimiter like "'" and "}" on last run - bool delimited; - int stackToken; - - State state; - void setDone(State s); - uint pos; - void shift(uint p); - int lookupKeyword(const char *); - - bool isWhiteSpace() const; - bool isLineTerminator() const; - bool isHexDigit(ushort c) const; - bool isOctalDigit(ushort c) const; - - int matchPunctuator(ushort c1, ushort c2, - ushort c3, ushort c4); - ushort singleEscape(ushort c) const; - ushort convertOctal(ushort c1, ushort c2, - ushort c3) const; -public: - static unsigned char convertHex(ushort c1); - static unsigned char convertHex(ushort c1, ushort c2); - static QChar convertUnicode(ushort c1, ushort c2, - ushort c3, ushort c4); - static bool isIdentLetter(ushort c); - static bool isDecimalDigit(ushort c); - - inline int ival() const { return qsyylval.ival; } - inline double dval() const { return qsyylval.dval; } - inline NameId *ustr() const { return qsyylval.ustr; } - - const QChar *characterBuffer() const { return buffer16; } - int characterCount() const { return pos16; } - -private: - void record8(ushort c); - void record16(QChar c); - void recordStartPos(); - - int findReservedWord(const QChar *buffer, int size) const; - - void syncProhibitAutomaticSemicolon(); - - const QChar *code; - uint length; - int yycolumn; - int startpos; - int startlineno; - int startcolumn; - int bol; // begin of line - - union { - int ival; - double dval; - NameId *ustr; - } qsyylval; - - // current and following unicode characters - ushort current, next1, next2, next3; - - struct keyword { - const char *name; - int token; - }; - - QString errmsg; - Error err; - - bool wantRx; - bool check_reserved; - - ParenthesesState parenthesesState; - int parenthesesCount; - bool prohibitAutomaticSemicolon; -}; - -} // namespace JavaScript - -QT_END_NAMESPACE - - - -#endif diff --git a/src/declarative/qml/parser/javascriptmemorypool_p.h b/src/declarative/qml/parser/javascriptmemorypool_p.h deleted file mode 100644 index cff7677..0000000 --- a/src/declarative/qml/parser/javascriptmemorypool_p.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 JAVASCRIPTMEMORYPOOL_P_H -#define JAVASCRIPTMEMORYPOOL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace JavaScript { - -class MemoryPool : public QSharedData -{ -public: - enum { maxBlockCount = -1 }; - enum { defaultBlockSize = 1 << 12 }; - - MemoryPool() { - m_blockIndex = maxBlockCount; - m_currentIndex = 0; - m_storage = 0; - m_currentBlock = 0; - m_currentBlockSize = 0; - } - - virtual ~MemoryPool() { - for (int index = 0; index < m_blockIndex + 1; ++index) - qFree(m_storage[index]); - - qFree(m_storage); - } - - char *allocate(int bytes) { - bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment) - if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) { - ++m_blockIndex; - m_currentBlockSize = defaultBlockSize << m_blockIndex; - - m_storage = reinterpret_cast(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex))); - m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast(qMalloc(m_currentBlockSize)); - ::memset(m_currentBlock, 0, m_currentBlockSize); - - m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned - Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize); - } - - char *p = reinterpret_cast - (m_currentBlock + m_currentIndex); - - m_currentIndex += bytes; - - return p; - } - - int bytesAllocated() const { - int bytes = 0; - for (int index = 0; index < m_blockIndex; ++index) - bytes += (defaultBlockSize << index); - bytes += m_currentIndex; - return bytes; - } - -private: - int m_blockIndex; - int m_currentIndex; - char *m_currentBlock; - int m_currentBlockSize; - char **m_storage; - -private: - Q_DISABLE_COPY(MemoryPool) -}; - -} // namespace JavaScript - -QT_END_NAMESPACE - -#endif diff --git a/src/declarative/qml/parser/javascriptnodepool_p.h b/src/declarative/qml/parser/javascriptnodepool_p.h deleted file mode 100644 index cb56fbb..0000000 --- a/src/declarative/qml/parser/javascriptnodepool_p.h +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 JAVASCRIPTNODEPOOL_P_H -#define JAVASCRIPTNODEPOOL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -#include "javascriptmemorypool_p.h" - -QT_BEGIN_NAMESPACE - -namespace JavaScript { - -namespace AST { -class Node; -} // namespace AST - -class Code; -class CompilationUnit; -class Engine; - -template -inline NodeType *makeAstNode(MemoryPool *storage) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(); - return node; -} - -template -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1); - return node; -} - -template -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2); - return node; -} - -template -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3); - return node; -} - -template -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4); - return node; -} - -class NodePool : public MemoryPool -{ -public: - NodePool(const QString &fileName, Engine *engine); - virtual ~NodePool(); - - Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation); - - inline QString fileName() const { return m_fileName; } - inline Engine *engine() const { return m_engine; } -#ifndef J_SCRIPT_NO_EVENT_NOTIFY - inline qint64 id() const { return m_id; } -#endif - -private: - QHash m_codeCache; - QString m_fileName; - Engine *m_engine; -#ifndef J_SCRIPT_NO_EVENT_NOTIFY - qint64 m_id; -#endif - -private: - Q_DISABLE_COPY(NodePool) -}; - -} // namespace JavaScript - -QT_END_NAMESPACE - -#endif diff --git a/src/declarative/qml/parser/javascriptparser.cpp b/src/declarative/qml/parser/javascriptparser.cpp deleted file mode 100644 index bbffc4f..0000000 --- a/src/declarative/qml/parser/javascriptparser.cpp +++ /dev/null @@ -1,1717 +0,0 @@ -// This file was generated by qlalr - DO NOT EDIT! - -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 - -#include - -#include "javascriptengine_p.h" -#include "javascriptlexer_p.h" -#include "javascriptast_p.h" -#include "javascriptnodepool_p.h" - - - -#include "javascriptparser_p.h" -#include - -// -// This file is automatically generated from javascript.g. -// Changes will be lost. -// - -using namespace JavaScript; - -QT_BEGIN_NAMESPACE - -void Parser::reallocateStack() -{ - if (! stack_size) - stack_size = 128; - else - stack_size <<= 1; - - sym_stack = reinterpret_cast (qRealloc(sym_stack, stack_size * sizeof(Value))); - state_stack = reinterpret_cast (qRealloc(state_stack, stack_size * sizeof(int))); - location_stack = reinterpret_cast (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); -} - -inline static bool automatic(Engine *driver, int token) -{ - return token == JavaScriptGrammar::T_RBRACE - || token == 0 - || driver->lexer()->prevTerminator(); -} - - -Parser::Parser(Engine *engine): - driver(engine), - tos(0), - stack_size(0), - sym_stack(0), - state_stack(0), - location_stack(0), - first_token(0), - last_token(0) -{ -} - -Parser::~Parser() -{ - if (stack_size) { - qFree(sym_stack); - qFree(state_stack); - qFree(location_stack); - } -} - -static inline AST::SourceLocation location(Lexer *lexer) -{ - AST::SourceLocation loc; - loc.offset = lexer->tokenOffset(); - loc.length = lexer->tokenLength(); - loc.startLine = lexer->startLineNo(); - loc.startColumn = lexer->startColumnNo(); - return loc; -} - -AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) -{ - QVarLengthArray nameIds; - QVarLengthArray locations; - - AST::ExpressionNode *it = expr; - while (AST::FieldMemberExpression *m = AST::cast(it)) { - nameIds.append(m->name); - locations.append(m->identifierToken); - it = m->base; - } - - if (AST::IdentifierExpression *idExpr = AST::cast(it)) { - AST::UiQualifiedId *q = makeAstNode(driver->nodePool(), idExpr->name); - q->identifierToken = idExpr->identifierToken; - - AST::UiQualifiedId *currentId = q; - for (int i = nameIds.size() - 1; i != -1; --i) { - currentId = makeAstNode(driver->nodePool(), currentId, nameIds[i]); - currentId->identifierToken = locations[i]; - } - - return currentId->finish(); - } - - return 0; -} - -bool Parser::parse() -{ - Lexer *lexer = driver->lexer(); - bool hadErrors = false; - int yytoken = -1; - int action = 0; - - first_token = last_token = 0; - - tos = -1; - program = 0; - - do { - if (++tos == stack_size) - reallocateStack(); - - state_stack[tos] = action; - - _Lcheck_token: - if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { - yyprevlloc = yylloc; - - if (first_token == last_token) { - yytoken = lexer->lex(); - yylval = lexer->dval(); - yylloc = location(lexer); - } else { - yytoken = first_token->token; - yylval = first_token->dval; - yylloc = first_token->loc; - ++first_token; - } - } - - action = t_action(action, yytoken); - if (action > 0) { - if (action != ACCEPT_STATE) { - yytoken = -1; - sym(1).dval = yylval; - loc(1) = yylloc; - } else { - --tos; - return ! hadErrors; - } - } else if (action < 0) { - const int r = -action - 1; - tos -= rhs[r]; - - switch (r) { - -case 0: { - program = makeAstNode (driver->nodePool(), sym(1).UiImportList, - sym(2).UiObjectMemberList->finish()); - sym(1).UiProgram = program; -} break; - -case 2: { - sym(1).Node = sym(1).UiImportList->finish(); -} break; - -case 3: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiImport); -} break; - -case 4: { - sym(1).Node = makeAstNode (driver->nodePool(), - sym(1).UiImportList, sym(2).UiImport); -} break; - -case 6: { - AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).sval); - node->importToken = loc(1); - node->fileNameToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 7: { - sym(1).Node = 0; -} break; - -case 8: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); -} break; - -case 9: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); -} break; - -case 10: { - AST::UiObjectMemberList *node = makeAstNode (driver->nodePool(), - sym(1).UiObjectMemberList, sym(2).UiObjectMember); - sym(1).Node = node; -} break; - -case 11: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); -} break; - -case 12: { - AST::UiArrayMemberList *node = makeAstNode (driver->nodePool(), - sym(1).UiArrayMemberList, sym(3).UiObjectMember); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 13: { - AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), (AST::UiObjectMemberList*)0); - node->lbraceToken = loc(1); - node->rbraceToken = loc(2); - sym(1).Node = node; -} break; - -case 14: { - AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), sym(2).UiObjectMemberList->finish()); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 15: { - AST::UiObjectDefinition *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(2).UiObjectInitializer); - sym(1).Node = node; -} break; - -case 17: { - AST::UiArrayBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(4).UiArrayMemberList->finish()); - node->colonToken = loc(2); - node->lbracketToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; - -case 18: { - AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 20: { - AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 21: { - if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { - AST::UiObjectBinding *node = makeAstNode (driver->nodePool(), - sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - sym(1).Node = node; - } else { - sym(1).Node = 0; - - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2), - QLatin1String("Expected a type name after token `:'"))); - - return false; // ### recover - } -} break; -case 22:case 23:case 24:case 25:case 26:case 27: -{ - AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(3).Statement); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 28: - -case 29: { - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); - break; -} - -case 31: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); - node->type = AST::UiPublicMember::Signal; - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 33: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->semicolonToken = loc(4); - sym(1).Node = node; -} break; - -case 35: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->semicolonToken = loc(5); - sym(1).Node = node; -} break; - -case 37: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, - sym(5).Expression); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->colonToken = loc(4); - node->semicolonToken = loc(6); - sym(1).Node = node; -} break; - -case 39: { - AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, - sym(6).Expression); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->colonToken = loc(5); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; - -case 40: { - sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); -} break; - -case 41: { - sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); -} break; -case 42: -case 43: -{ - AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 45: { - QString s = QLatin1String(JavaScriptGrammar::spell[T_PROPERTY]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} - -case 46: { - QString s = QLatin1String(JavaScriptGrammar::spell[T_SIGNAL]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} - -case 47: { - AST::ThisExpression *node = makeAstNode (driver->nodePool()); - node->thisToken = loc(1); - sym(1).Node = node; -} break; - -case 48: { - AST::IdentifierExpression *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 49: { - AST::NullExpression *node = makeAstNode (driver->nodePool()); - node->nullToken = loc(1); - sym(1).Node = node; -} break; - -case 50: { - AST::TrueLiteral *node = makeAstNode (driver->nodePool()); - node->trueToken = loc(1); - sym(1).Node = node; -} break; - -case 51: { - AST::FalseLiteral *node = makeAstNode (driver->nodePool()); - node->falseToken = loc(1); - sym(1).Node = node; -} break; - -case 52: { - AST::NumericLiteral *node = makeAstNode (driver->nodePool(), sym(1).dval, lexer->flags); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 53: { - AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 54: { - bool rx = lexer->scanRegExp(Lexer::NoPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; // ### remove me - } - AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 55: { - bool rx = lexer->scanRegExp(Lexer::EqualPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; - } - AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 56: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), (AST::Elision *) 0); - node->lbracketToken = loc(1); - node->rbracketToken = loc(2); - sym(1).Node = node; -} break; - -case 57: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).Elision->finish()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; - -case 58: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish ()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; - -case 59: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), - (AST::Elision *) 0); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; - -case 60: { - AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), - sym(4).Elision->finish()); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; - -case 61: { - AST::ObjectLiteral *node = 0; - if (sym(2).Node) - node = makeAstNode (driver->nodePool(), - sym(2).PropertyNameAndValueList->finish ()); - else - node = makeAstNode (driver->nodePool()); - node->lbraceToken = loc(1); - node->lbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 62: { - AST::ObjectLiteral *node = makeAstNode (driver->nodePool(), - sym(2).PropertyNameAndValueList->finish ()); - node->lbraceToken = loc(1); - node->lbraceToken = loc(4); - sym(1).Node = node; -} break; - -case 63: { - AST::NestedExpression *node = makeAstNode(driver->nodePool(), sym(2).Expression); - node->lparenToken = loc(1); - node->rparenToken = loc(3); - sym(1).Node = node; -} break; - -case 64: { - AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 65: { - AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 66: { - sym(1).Node = makeAstNode (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); -} break; - -case 67: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); -} break; - -case 68: { - AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, - (AST::Elision *) 0, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 69: { - AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), - sym(4).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 70: { - AST::Elision *node = makeAstNode (driver->nodePool()); - node->commaToken = loc(1); - sym(1).Node = node; -} break; - -case 71: { - AST::Elision *node = makeAstNode (driver->nodePool(), sym(1).Elision); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 72: { - AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), - sym(1).PropertyName, sym(3).Expression); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 73: { - AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), - sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); - node->commaToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; - -case 74: { - AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; -case 75: -case 76: { - AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 77: { - AST::StringLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 78: { - AST::NumericLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).dval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 79: { - AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 80: - -case 81: - -case 82: - -case 83: - -case 84: - -case 85: - -case 86: - -case 87: - -case 88: - -case 89: - -case 90: - -case 91: - -case 92: - -case 93: - -case 94: - -case 95: - -case 96: - -case 97: - -case 98: - -case 99: - -case 100: - -case 101: - -case 102: - -case 103: - -case 104: - -case 105: - -case 106: - -case 107: - -case 108: - -case 109: - -case 110: -{ - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); -} break; - -case 115: { - AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; - -case 116: { - AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 117: { - AST::NewMemberExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); - node->newToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - sym(1).Node = node; -} break; - -case 119: { - AST::NewExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->newToken = loc(1); - sym(1).Node = node; -} break; - -case 120: { - AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 121: { - AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 122: { - AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; - -case 123: { - AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 124: { - sym(1).Node = 0; -} break; - -case 125: { - sym(1).Node = sym(1).ArgumentList->finish(); -} break; - -case 126: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Expression); -} break; - -case 127: { - AST::ArgumentList *node = makeAstNode (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 131: { - AST::PostIncrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->incrementToken = loc(2); - sym(1).Node = node; -} break; - -case 132: { - AST::PostDecrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->decrementToken = loc(2); - sym(1).Node = node; -} break; - -case 134: { - AST::DeleteExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->deleteToken = loc(1); - sym(1).Node = node; -} break; - -case 135: { - AST::VoidExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->voidToken = loc(1); - sym(1).Node = node; -} break; - -case 136: { - AST::TypeOfExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->typeofToken = loc(1); - sym(1).Node = node; -} break; - -case 137: { - AST::PreIncrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->incrementToken = loc(1); - sym(1).Node = node; -} break; - -case 138: { - AST::PreDecrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->decrementToken = loc(1); - sym(1).Node = node; -} break; - -case 139: { - AST::UnaryPlusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->plusToken = loc(1); - sym(1).Node = node; -} break; - -case 140: { - AST::UnaryMinusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->minusToken = loc(1); - sym(1).Node = node; -} break; - -case 141: { - AST::TildeExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->tildeToken = loc(1); - sym(1).Node = node; -} break; - -case 142: { - AST::NotExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->notToken = loc(1); - sym(1).Node = node; -} break; - -case 144: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Mul, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 145: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Div, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 146: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Mod, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 148: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Add, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 149: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Sub, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 151: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::LShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 152: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::RShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 153: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::URShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 155: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 156: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 157: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 158: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 159: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 160: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::In, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 162: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 163: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 164: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 165: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 166: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 168: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 169: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 170: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 171: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 173: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 174: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 175: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 176: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 178: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 180: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 182: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 184: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 186: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 188: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 190: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 192: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 194: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 196: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 198: { - AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; - -case 200: { - AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; - -case 202: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 204: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 205: { - sym(1).ival = QSOperator::Assign; -} break; - -case 206: { - sym(1).ival = QSOperator::InplaceMul; -} break; - -case 207: { - sym(1).ival = QSOperator::InplaceDiv; -} break; - -case 208: { - sym(1).ival = QSOperator::InplaceMod; -} break; - -case 209: { - sym(1).ival = QSOperator::InplaceAdd; -} break; - -case 210: { - sym(1).ival = QSOperator::InplaceSub; -} break; - -case 211: { - sym(1).ival = QSOperator::InplaceLeftShift; -} break; - -case 212: { - sym(1).ival = QSOperator::InplaceRightShift; -} break; - -case 213: { - sym(1).ival = QSOperator::InplaceURightShift; -} break; - -case 214: { - sym(1).ival = QSOperator::InplaceAnd; -} break; - -case 215: { - sym(1).ival = QSOperator::InplaceXor; -} break; - -case 216: { - sym(1).ival = QSOperator::InplaceOr; -} break; - -case 218: { - AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 219: { - sym(1).Node = 0; -} break; - -case 222: { - AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 223: { - sym(1).Node = 0; -} break; - -case 240: { - AST::Block *node = makeAstNode (driver->nodePool(), sym(2).StatementList); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 241: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); -} break; - -case 242: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).StatementList, sym(2).Statement); -} break; - -case 243: { - sym(1).Node = 0; -} break; - -case 244: { - sym(1).Node = sym(1).StatementList->finish (); -} break; - -case 246: { - AST::VariableStatement *node = makeAstNode (driver->nodePool(), - sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); - node->declarationKindToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 247: { - sym(1).ival = T_CONST; -} break; - -case 248: { - sym(1).ival = T_VAR; -} break; - -case 249: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); -} break; - -case 250: { - AST::VariableDeclarationList *node = makeAstNode (driver->nodePool(), - sym(1).VariableDeclarationList, sym(3).VariableDeclaration); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 251: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); -} break; - -case 252: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); -} break; - -case 253: { - AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 254: { - AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 255: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; - -case 256: { - sym(1).Node = 0; -} break; - -case 258: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; - -case 259: { - sym(1).Node = 0; -} break; - -case 261: { - AST::EmptyStatement *node = makeAstNode (driver->nodePool()); - node->semicolonToken = loc(1); - sym(1).Node = node; -} break; - -case 263: { - AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 264: { - AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - node->elseToken = loc(5); - sym(1).Node = node; -} break; - -case 265: { - AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 267: { - AST::DoWhileStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(5).Expression); - node->doToken = loc(1); - node->whileToken = loc(3); - node->lparenToken = loc(4); - node->rparenToken = loc(6); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; - -case 268: { - AST::WhileStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); - node->whileToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 269: { - AST::ForStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, - sym(5).Expression, sym(7).Expression, sym(9).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->firstSemicolonToken = loc(4); - node->secondSemicolonToken = loc(6); - node->rparenToken = loc(8); - sym(1).Node = node; -} break; - -case 270: { - AST::LocalForStatement *node = makeAstNode (driver->nodePool(), - sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, - sym(8).Expression, sym(10).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->firstSemicolonToken = loc(5); - node->secondSemicolonToken = loc(7); - node->rparenToken = loc(9); - sym(1).Node = node; -} break; - -case 271: { - AST:: ForEachStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, - sym(5).Expression, sym(7).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->inToken = loc(4); - node->rparenToken = loc(6); - sym(1).Node = node; -} break; - -case 272: { - AST::LocalForEachStatement *node = makeAstNode (driver->nodePool(), - sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->inToken = loc(5); - node->rparenToken = loc(7); - sym(1).Node = node; -} break; - -case 274: { - AST::ContinueStatement *node = makeAstNode (driver->nodePool()); - node->continueToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 276: { - AST::ContinueStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); - node->continueToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 278: { - AST::BreakStatement *node = makeAstNode (driver->nodePool()); - node->breakToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 280: { - AST::BreakStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); - node->breakToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 282: { - AST::ReturnStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->returnToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 283: { - AST::WithStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); - node->withToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 284: { - AST::SwitchStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); - node->switchToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 285: { - AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 286: { - AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(5); - sym(1).Node = node; -} break; - -case 287: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClause); -} break; - -case 288: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); -} break; - -case 289: { - sym(1).Node = 0; -} break; - -case 290: { - sym(1).Node = sym(1).CaseClauses->finish (); -} break; - -case 291: { - AST::CaseClause *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).StatementList); - node->caseToken = loc(1); - node->colonToken = loc(3); - sym(1).Node = node; -} break; - -case 292: { - AST::DefaultClause *node = makeAstNode (driver->nodePool(), sym(3).StatementList); - node->defaultToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; -case 293: -case 294: { - AST::LabelledStatement *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); - node->identifierToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 295: { - AST::LabelledStatement *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(3).Statement); - node->identifierToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 297: { - AST::ThrowStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); - node->throwToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 298: { - AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch); - node->tryToken = loc(1); - sym(1).Node = node; -} break; - -case 299: { - AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; - -case 300: { - AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; - -case 301: { - AST::Catch *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(5).Block); - node->catchToken = loc(1); - node->lparenToken = loc(2); - node->identifierToken = loc(3); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 302: { - AST::Finally *node = makeAstNode (driver->nodePool(), sym(2).Block); - node->finallyToken = loc(1); - sym(1).Node = node; -} break; - -case 304: { - AST::DebuggerStatement *node = makeAstNode (driver->nodePool()); - node->debuggerToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 305: { - AST::FunctionDeclaration *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; - -case 306: { - AST::FunctionExpression *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - if (sym(2).sval) - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; - -case 307: { - AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 308: { - AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); - node->commaToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 309: { - sym(1).Node = 0; -} break; - -case 310: { - sym(1).Node = sym(1).FormalParameterList->finish (); -} break; - -case 311: { - sym(1).Node = 0; -} break; - -case 313: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); -} break; - -case 314: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElement); -} break; - -case 315: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); -} break; - -case 316: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); -} break; - -case 317: { - sym(1).Node = makeAstNode (driver->nodePool(), sym(1).FunctionDeclaration); -} break; - -case 318: { - sym(1).sval = 0; -} break; - -case 320: { - sym(1).Node = 0; -} break; - - } // switch - action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); - } // if - } while (action != 0); - - if (first_token == last_token) { - const int errorState = state_stack[tos]; - - // automatic insertion of `;' - if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { - SavedToken &tk = token_buffer[0]; - tk.token = yytoken; - tk.dval = yylval; - tk.loc = yylloc; - - yylloc = yyprevlloc; - yylloc.offset += yylloc.length; - yylloc.startColumn += yylloc.length; - yylloc.length = 0; - - //const QString msg = QString::fromUtf8("Missing `;'"); - //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); - - first_token = &token_buffer[0]; - last_token = &token_buffer[1]; - - yytoken = T_SEMICOLON; - yylval = 0; - - action = errorState; - - goto _Lcheck_token; - } - - hadErrors = true; - - token_buffer[0].token = yytoken; - token_buffer[0].dval = yylval; - token_buffer[0].loc = yylloc; - - token_buffer[1].token = yytoken = lexer->lex(); - token_buffer[1].dval = yylval = lexer->dval(); - token_buffer[1].loc = yylloc = location(lexer); - - if (t_action(errorState, yytoken)) { - const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - action = errorState; - goto _Lcheck_token; - } - - static int tokens[] = { - T_PLUS, - T_EQ, - - T_COMMA, - T_COLON, - T_SEMICOLON, - - T_RPAREN, T_RBRACKET, T_RBRACE, - - T_NUMERIC_LITERAL, - T_IDENTIFIER, - - T_LPAREN, T_LBRACKET, T_LBRACE, - - EOF_SYMBOL - }; - - for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { - int a = t_action(errorState, *tk); - if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - yytoken = *tk; - yylval = 0; - yylloc = token_buffer[0].loc; - yylloc.length = 0; - - first_token = &token_buffer[0]; - last_token = &token_buffer[2]; - - action = errorState; - goto _Lcheck_token; - } - } - - for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { - if (tk == T_AUTOMATIC_SEMICOLON) - continue; - - int a = t_action(errorState, tk); - if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - yytoken = tk; - yylval = 0; - yylloc = token_buffer[0].loc; - yylloc.length = 0; - - action = errorState; - goto _Lcheck_token; - } - } - - const QString msg = QString::fromUtf8("Syntax error"); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - } - - return false; -} - -QT_END_NAMESPACE - - diff --git a/src/declarative/qml/parser/javascriptparser_p.h b/src/declarative/qml/parser/javascriptparser_p.h deleted file mode 100644 index b6a2432..0000000 --- a/src/declarative/qml/parser/javascriptparser_p.h +++ /dev/null @@ -1,208 +0,0 @@ -// This file was generated by qlalr - DO NOT EDIT! - -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// -// This file is automatically generated from javascript.g. -// Changes will be lost. -// - -#ifndef JAVASCRIPTPARSER_P_H -#define JAVASCRIPTPARSER_P_H - -#include "javascriptgrammar_p.h" -#include "javascriptast_p.h" -#include "javascriptengine_p.h" - -#include - -QT_BEGIN_NAMESPACE - -class QString; - -namespace JavaScript { - -class Engine; -class NameId; - -class Parser: protected JavaScriptGrammar -{ -public: - union Value { - int ival; - double dval; - NameId *sval; - AST::ArgumentList *ArgumentList; - AST::CaseBlock *CaseBlock; - AST::CaseClause *CaseClause; - AST::CaseClauses *CaseClauses; - AST::Catch *Catch; - AST::DefaultClause *DefaultClause; - AST::ElementList *ElementList; - AST::Elision *Elision; - AST::ExpressionNode *Expression; - AST::Finally *Finally; - AST::FormalParameterList *FormalParameterList; - AST::FunctionBody *FunctionBody; - AST::FunctionDeclaration *FunctionDeclaration; - AST::Node *Node; - AST::PropertyName *PropertyName; - AST::PropertyNameAndValueList *PropertyNameAndValueList; - AST::SourceElement *SourceElement; - AST::SourceElements *SourceElements; - AST::Statement *Statement; - AST::StatementList *StatementList; - AST::Block *Block; - AST::VariableDeclaration *VariableDeclaration; - AST::VariableDeclarationList *VariableDeclarationList; - - AST::UiProgram *UiProgram; - AST::UiImportList *UiImportList; - AST::UiImport *UiImport; - AST::UiPublicMember *UiPublicMember; - AST::UiObjectDefinition *UiObjectDefinition; - AST::UiObjectInitializer *UiObjectInitializer; - AST::UiObjectBinding *UiObjectBinding; - AST::UiScriptBinding *UiScriptBinding; - AST::UiArrayBinding *UiArrayBinding; - AST::UiObjectMember *UiObjectMember; - AST::UiObjectMemberList *UiObjectMemberList; - AST::UiArrayMemberList *UiArrayMemberList; - AST::UiQualifiedId *UiQualifiedId; - }; - -public: - Parser(Engine *engine); - ~Parser(); - - bool parse(); - - AST::UiProgram *ast() - { return program; } - - QList diagnosticMessages() const - { return diagnostic_messages; } - - inline DiagnosticMessage diagnosticMessage() const - { - foreach (const DiagnosticMessage &d, diagnostic_messages) { - if (! d.kind == DiagnosticMessage::Warning) - return d; - } - - return DiagnosticMessage(); - } - - inline QString errorMessage() const - { return diagnosticMessage().message; } - - inline int errorLineNumber() const - { return diagnosticMessage().loc.startLine; } - - inline int errorColumnNumber() const - { return diagnosticMessage().loc.startColumn; } - -protected: - void reallocateStack(); - - inline Value &sym(int index) - { return sym_stack [tos + index - 1]; } - - inline AST::SourceLocation &loc(int index) - { return location_stack [tos + index - 1]; } - - AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); - -protected: - Engine *driver; - int tos; - int stack_size; - Value *sym_stack; - int *state_stack; - AST::SourceLocation *location_stack; - - AST::UiProgram *program; - - // error recovery - enum { TOKEN_BUFFER_SIZE = 3 }; - - struct SavedToken { - int token; - double dval; - AST::SourceLocation loc; - }; - - double yylval; - AST::SourceLocation yylloc; - AST::SourceLocation yyprevlloc; - - SavedToken token_buffer[TOKEN_BUFFER_SIZE]; - SavedToken *first_token; - SavedToken *last_token; - - QList diagnostic_messages; -}; - -} // end of namespace JavaScript - - - -#define J_SCRIPT_REGEXPLITERAL_RULE1 54 - -#define J_SCRIPT_REGEXPLITERAL_RULE2 55 - -QT_END_NAMESPACE - - - -#endif // JAVASCRIPTPARSER_P_H diff --git a/src/declarative/qml/parser/javascriptprettypretty.cpp b/src/declarative/qml/parser/javascriptprettypretty.cpp deleted file mode 100644 index 0342b39..0000000 --- a/src/declarative/qml/parser/javascriptprettypretty.cpp +++ /dev/null @@ -1,1334 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 "javascriptprettypretty_p.h" - - - -#include "javascriptengine_p.h" - - - - -#include "javascriptast_p.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace JavaScript { -QString numberToString(double value); -} - -using namespace JavaScript; - -PrettyPretty::PrettyPretty(QTextStream &o): - out(o), m_indentLevel(0) -{ -} - -PrettyPretty::~PrettyPretty() -{ -} - -void PrettyPretty::acceptAsBlock(AST::Node *node) -{ - out << "{"; - pushIndentLevel(); - newlineAndIndent(); - accept(node); - popIndentLevel(); - newlineAndIndent(); - out << "}"; -} - -int PrettyPretty::operatorPrecedenceLevel(int op) -{ - switch (op) { - case QSOperator::Div: - case QSOperator::Mod: - case QSOperator::Mul: - return 5; - case QSOperator::Add: - case QSOperator::Sub: - return 6; - case QSOperator::LShift: - case QSOperator::RShift: - case QSOperator::URShift: - return 7; - case QSOperator::Ge: - case QSOperator::Gt: - case QSOperator::In: - case QSOperator::InstanceOf: - case QSOperator::Le: - case QSOperator::Lt: - return 8; - case QSOperator::Equal: - case QSOperator::NotEqual: - case QSOperator::StrictEqual: - case QSOperator::StrictNotEqual: - return 9; - case QSOperator::BitAnd: - return 10; - case QSOperator::BitXor: - return 11; - case QSOperator::BitOr: - return 12; - case QSOperator::And: - return 13; - case QSOperator::Or: - return 14; - case QSOperator::InplaceAnd: - case QSOperator::InplaceSub: - case QSOperator::InplaceDiv: - case QSOperator::InplaceAdd: - case QSOperator::InplaceLeftShift: - case QSOperator::InplaceMod: - case QSOperator::InplaceMul: - case QSOperator::InplaceOr: - case QSOperator::InplaceRightShift: - case QSOperator::InplaceURightShift: - case QSOperator::InplaceXor: - case QSOperator::Assign: - return 16; - default: - Q_ASSERT_X(false, "PrettyPretty::operatorPrecedenceLevel()", "bad operator"); - } - return 0; -} - -int PrettyPretty::compareOperatorPrecedence(int op1, int op2) -{ - int prec1 = operatorPrecedenceLevel(op1); - int prec2 = operatorPrecedenceLevel(op2); - if (prec1 == prec2) - return 0; - if (prec1 > prec2) - return -1; - return 1; -} - -QTextStream &PrettyPretty::operator () (AST::Node *node, int level) -{ - int was = indentLevel(level); - accept(node); - indentLevel(was); - return out; -} - -QTextStream &PrettyPretty::newlineAndIndent() -{ - enum { IND = 4 }; - out << endl << QString().fill(QLatin1Char(' '), m_indentLevel * IND); - return out; -} - -void PrettyPretty::accept(AST::Node *node) -{ - AST::Node::acceptChild(node, this); -} - -bool PrettyPretty::visit(AST::ThisExpression *node) -{ - Q_UNUSED(node); - out << "this"; - return true; -} - -void PrettyPretty::endVisit(AST::ThisExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::IdentifierExpression *node) -{ - out << Engine::toString(node->name); - return true; -} - -void PrettyPretty::endVisit(AST::IdentifierExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NullExpression *node) -{ - Q_UNUSED(node); - out << "null"; - return false; -} - -void PrettyPretty::endVisit(AST::NullExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TrueLiteral *node) -{ - Q_UNUSED(node); - out << "true"; - return false; -} - -void PrettyPretty::endVisit(AST::TrueLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FalseLiteral *node) -{ - Q_UNUSED(node); - out << "false"; - return false; -} - -void PrettyPretty::endVisit(AST::FalseLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StringLiteral *node) -{ - QString lit = Engine::toString(node->value); - lit.replace(QLatin1String("\\"), QLatin1String("\\\\")); - out << "\"" << lit << "\""; - return false; -} - -void PrettyPretty::endVisit(AST::StringLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NumericLiteral *node) -{ - out << JavaScript::numberToString(node->value); - return true; -} - -void PrettyPretty::endVisit(AST::NumericLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::RegExpLiteral *node) -{ - out << "/" << Engine::toString(node->pattern) << "/"; - if (node->flags) - out << JavaScript::Ecma::RegExp::flagsToString(node->flags); - - return true; -} - -void PrettyPretty::endVisit(AST::RegExpLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ArrayLiteral *node) -{ - out << "["; - accept(node->elements); - accept(node->elision); - out << "]"; - return false; -} - -void PrettyPretty::endVisit(AST::ArrayLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ObjectLiteral *node) -{ - out << "{"; - if (node->properties) { - pushIndentLevel(); - AST::PropertyNameAndValueList *prop; - for (prop = node->properties; prop != 0; prop = prop->next) { - newlineAndIndent(); - accept(prop); - if (prop->next) - out << ","; - } - popIndentLevel(); - newlineAndIndent(); - } - out << "}"; - return false; -} - -void PrettyPretty::endVisit(AST::ObjectLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ElementList *node) -{ - accept(node->elision); - accept(node->expression); - for (node = node->next; node != 0; node = node->next) { - out << ", "; - accept(node->elision); - accept(node->expression); - } - return false; -} - -void PrettyPretty::endVisit(AST::ElementList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Elision *node) -{ - out << ", "; - for (AST::Elision *eit = node->next; eit != 0; eit = eit->next) - out << ", "; - return false; -} - -void PrettyPretty::endVisit(AST::Elision *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PropertyNameAndValueList *node) -{ - accept(node->name); - out << ": "; - accept(node->value); - return false; -} - -void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::IdentifierPropertyName *node) -{ - out << Engine::toString(node->id); - return false; -} - -void PrettyPretty::endVisit(AST::IdentifierPropertyName *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StringLiteralPropertyName *node) -{ - QString lit = Engine::toString(node->id); - lit.replace(QLatin1String("\\"), QLatin1String("\\\\")); - out << lit; - return false; -} - -void PrettyPretty::endVisit(AST::StringLiteralPropertyName *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node) -{ - out << node->id; - return false; -} - -void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ArrayMemberExpression *node) -{ - accept(node->base); - out << "["; - accept(node->expression); - out << "]"; - return false; -} - -void PrettyPretty::endVisit(AST::ArrayMemberExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FieldMemberExpression *node) -{ - accept(node->base); - out << "." << Engine::toString(node->name); - return false; -} - -void PrettyPretty::endVisit(AST::FieldMemberExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NewMemberExpression *node) -{ - out << "new "; - accept(node->base); - out << "("; - accept(node->arguments); - out << ")"; - return false; -} - -void PrettyPretty::endVisit(AST::NewMemberExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NewExpression *node) -{ - Q_UNUSED(node); - out << "new "; - return true; -} - -void PrettyPretty::endVisit(AST::NewExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CallExpression *node) -{ - accept(node->base); - out << "("; - accept(node->arguments); - out << ")"; - return false; -} - -void PrettyPretty::endVisit(AST::CallExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ArgumentList *node) -{ - accept(node->expression); - for (node = node->next; node != 0; node = node->next) { - out << ", "; - accept(node->expression); - } - return false; -} - -void PrettyPretty::endVisit(AST::ArgumentList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PostIncrementExpression *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::PostIncrementExpression *node) -{ - Q_UNUSED(node); - out << "++"; -} - -bool PrettyPretty::visit(AST::PostDecrementExpression *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::PostDecrementExpression *node) -{ - Q_UNUSED(node); - out << "--"; -} - -bool PrettyPretty::visit(AST::DeleteExpression *node) -{ - Q_UNUSED(node); - out << "delete "; - return true; -} - -void PrettyPretty::endVisit(AST::DeleteExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::VoidExpression *node) -{ - Q_UNUSED(node); - out << "void "; - return true; -} - -void PrettyPretty::endVisit(AST::VoidExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TypeOfExpression *node) -{ - Q_UNUSED(node); - out << "typeof "; - return true; -} - -void PrettyPretty::endVisit(AST::TypeOfExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PreIncrementExpression *node) -{ - Q_UNUSED(node); - out << "++"; - return true; -} - -void PrettyPretty::endVisit(AST::PreIncrementExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PreDecrementExpression *node) -{ - Q_UNUSED(node); - out << "--"; - return true; -} - -void PrettyPretty::endVisit(AST::PreDecrementExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::UnaryPlusExpression *node) -{ - out << "+"; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << "("; - accept(node->expression); - if (needParens) - out << ")"; - return false; -} - -void PrettyPretty::endVisit(AST::UnaryPlusExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::UnaryMinusExpression *node) -{ - out << "-"; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << "("; - accept(node->expression); - if (needParens) - out << ")"; - return false; -} - -void PrettyPretty::endVisit(AST::UnaryMinusExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TildeExpression *node) -{ - out << "~"; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << "("; - accept(node->expression); - if (needParens) - out << ")"; - return false; -} - -void PrettyPretty::endVisit(AST::TildeExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NotExpression *node) -{ - out << "!"; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << "("; - accept(node->expression); - if (needParens) - out << ")"; - return false; -} - -void PrettyPretty::endVisit(AST::NotExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::BinaryExpression *node) -{ - bool needParens = node->left->binaryExpressionCast() - && (compareOperatorPrecedence(node->left->binaryExpressionCast()->op, node->op) < 0); - if (needParens) - out << "("; - accept(node->left); - if (needParens) - out << ")"; - QString s; - switch (node->op) { - case QSOperator::Add: - s = QLatin1String("+"); break; - case QSOperator::And: - s = QLatin1String("&&"); break; - case QSOperator::InplaceAnd: - s = QLatin1String("&="); break; - case QSOperator::Assign: - s = QLatin1String("="); break; - case QSOperator::BitAnd: - s = QLatin1String("&"); break; - case QSOperator::BitOr: - s = QLatin1String("|"); break; - case QSOperator::BitXor: - s = QLatin1String("^"); break; - case QSOperator::InplaceSub: - s = QLatin1String("-="); break; - case QSOperator::Div: - s = QLatin1String("/"); break; - case QSOperator::InplaceDiv: - s = QLatin1String("/="); break; - case QSOperator::Equal: - s = QLatin1String("=="); break; - case QSOperator::Ge: - s = QLatin1String(">="); break; - case QSOperator::Gt: - s = QLatin1String(">"); break; - case QSOperator::In: - s = QLatin1String("in"); break; - case QSOperator::InplaceAdd: - s = QLatin1String("+="); break; - case QSOperator::InstanceOf: - s = QLatin1String("instanceof"); break; - case QSOperator::Le: - s = QLatin1String("<="); break; - case QSOperator::LShift: - s = QLatin1String("<<"); break; - case QSOperator::InplaceLeftShift: - s = QLatin1String("<<="); break; - case QSOperator::Lt: - s = QLatin1String("<"); break; - case QSOperator::Mod: - s = QLatin1String("%"); break; - case QSOperator::InplaceMod: - s = QLatin1String("%="); break; - case QSOperator::Mul: - s = QLatin1String("*"); break; - case QSOperator::InplaceMul: - s = QLatin1String("*="); break; - case QSOperator::NotEqual: - s = QLatin1String("!="); break; - case QSOperator::Or: - s = QLatin1String("||"); break; - case QSOperator::InplaceOr: - s = QLatin1String("|="); break; - case QSOperator::RShift: - s = QLatin1String(">>"); break; - case QSOperator::InplaceRightShift: - s = QLatin1String(">>="); break; - case QSOperator::StrictEqual: - s = QLatin1String("==="); break; - case QSOperator::StrictNotEqual: - s = QLatin1String("!=="); break; - case QSOperator::Sub: - s = QLatin1String("-"); break; - case QSOperator::URShift: - s = QLatin1String(">>>"); break; - case QSOperator::InplaceURightShift: - s = QLatin1String(">>>="); break; - case QSOperator::InplaceXor: - s = QLatin1String("^="); break; - default: - Q_ASSERT (0); - } - out << " " << s << " "; - needParens = node->right->binaryExpressionCast() - && (compareOperatorPrecedence(node->right->binaryExpressionCast()->op, node->op) <= 0); - if (needParens) - out << "("; - accept(node->right); - if (needParens) - out << ")"; - return false; -} - -void PrettyPretty::endVisit(AST::BinaryExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ConditionalExpression *node) -{ - accept(node->expression); - out << " ? "; - accept(node->ok); - out << " : "; - accept(node->ko); - return false; -} - -void PrettyPretty::endVisit(AST::ConditionalExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Expression *node) -{ - accept(node->left); - out << ", "; - accept(node->right); - return false; -} - -void PrettyPretty::endVisit(AST::Expression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Block *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::Block *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StatementList *node) -{ - accept(node->statement); - for (node = node->next; node != 0; node = node->next) { - newlineAndIndent(); - accept(node->statement); - } - return false; -} - -void PrettyPretty::endVisit(AST::StatementList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::VariableDeclarationList *node) -{ - AST::VariableDeclarationList *it = node; - - do { - it->declaration->accept(this); - it = it->next; - if (it) - out << ", "; - } while (it); - - return false; -} - -void PrettyPretty::endVisit(AST::VariableDeclarationList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::VariableStatement *node) -{ - out << "var "; - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::VariableStatement *node) -{ - Q_UNUSED(node); - out << ";"; -} - -bool PrettyPretty::visit(AST::VariableDeclaration *node) -{ - out << Engine::toString(node->name); - if (node->expression) { - out << " = "; - accept(node->expression); - } - return false; -} - -void PrettyPretty::endVisit(AST::VariableDeclaration *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::EmptyStatement *node) -{ - Q_UNUSED(node); - out << ";"; - return true; -} - -void PrettyPretty::endVisit(AST::EmptyStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ExpressionStatement *node) -{ - accept(node->expression); - out << ";"; - return false; -} - -void PrettyPretty::endVisit(AST::ExpressionStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::IfStatement *node) -{ - out << "if ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->ok); - if (node->ko) { - out << " else "; - acceptAsBlock(node->ko); - } - return false; -} - -void PrettyPretty::endVisit(AST::IfStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::DoWhileStatement *node) -{ - out << "do "; - acceptAsBlock(node->statement); - out << " while ("; - accept(node->expression); - out << ");"; - return false; -} - -void PrettyPretty::endVisit(AST::DoWhileStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::WhileStatement *node) -{ - out << "while ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::WhileStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ForStatement *node) -{ - out << "for ("; - accept(node->initialiser); - out << "; "; - accept(node->condition); - out << "; "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::ForStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::LocalForStatement *node) -{ - out << "for (var "; - accept(node->declarations); - out << "; "; - accept(node->condition); - out << "; "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::LocalForStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ForEachStatement *node) -{ - out << "for ("; - accept(node->initialiser); - out << " in "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::ForEachStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::LocalForEachStatement *node) -{ - out << "for (var "; - accept(node->declaration); - out << " in "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::LocalForEachStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ContinueStatement *node) -{ - out << "continue"; - if (node->label) { - out << " " << Engine::toString(node->label); - } - out << ";"; - return false; -} - -void PrettyPretty::endVisit(AST::ContinueStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::BreakStatement *node) -{ - out << "break"; - if (node->label) { - out << " " << Engine::toString(node->label); - } - out << ";"; - return false; -} - -void PrettyPretty::endVisit(AST::BreakStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ReturnStatement *node) -{ - out << "return"; - if (node->expression) { - out << " "; - accept(node->expression); - } - out << ";"; - return false; -} - -void PrettyPretty::endVisit(AST::ReturnStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::WithStatement *node) -{ - out << "with ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::WithStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::SwitchStatement *node) -{ - out << "switch ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->block); - return false; -} - -void PrettyPretty::endVisit(AST::SwitchStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CaseBlock *node) -{ - accept(node->clauses); - if (node->defaultClause) { - newlineAndIndent(); - accept(node->defaultClause); - } - if (node->moreClauses) { - newlineAndIndent(); - accept(node->moreClauses); - } - return false; -} - -void PrettyPretty::endVisit(AST::CaseBlock *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CaseClauses *node) -{ - accept(node->clause); - for (node = node->next; node != 0; node = node->next) { - newlineAndIndent(); - accept(node->clause); - } - return false; -} - -void PrettyPretty::endVisit(AST::CaseClauses *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CaseClause *node) -{ - out << "case "; - accept(node->expression); - out << ":"; - if (node->statements) { - newlineAndIndent(); - accept(node->statements); - } - return false; -} - -void PrettyPretty::endVisit(AST::CaseClause *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::DefaultClause *node) -{ - Q_UNUSED(node); - out << "default:"; - newlineAndIndent(); - return true; -} - -void PrettyPretty::endVisit(AST::DefaultClause *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::LabelledStatement *node) -{ - out << Engine::toString(node->label) << ": "; - return true; -} - -void PrettyPretty::endVisit(AST::LabelledStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ThrowStatement *node) -{ - Q_UNUSED(node); - out << "throw "; - accept(node->expression); - out << ";"; - return false; -} - -void PrettyPretty::endVisit(AST::ThrowStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TryStatement *node) -{ - out << "try "; - acceptAsBlock(node->statement); - if (node->catchExpression) { - out << " catch (" << Engine::toString(node->catchExpression->name) << ") "; - acceptAsBlock(node->catchExpression->statement); - } - if (node->finallyExpression) { - out << " finally "; - acceptAsBlock(node->finallyExpression->statement); - } - return false; -} - -void PrettyPretty::endVisit(AST::TryStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Catch *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::Catch *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Finally *node) -{ - Q_UNUSED(node); - out << "finally "; - return true; -} - -void PrettyPretty::endVisit(AST::Finally *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionDeclaration *node) -{ - out << "function"; - - if (node->name) - out << " " << Engine::toString(node->name); - - // the arguments - out << "("; - for (AST::FormalParameterList *it = node->formals; it; it = it->next) { - if (it->name) - out << Engine::toString(it->name); - - if (it->next) - out << ", "; - } - out << ")"; - - // the function body - out << " {"; - - if (node->body) { - pushIndentLevel(); - newlineAndIndent(); - accept(node->body); - popIndentLevel(); - newlineAndIndent(); - } - - out << "}"; - - return false; -} - -void PrettyPretty::endVisit(AST::FunctionDeclaration *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionExpression *node) -{ - out << "function"; - - if (node->name) - out << " " << Engine::toString(node->name); - - // the arguments - out << "("; - for (AST::FormalParameterList *it = node->formals; it; it = it->next) { - if (it->name) - out << Engine::toString(it->name); - - if (it->next) - out << ", "; - } - out << ")"; - - // the function body - out << " {"; - - if (node->body) { - pushIndentLevel(); - newlineAndIndent(); - accept(node->body); - popIndentLevel(); - newlineAndIndent(); - } - - out << "}"; - - return false; -} - -void PrettyPretty::endVisit(AST::FunctionExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FormalParameterList *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::FormalParameterList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionBody *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::FunctionBody *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Program *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::Program *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::SourceElements *node) -{ - Q_UNUSED(node); - accept(node->element); - for (node = node->next; node != 0; node = node->next) { - newlineAndIndent(); - accept(node->element); - } - return false; -} - -void PrettyPretty::endVisit(AST::SourceElements *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionSourceElement *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::FunctionSourceElement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StatementSourceElement *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::StatementSourceElement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::DebuggerStatement *node) -{ - Q_UNUSED(node); - out << "debugger"; - return true; -} - -void PrettyPretty::endVisit(AST::DebuggerStatement *node) -{ - Q_UNUSED(node); - out << ";"; -} - -bool PrettyPretty::preVisit(AST::Node *node) -{ - Q_UNUSED(node); - return true; -} - -QT_END_NAMESPACE - - diff --git a/src/declarative/qml/parser/javascriptprettypretty_p.h b/src/declarative/qml/parser/javascriptprettypretty_p.h deleted file mode 100644 index c692da5..0000000 --- a/src/declarative/qml/parser/javascriptprettypretty_p.h +++ /dev/null @@ -1,329 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtScript module 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 JAVASCRIPTPRETTYPRETTY_P_H -#define JAVASCRIPTPRETTYPRETTY_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#include "javascriptastvisitor_p.h" - -QT_BEGIN_NAMESPACE - -class QTextStream; - -namespace JavaScript { - -class PrettyPretty: protected AST::Visitor -{ -public: - PrettyPretty(QTextStream &out); - virtual ~PrettyPretty(); - - QTextStream &operator () (AST::Node *node, int level = 0); - -protected: - void accept(AST::Node *node); - - virtual bool preVisit(AST::Node *node); - - virtual bool visit(AST::ThisExpression *node); - virtual void endVisit(AST::ThisExpression *node); - - virtual bool visit(AST::IdentifierExpression *node); - virtual void endVisit(AST::IdentifierExpression *node); - - virtual bool visit(AST::NullExpression *node); - virtual void endVisit(AST::NullExpression *node); - - virtual bool visit(AST::TrueLiteral *node); - virtual void endVisit(AST::TrueLiteral *node); - - virtual bool visit(AST::FalseLiteral *node); - virtual void endVisit(AST::FalseLiteral *node); - - virtual bool visit(AST::StringLiteral *node); - virtual void endVisit(AST::StringLiteral *node); - - virtual bool visit(AST::NumericLiteral *node); - virtual void endVisit(AST::NumericLiteral *node); - - virtual bool visit(AST::RegExpLiteral *node); - virtual void endVisit(AST::RegExpLiteral *node); - - virtual bool visit(AST::ArrayLiteral *node); - virtual void endVisit(AST::ArrayLiteral *node); - - virtual bool visit(AST::ObjectLiteral *node); - virtual void endVisit(AST::ObjectLiteral *node); - - virtual bool visit(AST::ElementList *node); - virtual void endVisit(AST::ElementList *node); - - virtual bool visit(AST::Elision *node); - virtual void endVisit(AST::Elision *node); - - virtual bool visit(AST::PropertyNameAndValueList *node); - virtual void endVisit(AST::PropertyNameAndValueList *node); - - virtual bool visit(AST::IdentifierPropertyName *node); - virtual void endVisit(AST::IdentifierPropertyName *node); - - virtual bool visit(AST::StringLiteralPropertyName *node); - virtual void endVisit(AST::StringLiteralPropertyName *node); - - virtual bool visit(AST::NumericLiteralPropertyName *node); - virtual void endVisit(AST::NumericLiteralPropertyName *node); - - virtual bool visit(AST::ArrayMemberExpression *node); - virtual void endVisit(AST::ArrayMemberExpression *node); - - virtual bool visit(AST::FieldMemberExpression *node); - virtual void endVisit(AST::FieldMemberExpression *node); - - virtual bool visit(AST::NewMemberExpression *node); - virtual void endVisit(AST::NewMemberExpression *node); - - virtual bool visit(AST::NewExpression *node); - virtual void endVisit(AST::NewExpression *node); - - virtual bool visit(AST::CallExpression *node); - virtual void endVisit(AST::CallExpression *node); - - virtual bool visit(AST::ArgumentList *node); - virtual void endVisit(AST::ArgumentList *node); - - virtual bool visit(AST::PostIncrementExpression *node); - virtual void endVisit(AST::PostIncrementExpression *node); - - virtual bool visit(AST::PostDecrementExpression *node); - virtual void endVisit(AST::PostDecrementExpression *node); - - virtual bool visit(AST::DeleteExpression *node); - virtual void endVisit(AST::DeleteExpression *node); - - virtual bool visit(AST::VoidExpression *node); - virtual void endVisit(AST::VoidExpression *node); - - virtual bool visit(AST::TypeOfExpression *node); - virtual void endVisit(AST::TypeOfExpression *node); - - virtual bool visit(AST::PreIncrementExpression *node); - virtual void endVisit(AST::PreIncrementExpression *node); - - virtual bool visit(AST::PreDecrementExpression *node); - virtual void endVisit(AST::PreDecrementExpression *node); - - virtual bool visit(AST::UnaryPlusExpression *node); - virtual void endVisit(AST::UnaryPlusExpression *node); - - virtual bool visit(AST::UnaryMinusExpression *node); - virtual void endVisit(AST::UnaryMinusExpression *node); - - virtual bool visit(AST::TildeExpression *node); - virtual void endVisit(AST::TildeExpression *node); - - virtual bool visit(AST::NotExpression *node); - virtual void endVisit(AST::NotExpression *node); - - virtual bool visit(AST::BinaryExpression *node); - virtual void endVisit(AST::BinaryExpression *node); - - virtual bool visit(AST::ConditionalExpression *node); - virtual void endVisit(AST::ConditionalExpression *node); - - virtual bool visit(AST::Expression *node); - virtual void endVisit(AST::Expression *node); - - virtual bool visit(AST::Block *node); - virtual void endVisit(AST::Block *node); - - virtual bool visit(AST::StatementList *node); - virtual void endVisit(AST::StatementList *node); - - virtual bool visit(AST::VariableStatement *node); - virtual void endVisit(AST::VariableStatement *node); - - virtual bool visit(AST::VariableDeclarationList *node); - virtual void endVisit(AST::VariableDeclarationList *node); - - virtual bool visit(AST::VariableDeclaration *node); - virtual void endVisit(AST::VariableDeclaration *node); - - virtual bool visit(AST::EmptyStatement *node); - virtual void endVisit(AST::EmptyStatement *node); - - virtual bool visit(AST::ExpressionStatement *node); - virtual void endVisit(AST::ExpressionStatement *node); - - virtual bool visit(AST::IfStatement *node); - virtual void endVisit(AST::IfStatement *node); - - virtual bool visit(AST::DoWhileStatement *node); - virtual void endVisit(AST::DoWhileStatement *node); - - virtual bool visit(AST::WhileStatement *node); - virtual void endVisit(AST::WhileStatement *node); - - virtual bool visit(AST::ForStatement *node); - virtual void endVisit(AST::ForStatement *node); - - virtual bool visit(AST::LocalForStatement *node); - virtual void endVisit(AST::LocalForStatement *node); - - virtual bool visit(AST::ForEachStatement *node); - virtual void endVisit(AST::ForEachStatement *node); - - virtual bool visit(AST::LocalForEachStatement *node); - virtual void endVisit(AST::LocalForEachStatement *node); - - virtual bool visit(AST::ContinueStatement *node); - virtual void endVisit(AST::ContinueStatement *node); - - virtual bool visit(AST::BreakStatement *node); - virtual void endVisit(AST::BreakStatement *node); - - virtual bool visit(AST::ReturnStatement *node); - virtual void endVisit(AST::ReturnStatement *node); - - virtual bool visit(AST::WithStatement *node); - virtual void endVisit(AST::WithStatement *node); - - virtual bool visit(AST::SwitchStatement *node); - virtual void endVisit(AST::SwitchStatement *node); - - virtual bool visit(AST::CaseBlock *node); - virtual void endVisit(AST::CaseBlock *node); - - virtual bool visit(AST::CaseClauses *node); - virtual void endVisit(AST::CaseClauses *node); - - virtual bool visit(AST::CaseClause *node); - virtual void endVisit(AST::CaseClause *node); - - virtual bool visit(AST::DefaultClause *node); - virtual void endVisit(AST::DefaultClause *node); - - virtual bool visit(AST::LabelledStatement *node); - virtual void endVisit(AST::LabelledStatement *node); - - virtual bool visit(AST::ThrowStatement *node); - virtual void endVisit(AST::ThrowStatement *node); - - virtual bool visit(AST::TryStatement *node); - virtual void endVisit(AST::TryStatement *node); - - virtual bool visit(AST::Catch *node); - virtual void endVisit(AST::Catch *node); - - virtual bool visit(AST::Finally *node); - virtual void endVisit(AST::Finally *node); - - virtual bool visit(AST::FunctionDeclaration *node); - virtual void endVisit(AST::FunctionDeclaration *node); - - virtual bool visit(AST::FunctionExpression *node); - virtual void endVisit(AST::FunctionExpression *node); - - virtual bool visit(AST::FormalParameterList *node); - virtual void endVisit(AST::FormalParameterList *node); - - virtual bool visit(AST::FunctionBody *node); - virtual void endVisit(AST::FunctionBody *node); - - virtual bool visit(AST::Program *node); - virtual void endVisit(AST::Program *node); - - virtual bool visit(AST::SourceElements *node); - virtual void endVisit(AST::SourceElements *node); - - virtual bool visit(AST::FunctionSourceElement *node); - virtual void endVisit(AST::FunctionSourceElement *node); - - virtual bool visit(AST::StatementSourceElement *node); - virtual void endVisit(AST::StatementSourceElement *node); - - virtual bool visit(AST::DebuggerStatement *node); - virtual void endVisit(AST::DebuggerStatement *node); - - int indentLevel(int level) - { - int was = m_indentLevel; - m_indentLevel = level; - return was; - } - - void pushIndentLevel() - { ++m_indentLevel; } - - void popIndentLevel() - { --m_indentLevel; } - - QTextStream &newlineAndIndent(); - - void acceptAsBlock(AST::Node *node); - - static int operatorPrecedenceLevel(int op); - static int compareOperatorPrecedence(int op1, int op2); - -private: - QTextStream &out; - int m_indentLevel; - - Q_DISABLE_COPY(PrettyPretty) -}; - -} // namespace JavaScript - -QT_END_NAMESPACE - -#endif diff --git a/src/declarative/qml/parser/parser.pri b/src/declarative/qml/parser/parser.pri index 72bd46c..610b2aa 100644 --- a/src/declarative/qml/parser/parser.pri +++ b/src/declarative/qml/parser/parser.pri @@ -1,22 +1,22 @@ INCLUDEPATH += $$PWD -HEADERS += $$PWD/javascriptast_p.h \ - $$PWD/javascriptastfwd_p.h \ - $$PWD/javascriptastvisitor_p.h \ - $$PWD/javascriptengine_p.h \ - $$PWD/javascriptgrammar_p.h \ - $$PWD/javascriptlexer_p.h \ - $$PWD/javascriptmemorypool_p.h \ - $$PWD/javascriptnodepool_p.h \ - $$PWD/javascriptparser_p.h \ - $$PWD/javascriptprettypretty_p.h +HEADERS += $$PWD/qmljsast_p.h \ + $$PWD/qmljsastfwd_p.h \ + $$PWD/qmljsastvisitor_p.h \ + $$PWD/qmljsengine_p.h \ + $$PWD/qmljsgrammar_p.h \ + $$PWD/qmljslexer_p.h \ + $$PWD/qmljsmemorypool_p.h \ + $$PWD/qmljsnodepool_p.h \ + $$PWD/qmljsparser_p.h \ + $$PWD/qmljsprettypretty_p.h -SOURCES += $$PWD/javascriptast.cpp \ - $$PWD/javascriptastvisitor.cpp \ - $$PWD/javascriptengine_p.cpp \ - $$PWD/javascriptgrammar.cpp \ - $$PWD/javascriptlexer.cpp \ - $$PWD/javascriptprettypretty.cpp \ - $$PWD/javascriptparser.cpp +SOURCES += $$PWD/qmljsast.cpp \ + $$PWD/qmljsastvisitor.cpp \ + $$PWD/qmljsengine_p.cpp \ + $$PWD/qmljsgrammar.cpp \ + $$PWD/qmljslexer.cpp \ + $$PWD/qmljsprettypretty.cpp \ + $$PWD/qmljsparser.cpp diff --git a/src/declarative/qml/parser/qmljs.g b/src/declarative/qml/parser/qmljs.g new file mode 100644 index 0000000..907ca52 --- /dev/null +++ b/src/declarative/qml/parser/qmljs.g @@ -0,0 +1,2881 @@ +---------------------------------------------------------------------------- +-- +-- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +-- Contact: Qt Software Information (qt-info@nokia.com) +-- +-- This file is part of the QtScript module 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$ +-- +-- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +-- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +-- +---------------------------------------------------------------------------- + +%parser QmlJSGrammar +%decl qmljsparser_p.h +%impl qmljsparser.cpp +%expect 2 +%expect-rr 3 + +%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" +%token T_BREAK "break" T_CASE "case" T_CATCH "catch" +%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue" +%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/" +%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "." +%token T_ELSE "else" T_EQ "=" T_EQ_EQ "==" +%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for" +%token T_FUNCTION "function" T_GE ">=" T_GT ">" +%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>" +%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if" +%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{" +%token T_LBRACKET "[" T_LE "<=" T_LPAREN "(" +%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<=" +%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--" +%token T_NEW "new" T_NOT "!" T_NOT_EQ "!=" +%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|" +%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+" +%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?" +%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%" +%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")" +%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*" +%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal" +%token T_PROPERTY "property" T_SIGNAL "signal" +%token T_SWITCH "switch" T_THIS "this" T_THROW "throw" +%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof" +%token T_VAR "var" T_VOID "void" T_WHILE "while" +%token T_WITH "with" T_XOR "^" T_XOR_EQ "^=" +%token T_NULL "null" T_TRUE "true" T_FALSE "false" +%token T_CONST "const" +%token T_DEBUGGER "debugger" +%token T_RESERVED_WORD "reserved word" +%token T_MULTILINE_STRING_LITERAL "multiline string literal" + +--- context keywords. +%token T_PUBLIC "public" +%token T_IMPORT "import" + +%nonassoc SHIFT_THERE +%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY +%nonassoc REDUCE_HERE + +%start UiProgram + +/. +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 + +#include + +#include "qmljsengine_p.h" +#include "qmljslexer_p.h" +#include "qmljsast_p.h" +#include "qmljsnodepool_p.h" + +./ + +/: +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +#ifndef QMLJSPARSER_P_H +#define QMLJSPARSER_P_H + +#include "qmljsgrammar_p.h" +#include "qmljsast_p.h" +#include "qmljsengine_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QString; + +namespace QmlJS { + +class Engine; +class NameId; + +class Parser: protected $table +{ +public: + union Value { + int ival; + double dval; + NameId *sval; + AST::ArgumentList *ArgumentList; + AST::CaseBlock *CaseBlock; + AST::CaseClause *CaseClause; + AST::CaseClauses *CaseClauses; + AST::Catch *Catch; + AST::DefaultClause *DefaultClause; + AST::ElementList *ElementList; + AST::Elision *Elision; + AST::ExpressionNode *Expression; + AST::Finally *Finally; + AST::FormalParameterList *FormalParameterList; + AST::FunctionBody *FunctionBody; + AST::FunctionDeclaration *FunctionDeclaration; + AST::Node *Node; + AST::PropertyName *PropertyName; + AST::PropertyNameAndValueList *PropertyNameAndValueList; + AST::SourceElement *SourceElement; + AST::SourceElements *SourceElements; + AST::Statement *Statement; + AST::StatementList *StatementList; + AST::Block *Block; + AST::VariableDeclaration *VariableDeclaration; + AST::VariableDeclarationList *VariableDeclarationList; + + AST::UiProgram *UiProgram; + AST::UiImportList *UiImportList; + AST::UiImport *UiImport; + AST::UiPublicMember *UiPublicMember; + AST::UiObjectDefinition *UiObjectDefinition; + AST::UiObjectInitializer *UiObjectInitializer; + AST::UiObjectBinding *UiObjectBinding; + AST::UiScriptBinding *UiScriptBinding; + AST::UiArrayBinding *UiArrayBinding; + AST::UiObjectMember *UiObjectMember; + AST::UiObjectMemberList *UiObjectMemberList; + AST::UiArrayMemberList *UiArrayMemberList; + AST::UiQualifiedId *UiQualifiedId; + }; + +public: + Parser(Engine *engine); + ~Parser(); + + bool parse(); + + AST::UiProgram *ast() + { return program; } + + QList diagnosticMessages() const + { return diagnostic_messages; } + + inline DiagnosticMessage diagnosticMessage() const + { + foreach (const DiagnosticMessage &d, diagnostic_messages) { + if (! d.kind == DiagnosticMessage::Warning) + return d; + } + + return DiagnosticMessage(); + } + + inline QString errorMessage() const + { return diagnosticMessage().message; } + + inline int errorLineNumber() const + { return diagnosticMessage().loc.startLine; } + + inline int errorColumnNumber() const + { return diagnosticMessage().loc.startColumn; } + +protected: + void reallocateStack(); + + inline Value &sym(int index) + { return sym_stack [tos + index - 1]; } + + inline AST::SourceLocation &loc(int index) + { return location_stack [tos + index - 1]; } + + AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); + +protected: + Engine *driver; + int tos; + int stack_size; + Value *sym_stack; + int *state_stack; + AST::SourceLocation *location_stack; + + AST::UiProgram *program; + + // error recovery + enum { TOKEN_BUFFER_SIZE = 3 }; + + struct SavedToken { + int token; + double dval; + AST::SourceLocation loc; + }; + + double yylval; + AST::SourceLocation yylloc; + AST::SourceLocation yyprevlloc; + + SavedToken token_buffer[TOKEN_BUFFER_SIZE]; + SavedToken *first_token; + SavedToken *last_token; + + QList diagnostic_messages; +}; + +} // end of namespace QmlJS + + +:/ + + +/. + +#include "qmljsparser_p.h" +#include + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +using namespace QmlJS; + +QT_BEGIN_NAMESPACE + +void Parser::reallocateStack() +{ + if (! stack_size) + stack_size = 128; + else + stack_size <<= 1; + + sym_stack = reinterpret_cast (qRealloc(sym_stack, stack_size * sizeof(Value))); + state_stack = reinterpret_cast (qRealloc(state_stack, stack_size * sizeof(int))); + location_stack = reinterpret_cast (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); +} + +inline static bool automatic(Engine *driver, int token) +{ + return token == $table::T_RBRACE + || token == 0 + || driver->lexer()->prevTerminator(); +} + + +Parser::Parser(Engine *engine): + driver(engine), + tos(0), + stack_size(0), + sym_stack(0), + state_stack(0), + location_stack(0), + first_token(0), + last_token(0) +{ +} + +Parser::~Parser() +{ + if (stack_size) { + qFree(sym_stack); + qFree(state_stack); + qFree(location_stack); + } +} + +static inline AST::SourceLocation location(Lexer *lexer) +{ + AST::SourceLocation loc; + loc.offset = lexer->tokenOffset(); + loc.length = lexer->tokenLength(); + loc.startLine = lexer->startLineNo(); + loc.startColumn = lexer->startColumnNo(); + return loc; +} + +AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) +{ + QVarLengthArray nameIds; + QVarLengthArray locations; + + AST::ExpressionNode *it = expr; + while (AST::FieldMemberExpression *m = AST::cast(it)) { + nameIds.append(m->name); + locations.append(m->identifierToken); + it = m->base; + } + + if (AST::IdentifierExpression *idExpr = AST::cast(it)) { + AST::UiQualifiedId *q = makeAstNode(driver->nodePool(), idExpr->name); + q->identifierToken = idExpr->identifierToken; + + AST::UiQualifiedId *currentId = q; + for (int i = nameIds.size() - 1; i != -1; --i) { + currentId = makeAstNode(driver->nodePool(), currentId, nameIds[i]); + currentId->identifierToken = locations[i]; + } + + return currentId->finish(); + } + + return 0; +} + +bool Parser::parse() +{ + Lexer *lexer = driver->lexer(); + bool hadErrors = false; + int yytoken = -1; + int action = 0; + + first_token = last_token = 0; + + tos = -1; + program = 0; + + do { + if (++tos == stack_size) + reallocateStack(); + + state_stack[tos] = action; + + _Lcheck_token: + if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { + yyprevlloc = yylloc; + + if (first_token == last_token) { + yytoken = lexer->lex(); + yylval = lexer->dval(); + yylloc = location(lexer); + } else { + yytoken = first_token->token; + yylval = first_token->dval; + yylloc = first_token->loc; + ++first_token; + } + } + + action = t_action(action, yytoken); + if (action > 0) { + if (action != ACCEPT_STATE) { + yytoken = -1; + sym(1).dval = yylval; + loc(1) = yylloc; + } else { + --tos; + return ! hadErrors; + } + } else if (action < 0) { + const int r = -action - 1; + tos -= rhs[r]; + + switch (r) { +./ + +-------------------------------------------------------------------------------------------------------- +-- Declarative UI +-------------------------------------------------------------------------------------------------------- + +UiProgram: UiImportListOpt UiRootMember ; +/. +case $rule_number: { + program = makeAstNode (driver->nodePool(), sym(1).UiImportList, + sym(2).UiObjectMemberList->finish()); + sym(1).UiProgram = program; +} break; +./ + +UiImportListOpt: Empty ; +UiImportListOpt: UiImportList ; +/. +case $rule_number: { + sym(1).Node = sym(1).UiImportList->finish(); +} break; +./ + +UiImportList: UiImport ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiImport); +} break; +./ + +UiImportList: UiImportList UiImport ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), + sym(1).UiImportList, sym(2).UiImport); +} break; +./ + +UiImport: T_IMPORT T_STRING_LITERAL T_AUTOMATIC_SEMICOLON; +UiImport: T_IMPORT T_STRING_LITERAL T_SEMICOLON; +/. +case $rule_number: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).sval); + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +Empty: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +UiRootMember: UiObjectDefinition ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); +} break; +./ + +UiObjectMemberList: UiObjectMember ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); +} break; +./ + +UiObjectMemberList: UiObjectMemberList UiObjectMember ; +/. +case $rule_number: { + AST::UiObjectMemberList *node = makeAstNode (driver->nodePool(), + sym(1).UiObjectMemberList, sym(2).UiObjectMember); + sym(1).Node = node; +} break; +./ + +UiArrayMemberList: UiObjectDefinition ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); +} break; +./ + +UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; +/. +case $rule_number: { + AST::UiArrayMemberList *node = makeAstNode (driver->nodePool(), + sym(1).UiArrayMemberList, sym(3).UiObjectMember); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiObjectInitializer: T_LBRACE T_RBRACE ; +/. +case $rule_number: { + AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), (AST::UiObjectMemberList*)0); + node->lbraceToken = loc(1); + node->rbraceToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ; +/. +case $rule_number: { + AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), sym(2).UiObjectMemberList->finish()); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +UiObjectDefinition: UiQualifiedId UiObjectInitializer ; +/. +case $rule_number: { + AST::UiObjectDefinition *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), + sym(2).UiObjectInitializer); + sym(1).Node = node; +} break; +./ + +UiObjectMember: UiObjectDefinition ; + +UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; +/. +case $rule_number: { + AST::UiArrayBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), + sym(4).UiArrayMemberList->finish()); + node->colonToken = loc(2); + node->lbracketToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; +./ + +UiMultilineStringLiteral: T_MULTILINE_STRING_LITERAL ; +/. +case $rule_number: { + AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +UiMultilineStringStatement: UiMultilineStringLiteral T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +UiMultilineStringStatement: UiMultilineStringLiteral T_SEMICOLON ; +/. +case $rule_number: { + AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + + +UiObjectMember: UiQualifiedId T_COLON Expression UiObjectInitializer ; +/. +case $rule_number: { + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { + AST::UiObjectBinding *node = makeAstNode (driver->nodePool(), + sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); + node->colonToken = loc(2); + sym(1).Node = node; + } else { + sym(1).Node = 0; + + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2), + QLatin1String("Expected a type name after token `:'"))); + + return false; // ### recover + } +} break; +./ + +UiObjectMember: UiQualifiedId T_COLON Block ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON EmptyStatement ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON DebuggerStatement ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON UiMultilineStringStatement ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding? +/.case $rule_number:./ + +/. +{ + AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), + sym(3).Statement); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiPropertyType: T_VAR ; +/. +case $rule_number: +./ +UiPropertyType: T_RESERVED_WORD ; +/. +case $rule_number: { + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); + break; +} +./ + +UiPropertyType: T_IDENTIFIER ; + +UiObjectMember: T_SIGNAL T_IDENTIFIER ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->semicolonToken = loc(4); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, + sym(5).Expression); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->colonToken = loc(4); + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, + sym(6).Expression); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; +./ + +UiObjectMember: FunctionDeclaration ; +/. +case $rule_number: { + sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); +} break; +./ + +UiObjectMember: VariableStatement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); +} break; +./ + +UiQualifiedId: T_RESERVED_WORD ; +/.case $rule_number: ./ + +UiQualifiedId: T_RETURN ; +/. +case $rule_number: +{ + AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +JsIdentifier: T_IDENTIFIER; + +JsIdentifier: T_PROPERTY ; +/. +case $rule_number: { + QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} +./ + +JsIdentifier: T_SIGNAL ; +/. +case $rule_number: { + QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} +./ + +-------------------------------------------------------------------------------------------------------- +-- Expressions +-------------------------------------------------------------------------------------------------------- + +PrimaryExpression: T_THIS ; +/. +case $rule_number: { + AST::ThisExpression *node = makeAstNode (driver->nodePool()); + node->thisToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: JsIdentifier ; +/. +case $rule_number: { + AST::IdentifierExpression *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_NULL ; +/. +case $rule_number: { + AST::NullExpression *node = makeAstNode (driver->nodePool()); + node->nullToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_TRUE ; +/. +case $rule_number: { + AST::TrueLiteral *node = makeAstNode (driver->nodePool()); + node->trueToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_FALSE ; +/. +case $rule_number: { + AST::FalseLiteral *node = makeAstNode (driver->nodePool()); + node->falseToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_NUMERIC_LITERAL ; +/. +case $rule_number: { + AST::NumericLiteral *node = makeAstNode (driver->nodePool(), sym(1).dval, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_STRING_LITERAL ; +/. +case $rule_number: { + AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_DIVIDE_ ; +/: +#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number +:/ +/. +case $rule_number: { + bool rx = lexer->scanRegExp(Lexer::NoPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; // ### remove me + } + AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_DIVIDE_EQ ; +/: +#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number +:/ +/. +case $rule_number: { + bool rx = lexer->scanRegExp(Lexer::EqualPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; + } + AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->rbracketToken = loc(2); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).Elision->finish()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish ()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), + (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), + sym(4).Elision->finish()); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; +./ + +-- PrimaryExpression: T_LBRACE T_RBRACE ; +-- /. +-- case $rule_number: { +-- sym(1).Node = makeAstNode (driver->nodePool()); +-- } break; +-- ./ + +PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ; +/. +case $rule_number: { + AST::ObjectLiteral *node = 0; + if (sym(2).Node) + node = makeAstNode (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + else + node = makeAstNode (driver->nodePool()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ; +/. +case $rule_number: { + AST::ObjectLiteral *node = makeAstNode (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(4); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LPAREN Expression T_RPAREN ; +/. +case $rule_number: { + AST::NestedExpression *node = makeAstNode(driver->nodePool(), sym(2).Expression); + node->lparenToken = loc(1); + node->rparenToken = loc(3); + sym(1).Node = node; +} break; +./ + +UiQualifiedId: JsIdentifier ; +/. +case $rule_number: { + AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +UiQualifiedId: UiQualifiedId T_DOT JsIdentifier ; +/. +case $rule_number: { + AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +ElementList: AssignmentExpression ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); +} break; +./ + +ElementList: Elision AssignmentExpression ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); +} break; +./ + +ElementList: ElementList T_COMMA AssignmentExpression ; +/. +case $rule_number: { + AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, + (AST::Elision *) 0, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +ElementList: ElementList T_COMMA Elision AssignmentExpression ; +/. +case $rule_number: { + AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), + sym(4).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +Elision: T_COMMA ; +/. +case $rule_number: { + AST::Elision *node = makeAstNode (driver->nodePool()); + node->commaToken = loc(1); + sym(1).Node = node; +} break; +./ + +Elision: Elision T_COMMA ; +/. +case $rule_number: { + AST::Elision *node = makeAstNode (driver->nodePool(), sym(1).Elision); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ; +/. +case $rule_number: { + AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), + sym(1).PropertyName, sym(3).Expression); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ; +/. +case $rule_number: { + AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), + sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); + node->commaToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; +./ + +PropertyName: T_IDENTIFIER %prec REDUCE_HERE ; +/. +case $rule_number: { + AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: T_SIGNAL ; +/.case $rule_number:./ + +PropertyName: T_PROPERTY ; +/. +case $rule_number: { + AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: T_STRING_LITERAL ; +/. +case $rule_number: { + AST::StringLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: T_NUMERIC_LITERAL ; +/. +case $rule_number: { + AST::NumericLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).dval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: ReservedIdentifier ; +/. +case $rule_number: { + AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +ReservedIdentifier: T_BREAK ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CASE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CATCH ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CONTINUE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DEFAULT ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DELETE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DO ; +/. +case $rule_number: +./ +ReservedIdentifier: T_ELSE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FALSE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FINALLY ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FOR ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FUNCTION ; +/. +case $rule_number: +./ +ReservedIdentifier: T_IF ; +/. +case $rule_number: +./ +ReservedIdentifier: T_IN ; +/. +case $rule_number: +./ +ReservedIdentifier: T_INSTANCEOF ; +/. +case $rule_number: +./ +ReservedIdentifier: T_NEW ; +/. +case $rule_number: +./ +ReservedIdentifier: T_NULL ; +/. +case $rule_number: +./ +ReservedIdentifier: T_RETURN ; +/. +case $rule_number: +./ +ReservedIdentifier: T_SWITCH ; +/. +case $rule_number: +./ +ReservedIdentifier: T_THIS ; +/. +case $rule_number: +./ +ReservedIdentifier: T_THROW ; +/. +case $rule_number: +./ +ReservedIdentifier: T_TRUE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_TRY ; +/. +case $rule_number: +./ +ReservedIdentifier: T_TYPEOF ; +/. +case $rule_number: +./ +ReservedIdentifier: T_VAR ; +/. +case $rule_number: +./ +ReservedIdentifier: T_VOID ; +/. +case $rule_number: +./ +ReservedIdentifier: T_WHILE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CONST ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DEBUGGER ; +/. +case $rule_number: +./ +ReservedIdentifier: T_RESERVED_WORD ; +/. +case $rule_number: +./ +ReservedIdentifier: T_WITH ; +/. +case $rule_number: +{ + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); +} break; +./ + +PropertyIdentifier: JsIdentifier ; +PropertyIdentifier: ReservedIdentifier ; + +MemberExpression: PrimaryExpression ; +MemberExpression: FunctionExpression ; + +MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; +./ + +MemberExpression: MemberExpression T_DOT PropertyIdentifier ; +/. +case $rule_number: { + AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; +/. +case $rule_number: { + AST::NewMemberExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); + node->newToken = loc(1); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + sym(1).Node = node; +} break; +./ + +NewExpression: MemberExpression ; + +NewExpression: T_NEW NewExpression ; +/. +case $rule_number: { + AST::NewExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->newToken = loc(1); + sym(1).Node = node; +} break; +./ + +CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; +/. +case $rule_number: { + AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ; +/. +case $rule_number: { + AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; +./ + +CallExpression: CallExpression T_DOT PropertyIdentifier ; +/. +case $rule_number: { + AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +ArgumentListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +ArgumentListOpt: ArgumentList ; +/. +case $rule_number: { + sym(1).Node = sym(1).ArgumentList->finish(); +} break; +./ + +ArgumentList: AssignmentExpression ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Expression); +} break; +./ + +ArgumentList: ArgumentList T_COMMA AssignmentExpression ; +/. +case $rule_number: { + AST::ArgumentList *node = makeAstNode (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +LeftHandSideExpression: NewExpression ; +LeftHandSideExpression: CallExpression ; +PostfixExpression: LeftHandSideExpression ; + +PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ; +/. +case $rule_number: { + AST::PostIncrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->incrementToken = loc(2); + sym(1).Node = node; +} break; +./ + +PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ; +/. +case $rule_number: { + AST::PostDecrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->decrementToken = loc(2); + sym(1).Node = node; +} break; +./ + +UnaryExpression: PostfixExpression ; + +UnaryExpression: T_DELETE UnaryExpression ; +/. +case $rule_number: { + AST::DeleteExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->deleteToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_VOID UnaryExpression ; +/. +case $rule_number: { + AST::VoidExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->voidToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_TYPEOF UnaryExpression ; +/. +case $rule_number: { + AST::TypeOfExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->typeofToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_PLUS_PLUS UnaryExpression ; +/. +case $rule_number: { + AST::PreIncrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->incrementToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_MINUS_MINUS UnaryExpression ; +/. +case $rule_number: { + AST::PreDecrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->decrementToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_PLUS UnaryExpression ; +/. +case $rule_number: { + AST::UnaryPlusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->plusToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_MINUS UnaryExpression ; +/. +case $rule_number: { + AST::UnaryMinusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->minusToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_TILDE UnaryExpression ; +/. +case $rule_number: { + AST::TildeExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->tildeToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_NOT UnaryExpression ; +/. +case $rule_number: { + AST::NotExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->notToken = loc(1); + sym(1).Node = node; +} break; +./ + +MultiplicativeExpression: UnaryExpression ; + +MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Mul, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Div, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Mod, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AdditiveExpression: MultiplicativeExpression ; + +AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Add, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Sub, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ShiftExpression: AdditiveExpression ; + +ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::LShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::RShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::URShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: ShiftExpression ; + +RelationalExpression: RelationalExpression T_LT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_GT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_LE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_GE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_IN ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::In, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: ShiftExpression ; + +RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: RelationalExpression ; + +EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: RelationalExpressionNotIn ; + +EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseANDExpression: EqualityExpression ; + +BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseANDExpressionNotIn: EqualityExpressionNotIn ; + +BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseXORExpression: BitwiseANDExpression ; + +BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ; + +BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseORExpression: BitwiseXORExpression ; + +BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ; + +BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalANDExpression: BitwiseORExpression ; + +LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ; + +LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalORExpression: LogicalANDExpression ; + +LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalORExpressionNotIn: LogicalANDExpressionNotIn ; + +LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ConditionalExpression: LogicalORExpression ; + +ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ; +/. +case $rule_number: { + AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; +./ + +ConditionalExpressionNotIn: LogicalORExpressionNotIn ; + +ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ; +/. +case $rule_number: { + AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; +./ + +AssignmentExpression: ConditionalExpression ; + +AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AssignmentExpressionNotIn: ConditionalExpressionNotIn ; + +AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AssignmentOperator: T_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::Assign; +} break; +./ + +AssignmentOperator: T_STAR_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceMul; +} break; +./ + +AssignmentOperator: T_DIVIDE_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceDiv; +} break; +./ + +AssignmentOperator: T_REMAINDER_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceMod; +} break; +./ + +AssignmentOperator: T_PLUS_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceAdd; +} break; +./ + +AssignmentOperator: T_MINUS_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceSub; +} break; +./ + +AssignmentOperator: T_LT_LT_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceLeftShift; +} break; +./ + +AssignmentOperator: T_GT_GT_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceRightShift; +} break; +./ + +AssignmentOperator: T_GT_GT_GT_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceURightShift; +} break; +./ + +AssignmentOperator: T_AND_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceAnd; +} break; +./ + +AssignmentOperator: T_XOR_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceXor; +} break; +./ + +AssignmentOperator: T_OR_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceOr; +} break; +./ + +Expression: AssignmentExpression ; + +Expression: Expression T_COMMA AssignmentExpression ; +/. +case $rule_number: { + AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +ExpressionOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +ExpressionOpt: Expression ; + +ExpressionNotIn: AssignmentExpressionNotIn ; + +ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ; +/. +case $rule_number: { + AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +ExpressionNotInOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +ExpressionNotInOpt: ExpressionNotIn ; + +Statement: Block ; +Statement: VariableStatement ; +Statement: EmptyStatement ; +Statement: ExpressionStatement ; +Statement: IfStatement ; +Statement: IterationStatement ; +Statement: ContinueStatement ; +Statement: BreakStatement ; +Statement: ReturnStatement ; +Statement: WithStatement ; +Statement: LabelledStatement ; +Statement: SwitchStatement ; +Statement: ThrowStatement ; +Statement: TryStatement ; +Statement: DebuggerStatement ; + + +Block: T_LBRACE StatementListOpt T_RBRACE ; +/. +case $rule_number: { + AST::Block *node = makeAstNode (driver->nodePool(), sym(2).StatementList); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +StatementList: Statement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); +} break; +./ + +StatementList: StatementList Statement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).StatementList, sym(2).Statement); +} break; +./ + +StatementListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +StatementListOpt: StatementList ; +/. +case $rule_number: { + sym(1).Node = sym(1).StatementList->finish (); +} break; +./ + +VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ; +/. +case $rule_number: { + AST::VariableStatement *node = makeAstNode (driver->nodePool(), + sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); + node->declarationKindToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +VariableDeclarationKind: T_CONST ; +/. +case $rule_number: { + sym(1).ival = T_CONST; +} break; +./ + +VariableDeclarationKind: T_VAR ; +/. +case $rule_number: { + sym(1).ival = T_VAR; +} break; +./ + +VariableDeclarationList: VariableDeclaration ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); +} break; +./ + +VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ; +/. +case $rule_number: { + AST::VariableDeclarationList *node = makeAstNode (driver->nodePool(), + sym(1).VariableDeclarationList, sym(3).VariableDeclaration); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +VariableDeclarationListNotIn: VariableDeclarationNotIn ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); +} break; +./ + +VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); +} break; +./ + +VariableDeclaration: JsIdentifier InitialiserOpt ; +/. +case $rule_number: { + AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ; +/. +case $rule_number: { + AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +Initialiser: T_EQ AssignmentExpression ; +/. +case $rule_number: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; +./ + +InitialiserOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +InitialiserOpt: Initialiser ; + +InitialiserNotIn: T_EQ AssignmentExpressionNotIn ; +/. +case $rule_number: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; +./ + +InitialiserNotInOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +InitialiserNotInOpt: InitialiserNotIn ; + +EmptyStatement: T_SEMICOLON ; +/. +case $rule_number: { + AST::EmptyStatement *node = makeAstNode (driver->nodePool()); + node->semicolonToken = loc(1); + sym(1).Node = node; +} break; +./ + +ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ExpressionStatement: Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ; +/. +case $rule_number: { + AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + node->elseToken = loc(5); + sym(1).Node = node; +} break; +./ + +IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + + +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ; +/. +case $rule_number: { + AST::DoWhileStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(5).Expression); + node->doToken = loc(1); + node->whileToken = loc(3); + node->lparenToken = loc(4); + node->rparenToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::WhileStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->whileToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; +/. +case $rule_number: { + AST::ForStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Expression, sym(9).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->firstSemicolonToken = loc(4); + node->secondSemicolonToken = loc(6); + node->rparenToken = loc(8); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; +/. +case $rule_number: { + AST::LocalForStatement *node = makeAstNode (driver->nodePool(), + sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, + sym(8).Expression, sym(10).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->firstSemicolonToken = loc(5); + node->secondSemicolonToken = loc(7); + node->rparenToken = loc(9); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST:: ForEachStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->inToken = loc(4); + node->rparenToken = loc(6); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::LocalForEachStatement *node = makeAstNode (driver->nodePool(), + sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->inToken = loc(5); + node->rparenToken = loc(7); + sym(1).Node = node; +} break; +./ + +ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ContinueStatement: T_CONTINUE T_SEMICOLON ; +/. +case $rule_number: { + AST::ContinueStatement *node = makeAstNode (driver->nodePool()); + node->continueToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ; +/. +case $rule_number: { + AST::ContinueStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); + node->continueToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +BreakStatement: T_BREAK T_SEMICOLON ; +/. +case $rule_number: { + AST::BreakStatement *node = makeAstNode (driver->nodePool()); + node->breakToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ; +/. +case $rule_number: { + AST::BreakStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); + node->breakToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ; +/. +case $rule_number: { + AST::ReturnStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->returnToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::WithStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->withToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ; +/. +case $rule_number: { + AST::SwitchStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); + node->switchToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ; +/. +case $rule_number: { + AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ; +/. +case $rule_number: { + AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(5); + sym(1).Node = node; +} break; +./ + +CaseClauses: CaseClause ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClause); +} break; +./ + +CaseClauses: CaseClauses CaseClause ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); +} break; +./ + +CaseClausesOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +CaseClausesOpt: CaseClauses ; +/. +case $rule_number: { + sym(1).Node = sym(1).CaseClauses->finish (); +} break; +./ + +CaseClause: T_CASE Expression T_COLON StatementListOpt ; +/. +case $rule_number: { + AST::CaseClause *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).StatementList); + node->caseToken = loc(1); + node->colonToken = loc(3); + sym(1).Node = node; +} break; +./ + +DefaultClause: T_DEFAULT T_COLON StatementListOpt ; +/. +case $rule_number: { + AST::DefaultClause *node = makeAstNode (driver->nodePool(), sym(3).StatementList); + node->defaultToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +LabelledStatement: T_SIGNAL T_COLON Statement ; +/.case $rule_number:./ + +LabelledStatement: T_PROPERTY T_COLON Statement ; +/. +case $rule_number: { + AST::LabelledStatement *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +LabelledStatement: T_IDENTIFIER T_COLON Statement ; +/. +case $rule_number: { + AST::LabelledStatement *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ThrowStatement: T_THROW Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::ThrowStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->throwToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +TryStatement: T_TRY Block Catch ; +/. +case $rule_number: { + AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch); + node->tryToken = loc(1); + sym(1).Node = node; +} break; +./ + +TryStatement: T_TRY Block Finally ; +/. +case $rule_number: { + AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; +./ + +TryStatement: T_TRY Block Catch Finally ; +/. +case $rule_number: { + AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; +./ + +Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ; +/. +case $rule_number: { + AST::Catch *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(5).Block); + node->catchToken = loc(1); + node->lparenToken = loc(2); + node->identifierToken = loc(3); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +Finally: T_FINALLY Block ; +/. +case $rule_number: { + AST::Finally *node = makeAstNode (driver->nodePool(), sym(2).Block); + node->finallyToken = loc(1); + sym(1).Node = node; +} break; +./ + +DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +DebuggerStatement: T_DEBUGGER T_SEMICOLON ; +/. +case $rule_number: { + AST::DebuggerStatement *node = makeAstNode (driver->nodePool()); + node->debuggerToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +/. +case $rule_number: { + AST::FunctionDeclaration *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; +./ + +FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +/. +case $rule_number: { + AST::FunctionExpression *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + if (sym(2).sval) + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; +./ + +FormalParameterList: JsIdentifier ; +/. +case $rule_number: { + AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +FormalParameterList: FormalParameterList T_COMMA JsIdentifier ; +/. +case $rule_number: { + AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); + node->commaToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +FormalParameterListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +FormalParameterListOpt: FormalParameterList ; +/. +case $rule_number: { + sym(1).Node = sym(1).FormalParameterList->finish (); +} break; +./ + +FunctionBodyOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +FunctionBodyOpt: FunctionBody ; + +FunctionBody: SourceElements ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); +} break; +./ + +--QmlJSProgram: SourceElements ; +--/. +--case $rule_number: { +-- sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); +-- driver->changeAbstractSyntaxTree(sym(1).Node); +--} break; +--./ + +SourceElements: SourceElement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElement); +} break; +./ + +SourceElements: SourceElements SourceElement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); +} break; +./ + +SourceElement: Statement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); +} break; +./ + +SourceElement: FunctionDeclaration ; +/. +case $rule_number: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).FunctionDeclaration); +} break; +./ + +IdentifierOpt: ; +/. +case $rule_number: { + sym(1).sval = 0; +} break; +./ + +IdentifierOpt: JsIdentifier ; + +PropertyNameAndValueListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +PropertyNameAndValueListOpt: PropertyNameAndValueList ; + +/. + } // switch + action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); + } // if + } while (action != 0); + + if (first_token == last_token) { + const int errorState = state_stack[tos]; + + // automatic insertion of `;' + if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { + SavedToken &tk = token_buffer[0]; + tk.token = yytoken; + tk.dval = yylval; + tk.loc = yylloc; + + yylloc = yyprevlloc; + yylloc.offset += yylloc.length; + yylloc.startColumn += yylloc.length; + yylloc.length = 0; + + //const QString msg = QString::fromUtf8("Missing `;'"); + //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); + + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; + + yytoken = T_SEMICOLON; + yylval = 0; + + action = errorState; + + goto _Lcheck_token; + } + + hadErrors = true; + + token_buffer[0].token = yytoken; + token_buffer[0].dval = yylval; + token_buffer[0].loc = yylloc; + + token_buffer[1].token = yytoken = lexer->lex(); + token_buffer[1].dval = yylval = lexer->dval(); + token_buffer[1].loc = yylloc = location(lexer); + + if (t_action(errorState, yytoken)) { + const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + action = errorState; + goto _Lcheck_token; + } + + static int tokens[] = { + T_PLUS, + T_EQ, + + T_COMMA, + T_COLON, + T_SEMICOLON, + + T_RPAREN, T_RBRACKET, T_RBRACE, + + T_NUMERIC_LITERAL, + T_IDENTIFIER, + + T_LPAREN, T_LBRACKET, T_LBRACE, + + EOF_SYMBOL + }; + + for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { + int a = t_action(errorState, *tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = *tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + first_token = &token_buffer[0]; + last_token = &token_buffer[2]; + + action = errorState; + goto _Lcheck_token; + } + } + + for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { + if (tk == T_AUTOMATIC_SEMICOLON) + continue; + + int a = t_action(errorState, tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + action = errorState; + goto _Lcheck_token; + } + } + + const QString msg = QString::fromUtf8("Syntax error"); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + } + + return false; +} + +QT_END_NAMESPACE + + +./ +/: +QT_END_NAMESPACE + + + +#endif // QMLJSPARSER_P_H +:/ diff --git a/src/declarative/qml/parser/qmljsast.cpp b/src/declarative/qml/parser/qmljsast.cpp new file mode 100644 index 0000000..d10c071 --- /dev/null +++ b/src/declarative/qml/parser/qmljsast.cpp @@ -0,0 +1,962 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 "qmljsast_p.h" + + + +#include "qmljsastvisitor_p.h" + +QT_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +int NumericLiteral::suffixLength[] = { + 0, // noSuffix + 2, // emSuffix + 2, // exSuffix + 2, // pxSuffix + 2, // cmSuffix + 2, // mmSuffix + 2, // inSuffix + 2, // ptSuffix + 2, // pcSuffix + 3, // degSuffix + 3, // radSuffix + 4, // gradSuffix + 2, // msSuffix + 1, // sSuffix + 2, // hzSuffix + 3 // khzSuffix +}; + +const char *const NumericLiteral::suffixSpell[] = { + "", + "em", + "ex", + "px", + "cm", + "mm", + "in", + "pt", + "pc", + "deg", + "rad", + "grad", + "ms", + "s", + "hz", + "khz" +}; + +ExpressionNode *Node::expressionCast() +{ + return 0; +} + +BinaryExpression *Node::binaryExpressionCast() +{ + return 0; +} + +Statement *Node::statementCast() +{ + return 0; +} + +ExpressionNode *ExpressionNode::expressionCast() +{ + return this; +} + +BinaryExpression *BinaryExpression::binaryExpressionCast() +{ + return this; +} + +Statement *Statement::statementCast() +{ + return this; +} + +void NestedExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + visitor->endVisit(this); +} + +void ThisExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void IdentifierExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void NullExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void TrueLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void FalseLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void StringLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void NumericLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void RegExpLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ArrayLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(elements, visitor); + acceptChild(elision, visitor); + } + + visitor->endVisit(this); +} + +void ObjectLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(properties, visitor); + } + + visitor->endVisit(this); +} + +void ElementList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + ElementList *it = this; + do { + acceptChild(it->elision, visitor); + acceptChild(it->expression, visitor); + it = it->next; + } while (it); + } + + visitor->endVisit(this); +} + +void Elision::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + // ### + } + + visitor->endVisit(this); +} + +void PropertyNameAndValueList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + PropertyNameAndValueList *it = this; + do { + acceptChild(it->name, visitor); + acceptChild(it->value, visitor); + it = it->next; + } while (it); + } + + visitor->endVisit(this); +} + +void IdentifierPropertyName::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void StringLiteralPropertyName::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void NumericLiteralPropertyName::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ArrayMemberExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(base, visitor); + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void FieldMemberExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(base, visitor); + } + + visitor->endVisit(this); +} + +void NewMemberExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(base, visitor); + acceptChild(arguments, visitor); + } + + visitor->endVisit(this); +} + +void NewExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void CallExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(base, visitor); + acceptChild(arguments, visitor); + } + + visitor->endVisit(this); +} + +void ArgumentList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + ArgumentList *it = this; + do { + acceptChild(it->expression, visitor); + it = it->next; + } while (it); + } + + visitor->endVisit(this); +} + +void PostIncrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(base, visitor); + } + + visitor->endVisit(this); +} + +void PostDecrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(base, visitor); + } + + visitor->endVisit(this); +} + +void DeleteExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void VoidExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void TypeOfExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void PreIncrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void PreDecrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void UnaryPlusExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void UnaryMinusExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void TildeExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void NotExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void BinaryExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(left, visitor); + acceptChild(right, visitor); + } + + visitor->endVisit(this); +} + +void ConditionalExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + acceptChild(ok, visitor); + acceptChild(ko, visitor); + } + + visitor->endVisit(this); +} + +void Expression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(left, visitor); + acceptChild(right, visitor); + } + + visitor->endVisit(this); +} + +void Block::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statements, visitor); + } + + visitor->endVisit(this); +} + +void StatementList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + StatementList *it = this; + do { + acceptChild(it->statement, visitor); + it = it->next; + } while (it); + } + + visitor->endVisit(this); +} + +void VariableStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(declarations, visitor); + } + + visitor->endVisit(this); +} + +void VariableDeclarationList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + VariableDeclarationList *it = this; + do { + acceptChild(it->declaration, visitor); + it = it->next; + } while (it); + } + + visitor->endVisit(this); +} + +void VariableDeclaration::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void EmptyStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ExpressionStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void IfStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + acceptChild(ok, visitor); + acceptChild(ko, visitor); + } + + visitor->endVisit(this); +} + +void DoWhileStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statement, visitor); + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void WhileStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void ForStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(initialiser, visitor); + acceptChild(condition, visitor); + acceptChild(expression, visitor); + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void LocalForStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(declarations, visitor); + acceptChild(condition, visitor); + acceptChild(expression, visitor); + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void ForEachStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(initialiser, visitor); + acceptChild(expression, visitor); + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void LocalForEachStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(declaration, visitor); + acceptChild(expression, visitor); + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void ContinueStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void BreakStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ReturnStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void WithStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void SwitchStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + acceptChild(block, visitor); + } + + visitor->endVisit(this); +} + +void CaseBlock::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(clauses, visitor); + acceptChild(defaultClause, visitor); + acceptChild(moreClauses, visitor); + } + + visitor->endVisit(this); +} + +void CaseClauses::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + CaseClauses *it = this; + do { + acceptChild(it->clause, visitor); + it = it->next; + } while (it); + } + + visitor->endVisit(this); +} + +void CaseClause::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + acceptChild(statements, visitor); + } + + visitor->endVisit(this); +} + +void DefaultClause::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statements, visitor); + } + + visitor->endVisit(this); +} + +void LabelledStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void ThrowStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void TryStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statement, visitor); + acceptChild(catchExpression, visitor); + acceptChild(finallyExpression, visitor); + } + + visitor->endVisit(this); +} + +void Catch::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void Finally::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void FunctionDeclaration::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(formals, visitor); + acceptChild(body, visitor); + } + + visitor->endVisit(this); +} + +void FunctionExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(formals, visitor); + acceptChild(body, visitor); + } + + visitor->endVisit(this); +} + +void FormalParameterList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + // ### + } + + visitor->endVisit(this); +} + +void FunctionBody::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(elements, visitor); + } + + visitor->endVisit(this); +} + +void Program::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(elements, visitor); + } + + visitor->endVisit(this); +} + +void SourceElements::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + SourceElements *it = this; + do { + acceptChild(it->element, visitor); + it = it->next; + } while (it); + } + + visitor->endVisit(this); +} + +void FunctionSourceElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(declaration, visitor); + } + + visitor->endVisit(this); +} + +void StatementSourceElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void DebuggerStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + + +void UiProgram::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiObjectMemberList *it = members; it; it = it->next) + acceptChild(it->member, visitor); + } + + visitor->endVisit(this); +} + +void UiPublicMember::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(expression, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectDefinition::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(qualifiedTypeNameId, visitor); + acceptChild(initializer, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectInitializer::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiObjectMemberList *it = members; it; it = it->next) + acceptChild(it->member, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectBinding::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(qualifiedId, visitor); + acceptChild(qualifiedTypeNameId, visitor); + acceptChild(initializer, visitor); + } + + visitor->endVisit(this); +} + +void UiScriptBinding::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(qualifiedId, visitor); + acceptChild(statement, visitor); + } + + visitor->endVisit(this); +} + +void UiArrayBinding::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(qualifiedId, visitor); + for (UiArrayMemberList *it = members; it; it = it->next) + acceptChild(it->member, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectMemberList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiObjectMemberList *it = this; it; it = it->next) + acceptChild(it->member, visitor); + } + + visitor->endVisit(this); +} + +void UiArrayMemberList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiArrayMemberList *it = this; it; it = it->next) + acceptChild(it->member, visitor); + } + + visitor->endVisit(this); +} + +void UiQualifiedId::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void UiImport::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void UiImportList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(import, visitor); + acceptChild(next, visitor); + } + + visitor->endVisit(this); +} + +void UiSourceElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + acceptChild(sourceElement, visitor); + } + + visitor->endVisit(this); +} + +} } // namespace QmlJS::AST + +QT_END_NAMESPACE + + diff --git a/src/declarative/qml/parser/qmljsast_p.h b/src/declarative/qml/parser/qmljsast_p.h new file mode 100644 index 0000000..8dc32ed --- /dev/null +++ b/src/declarative/qml/parser/qmljsast_p.h @@ -0,0 +1,2544 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 QMLJSAST_P_H +#define QMLJSAST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qmljsastvisitor_p.h" +#include + +QT_BEGIN_NAMESPACE + +#define QMLJS_DECLARE_AST_NODE(name) \ + enum { K = Kind_##name }; + +namespace QSOperator // ### rename +{ + +enum Op { + Add, + And, + InplaceAnd, + Assign, + BitAnd, + BitOr, + BitXor, + InplaceSub, + Div, + InplaceDiv, + Equal, + Ge, + Gt, + In, + InplaceAdd, + InstanceOf, + Le, + LShift, + InplaceLeftShift, + Lt, + Mod, + InplaceMod, + Mul, + InplaceMul, + NotEqual, + Or, + InplaceOr, + RShift, + InplaceRightShift, + StrictEqual, + StrictNotEqual, + Sub, + URShift, + InplaceURightShift, + InplaceXor +}; + +} // namespace QSOperator + +namespace QmlJS { +class NameId; +namespace AST { + +template +_T1 cast(_T2 *ast) +{ + if (ast && ast->kind == static_cast<_T1>(0)->K) + return static_cast<_T1>(ast); + + return 0; +} + +class Node +{ +public: + enum Kind { + Kind_Undefined, + + Kind_ArgumentList, + Kind_ArrayLiteral, + Kind_ArrayMemberExpression, + Kind_BinaryExpression, + Kind_Block, + Kind_BreakStatement, + Kind_CallExpression, + Kind_CaseBlock, + Kind_CaseClause, + Kind_CaseClauses, + Kind_Catch, + Kind_ConditionalExpression, + Kind_ContinueStatement, + Kind_DebuggerStatement, + Kind_DefaultClause, + Kind_DeleteExpression, + Kind_DoWhileStatement, + Kind_ElementList, + Kind_Elision, + Kind_EmptyStatement, + Kind_Expression, + Kind_ExpressionStatement, + Kind_FalseLiteral, + Kind_FieldMemberExpression, + Kind_Finally, + Kind_ForEachStatement, + Kind_ForStatement, + Kind_FormalParameterList, + Kind_FunctionBody, + Kind_FunctionDeclaration, + Kind_FunctionExpression, + Kind_FunctionSourceElement, + Kind_IdentifierExpression, + Kind_IdentifierPropertyName, + Kind_IfStatement, + Kind_LabelledStatement, + Kind_LocalForEachStatement, + Kind_LocalForStatement, + Kind_NewExpression, + Kind_NewMemberExpression, + Kind_NotExpression, + Kind_NullExpression, + Kind_NumericLiteral, + Kind_NumericLiteralPropertyName, + Kind_ObjectLiteral, + Kind_PostDecrementExpression, + Kind_PostIncrementExpression, + Kind_PreDecrementExpression, + Kind_PreIncrementExpression, + Kind_Program, + Kind_PropertyName, + Kind_PropertyNameAndValueList, + Kind_RegExpLiteral, + Kind_ReturnStatement, + Kind_SourceElement, + Kind_SourceElements, + Kind_StatementList, + Kind_StatementSourceElement, + Kind_StringLiteral, + Kind_StringLiteralPropertyName, + Kind_SwitchStatement, + Kind_ThisExpression, + Kind_ThrowStatement, + Kind_TildeExpression, + Kind_TrueLiteral, + Kind_TryStatement, + Kind_TypeOfExpression, + Kind_UnaryMinusExpression, + Kind_UnaryPlusExpression, + Kind_VariableDeclaration, + Kind_VariableDeclarationList, + Kind_VariableStatement, + Kind_VoidExpression, + Kind_WhileStatement, + Kind_WithStatement, + Kind_NestedExpression, + + Kind_UiArrayBinding, + Kind_UiImport, + Kind_UiImportList, + Kind_UiObjectBinding, + Kind_UiObjectDefinition, + Kind_UiObjectInitializer, + Kind_UiObjectMemberList, + Kind_UiArrayMemberList, + Kind_UiProgram, + Kind_UiPublicMember, + Kind_UiQualifiedId, + Kind_UiScriptBinding, + Kind_UiSourceElement + }; + + inline Node() + : kind(Kind_Undefined) {} + + virtual ~Node() {} + + virtual ExpressionNode *expressionCast(); + virtual BinaryExpression *binaryExpressionCast(); + virtual Statement *statementCast(); + + inline void accept(Visitor *visitor) + { + if (visitor->preVisit(this)) { + accept0(visitor); + visitor->postVisit(this); + } + } + + static void acceptChild(Node *node, Visitor *visitor) + { + if (node) + node->accept(visitor); + } + + virtual void accept0(Visitor *visitor) = 0; + +// attributes + int kind; +}; + +class ExpressionNode: public Node +{ +public: + ExpressionNode() {} + virtual ~ExpressionNode() {} + + virtual ExpressionNode *expressionCast(); + + virtual SourceLocation firstSourceLocation() const = 0; + virtual SourceLocation lastSourceLocation() const = 0; +}; + +class Statement: public Node +{ +public: + Statement() {} + virtual ~Statement() {} + + virtual Statement *statementCast(); + + virtual SourceLocation firstSourceLocation() const = 0; + virtual SourceLocation lastSourceLocation() const = 0; +}; + +class NestedExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NestedExpression) + + NestedExpression(ExpressionNode *expression) + : expression(expression) + { kind = K; } + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lparenToken; } + + virtual SourceLocation lastSourceLocation() const + { return rparenToken; } + +// attributes + ExpressionNode *expression; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class ThisExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ThisExpression) + + ThisExpression() { kind = K; } + virtual ~ThisExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return thisToken; } + + virtual SourceLocation lastSourceLocation() const + { return thisToken; } + +// attributes + SourceLocation thisToken; +}; + +class IdentifierExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(IdentifierExpression) + + IdentifierExpression(NameId *n): + name (n) { kind = K; } + + virtual ~IdentifierExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return identifierToken; } + +// attributes + NameId *name; + SourceLocation identifierToken; +}; + +class NullExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NullExpression) + + NullExpression() { kind = K; } + virtual ~NullExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return nullToken; } + + virtual SourceLocation lastSourceLocation() const + { return nullToken; } + +// attributes + SourceLocation nullToken; +}; + +class TrueLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(TrueLiteral) + + TrueLiteral() { kind = K; } + virtual ~TrueLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return trueToken; } + + virtual SourceLocation lastSourceLocation() const + { return trueToken; } + +// attributes + SourceLocation trueToken; +}; + +class FalseLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(FalseLiteral) + + FalseLiteral() { kind = K; } + virtual ~FalseLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return falseToken; } + + virtual SourceLocation lastSourceLocation() const + { return falseToken; } + +// attributes + SourceLocation falseToken; +}; + +class NumericLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NumericLiteral) + + enum Suffix { // ### keep it in sync with the Suffix enum in qmljslexer_p.h + noSuffix, + emSuffix, + exSuffix, + pxSuffix, + cmSuffix, + mmSuffix, + inSuffix, + ptSuffix, + pcSuffix, + degSuffix, + radSuffix, + gradSuffix, + msSuffix, + sSuffix, + hzSuffix, + khzSuffix + }; + + static int suffixLength[]; + static const char *const suffixSpell[]; + + NumericLiteral(double v, int suffix): + value(v), suffix(suffix) { kind = K; } + virtual ~NumericLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return literalToken; } + + virtual SourceLocation lastSourceLocation() const + { return literalToken; } + +// attributes: + double value; + int suffix; + SourceLocation literalToken; +}; + +class StringLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(StringLiteral) + + StringLiteral(NameId *v): + value (v) { kind = K; } + + virtual ~StringLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return literalToken; } + + virtual SourceLocation lastSourceLocation() const + { return literalToken; } + +// attributes: + NameId *value; + SourceLocation literalToken; +}; + +class RegExpLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(RegExpLiteral) + + RegExpLiteral(NameId *p, int f): + pattern (p), flags (f) { kind = K; } + + virtual ~RegExpLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return literalToken; } + + virtual SourceLocation lastSourceLocation() const + { return literalToken; } + +// attributes: + NameId *pattern; + int flags; + SourceLocation literalToken; +}; + +class ArrayLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ArrayLiteral) + + ArrayLiteral(Elision *e): + elements (0), elision (e) + { kind = K; } + + ArrayLiteral(ElementList *elts): + elements (elts), elision (0) + { kind = K; } + + ArrayLiteral(ElementList *elts, Elision *e): + elements (elts), elision (e) + { kind = K; } + + virtual ~ArrayLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lbracketToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbracketToken; } + +// attributes + ElementList *elements; + Elision *elision; + SourceLocation lbracketToken; + SourceLocation commaToken; + SourceLocation rbracketToken; +}; + +class ObjectLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ObjectLiteral) + + ObjectLiteral(): + properties (0) { kind = K; } + + ObjectLiteral(PropertyNameAndValueList *plist): + properties (plist) { kind = K; } + + virtual ~ObjectLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lbraceToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbraceToken; } + +// attributes + PropertyNameAndValueList *properties; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class ElementList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(ElementList) + + ElementList(Elision *e, ExpressionNode *expr): + elision (e), expression (expr), next (this) + { kind = K; } + + ElementList(ElementList *previous, Elision *e, ExpressionNode *expr): + elision (e), expression (expr) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~ElementList() {} + + inline ElementList *finish () + { + ElementList *front = next; + next = 0; + return front; + } + + virtual void accept0(Visitor *visitor); + +// attributes + Elision *elision; + ExpressionNode *expression; + ElementList *next; + SourceLocation commaToken; +}; + +class Elision: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Elision) + + Elision(): + next (this) { kind = K; } + + Elision(Elision *previous) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~Elision() {} + + virtual void accept0(Visitor *visitor); + + inline Elision *finish () + { + Elision *front = next; + next = 0; + return front; + } + +// attributes + Elision *next; + SourceLocation commaToken; +}; + +class PropertyNameAndValueList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(PropertyNameAndValueList) + + PropertyNameAndValueList(PropertyName *n, ExpressionNode *v): + name (n), value (v), next (this) + { kind = K; } + + PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v): + name (n), value (v) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~PropertyNameAndValueList() {} + + virtual void accept0(Visitor *visitor); + + inline PropertyNameAndValueList *finish () + { + PropertyNameAndValueList *front = next; + next = 0; + return front; + } + +// attributes + PropertyName *name; + ExpressionNode *value; + PropertyNameAndValueList *next; + SourceLocation colonToken; + SourceLocation commaToken; +}; + +class PropertyName: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(PropertyName) + + PropertyName() { kind = K; } + virtual ~PropertyName() {} + +// attributes + SourceLocation propertyNameToken; +}; + +class IdentifierPropertyName: public PropertyName +{ +public: + QMLJS_DECLARE_AST_NODE(IdentifierPropertyName) + + IdentifierPropertyName(NameId *n): + id (n) { kind = K; } + + virtual ~IdentifierPropertyName() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *id; +}; + +class StringLiteralPropertyName: public PropertyName +{ +public: + QMLJS_DECLARE_AST_NODE(StringLiteralPropertyName) + + StringLiteralPropertyName(NameId *n): + id (n) { kind = K; } + virtual ~StringLiteralPropertyName() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *id; +}; + +class NumericLiteralPropertyName: public PropertyName +{ +public: + QMLJS_DECLARE_AST_NODE(NumericLiteralPropertyName) + + NumericLiteralPropertyName(double n): + id (n) { kind = K; } + virtual ~NumericLiteralPropertyName() {} + + virtual void accept0(Visitor *visitor); + +// attributes + double id; +}; + +class ArrayMemberExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ArrayMemberExpression) + + ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e): + base (b), expression (e) + { kind = K; } + + virtual ~ArrayMemberExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return rbracketToken; } + +// attributes + ExpressionNode *base; + ExpressionNode *expression; + SourceLocation lbracketToken; + SourceLocation rbracketToken; +}; + +class FieldMemberExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(FieldMemberExpression) + + FieldMemberExpression(ExpressionNode *b, NameId *n): + base (b), name (n) + { kind = K; } + + virtual ~FieldMemberExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return identifierToken; } + + // attributes + ExpressionNode *base; + NameId *name; + SourceLocation dotToken; + SourceLocation identifierToken; +}; + +class NewMemberExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NewMemberExpression) + + NewMemberExpression(ExpressionNode *b, ArgumentList *a): + base (b), arguments (a) + { kind = K; } + + virtual ~NewMemberExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return newToken; } + + virtual SourceLocation lastSourceLocation() const + { return rparenToken; } + + // attributes + ExpressionNode *base; + ArgumentList *arguments; + SourceLocation newToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class NewExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NewExpression) + + NewExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~NewExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return newToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation newToken; +}; + +class CallExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(CallExpression) + + CallExpression(ExpressionNode *b, ArgumentList *a): + base (b), arguments (a) + { kind = K; } + + virtual ~CallExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return rparenToken; } + +// attributes + ExpressionNode *base; + ArgumentList *arguments; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class ArgumentList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(ArgumentList) + + ArgumentList(ExpressionNode *e): + expression (e), next (this) + { kind = K; } + + ArgumentList(ArgumentList *previous, ExpressionNode *e): + expression (e) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~ArgumentList() {} + + virtual void accept0(Visitor *visitor); + + inline ArgumentList *finish () + { + ArgumentList *front = next; + next = 0; + return front; + } + +// attributes + ExpressionNode *expression; + ArgumentList *next; + SourceLocation commaToken; +}; + +class PostIncrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PostIncrementExpression) + + PostIncrementExpression(ExpressionNode *b): + base (b) { kind = K; } + + virtual ~PostIncrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return incrementToken; } + +// attributes + ExpressionNode *base; + SourceLocation incrementToken; +}; + +class PostDecrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PostDecrementExpression) + + PostDecrementExpression(ExpressionNode *b): + base (b) { kind = K; } + + virtual ~PostDecrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return decrementToken; } + +// attributes + ExpressionNode *base; + SourceLocation decrementToken; +}; + +class DeleteExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(DeleteExpression) + + DeleteExpression(ExpressionNode *e): + expression (e) { kind = K; } + virtual ~DeleteExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return deleteToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation deleteToken; +}; + +class VoidExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(VoidExpression) + + VoidExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~VoidExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return voidToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation voidToken; +}; + +class TypeOfExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(TypeOfExpression) + + TypeOfExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~TypeOfExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return typeofToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation typeofToken; +}; + +class PreIncrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PreIncrementExpression) + + PreIncrementExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~PreIncrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return incrementToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation incrementToken; +}; + +class PreDecrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PreDecrementExpression) + + PreDecrementExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~PreDecrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return decrementToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation decrementToken; +}; + +class UnaryPlusExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(UnaryPlusExpression) + + UnaryPlusExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~UnaryPlusExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return plusToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation plusToken; +}; + +class UnaryMinusExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(UnaryMinusExpression) + + UnaryMinusExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~UnaryMinusExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return minusToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation minusToken; +}; + +class TildeExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(TildeExpression) + + TildeExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~TildeExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return tildeToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation tildeToken; +}; + +class NotExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NotExpression) + + NotExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~NotExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return notToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation notToken; +}; + +class BinaryExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(BinaryExpression) + + BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r): + left (l), op (o), right (r) + { kind = K; } + + virtual ~BinaryExpression() {} + + virtual BinaryExpression *binaryExpressionCast(); + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return left->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return right->lastSourceLocation(); } + +// attributes + ExpressionNode *left; + int op; + ExpressionNode *right; + SourceLocation operatorToken; +}; + +class ConditionalExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ConditionalExpression) + + ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f): + expression (e), ok (t), ko (f) + { kind = K; } + + virtual ~ConditionalExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return expression->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return ko->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + ExpressionNode *ok; + ExpressionNode *ko; + SourceLocation questionToken; + SourceLocation colonToken; +}; + +class Expression: public ExpressionNode // ### rename +{ +public: + QMLJS_DECLARE_AST_NODE(Expression) + + Expression(ExpressionNode *l, ExpressionNode *r): + left (l), right (r) { kind = K; } + + virtual ~Expression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return left->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return right->lastSourceLocation(); } + +// attributes + ExpressionNode *left; + ExpressionNode *right; + SourceLocation commaToken; +}; + +class Block: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(Block) + + Block(StatementList *slist): + statements (slist) { kind = K; } + + virtual ~Block() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lbraceToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbraceToken; } + + // attributes + StatementList *statements; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class StatementList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(StatementList) + + StatementList(Statement *stmt): + statement (stmt), next (this) + { kind = K; } + + StatementList(StatementList *previous, Statement *stmt): + statement (stmt) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~StatementList() {} + + virtual void accept0(Visitor *visitor); + + inline StatementList *finish () + { + StatementList *front = next; + next = 0; + return front; + } + +// attributes + Statement *statement; + StatementList *next; +}; + +class VariableStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(VariableStatement) + + VariableStatement(VariableDeclarationList *vlist): + declarations (vlist) + { kind = K; } + + virtual ~VariableStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return declarationKindToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + VariableDeclarationList *declarations; + SourceLocation declarationKindToken; + SourceLocation semicolonToken; +}; + +class VariableDeclaration: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(VariableDeclaration) + + VariableDeclaration(NameId *n, ExpressionNode *e): + name (n), expression (e), readOnly(false) + { kind = K; } + + virtual ~VariableDeclaration() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *name; + ExpressionNode *expression; + bool readOnly; + SourceLocation identifierToken; +}; + +class VariableDeclarationList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(VariableDeclarationList) + + VariableDeclarationList(VariableDeclaration *decl): + declaration (decl), next (this) + { kind = K; } + + VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl): + declaration (decl) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~VariableDeclarationList() {} + + virtual void accept0(Visitor *visitor); + + inline VariableDeclarationList *finish (bool readOnly) + { + VariableDeclarationList *front = next; + next = 0; + if (readOnly) { + VariableDeclarationList *vdl; + for (vdl = front; vdl != 0; vdl = vdl->next) + vdl->declaration->readOnly = true; + } + return front; + } + +// attributes + VariableDeclaration *declaration; + VariableDeclarationList *next; + SourceLocation commaToken; +}; + +class EmptyStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(EmptyStatement) + + EmptyStatement() { kind = K; } + virtual ~EmptyStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return semicolonToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + SourceLocation semicolonToken; +}; + +class ExpressionStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ExpressionStatement) + + ExpressionStatement(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~ExpressionStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return expression->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + ExpressionNode *expression; + SourceLocation semicolonToken; +}; + +class IfStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(IfStatement) + + IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0): + expression (e), ok (t), ko (f) + { kind = K; } + + virtual ~IfStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return ifToken; } + + virtual SourceLocation lastSourceLocation() const + { + if (ko) + return ko->lastSourceLocation(); + + return ok->lastSourceLocation(); + } + +// attributes + ExpressionNode *expression; + Statement *ok; + Statement *ko; + SourceLocation ifToken; + SourceLocation lparenToken; + SourceLocation rparenToken; + SourceLocation elseToken; +}; + +class DoWhileStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(DoWhileStatement) + + DoWhileStatement(Statement *stmt, ExpressionNode *e): + statement (stmt), expression (e) + { kind = K; } + + virtual ~DoWhileStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return doToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + Statement *statement; + ExpressionNode *expression; + SourceLocation doToken; + SourceLocation whileToken; + SourceLocation lparenToken; + SourceLocation rparenToken; + SourceLocation semicolonToken; +}; + +class WhileStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(WhileStatement) + + WhileStatement(ExpressionNode *e, Statement *stmt): + expression (e), statement (stmt) + { kind = K; } + + virtual ~WhileStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return whileToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + Statement *statement; + SourceLocation whileToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class ForStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ForStatement) + + ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt): + initialiser (i), condition (c), expression (e), statement (stmt) + { kind = K; } + + virtual ~ForStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *initialiser; + ExpressionNode *condition; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation firstSemicolonToken; + SourceLocation secondSemicolonToken; + SourceLocation rparenToken; +}; + +class LocalForStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(LocalForStatement) + + LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt): + declarations (vlist), condition (c), expression (e), statement (stmt) + { kind = K; } + + virtual ~LocalForStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + VariableDeclarationList *declarations; + ExpressionNode *condition; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation varToken; + SourceLocation firstSemicolonToken; + SourceLocation secondSemicolonToken; + SourceLocation rparenToken; +}; + +class ForEachStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ForEachStatement) + + ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt): + initialiser (i), expression (e), statement (stmt) + { kind = K; } + + virtual ~ForEachStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *initialiser; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation inToken; + SourceLocation rparenToken; +}; + +class LocalForEachStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(LocalForEachStatement) + + LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt): + declaration (v), expression (e), statement (stmt) + { kind = K; } + + virtual ~LocalForEachStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + VariableDeclaration *declaration; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation varToken; + SourceLocation inToken; + SourceLocation rparenToken; +}; + +class ContinueStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ContinueStatement) + + ContinueStatement(NameId *l = 0): + label (l) { kind = K; } + + virtual ~ContinueStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return continueToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + NameId *label; + SourceLocation continueToken; + SourceLocation identifierToken; + SourceLocation semicolonToken; +}; + +class BreakStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(BreakStatement) + + BreakStatement(NameId *l = 0): + label (l) { kind = K; } + + virtual ~BreakStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return breakToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + + // attributes + NameId *label; + SourceLocation breakToken; + SourceLocation identifierToken; + SourceLocation semicolonToken; +}; + +class ReturnStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ReturnStatement) + + ReturnStatement(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~ReturnStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return returnToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + ExpressionNode *expression; + SourceLocation returnToken; + SourceLocation semicolonToken; +}; + +class WithStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(WithStatement) + + WithStatement(ExpressionNode *e, Statement *stmt): + expression (e), statement (stmt) + { kind = K; } + + virtual ~WithStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return withToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + Statement *statement; + SourceLocation withToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class CaseBlock: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(CaseBlock) + + CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0): + clauses (c), defaultClause (d), moreClauses (r) + { kind = K; } + + virtual ~CaseBlock() {} + + virtual void accept0(Visitor *visitor); + +// attributes + CaseClauses *clauses; + DefaultClause *defaultClause; + CaseClauses *moreClauses; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class SwitchStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(SwitchStatement) + + SwitchStatement(ExpressionNode *e, CaseBlock *b): + expression (e), block (b) + { kind = K; } + + virtual ~SwitchStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return switchToken; } + + virtual SourceLocation lastSourceLocation() const + { return block->rbraceToken; } + +// attributes + ExpressionNode *expression; + CaseBlock *block; + SourceLocation switchToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class CaseClauses: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(CaseClauses) + + CaseClauses(CaseClause *c): + clause (c), next (this) + { kind = K; } + + CaseClauses(CaseClauses *previous, CaseClause *c): + clause (c) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~CaseClauses() {} + + virtual void accept0(Visitor *visitor); + + inline CaseClauses *finish () + { + CaseClauses *front = next; + next = 0; + return front; + } + +//attributes + CaseClause *clause; + CaseClauses *next; +}; + +class CaseClause: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(CaseClause) + + CaseClause(ExpressionNode *e, StatementList *slist): + expression (e), statements (slist) + { kind = K; } + + virtual ~CaseClause() {} + + virtual void accept0(Visitor *visitor); + +// attributes + ExpressionNode *expression; + StatementList *statements; + SourceLocation caseToken; + SourceLocation colonToken; +}; + +class DefaultClause: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(DefaultClause) + + DefaultClause(StatementList *slist): + statements (slist) + { kind = K; } + + virtual ~DefaultClause() {} + + virtual void accept0(Visitor *visitor); + +// attributes + StatementList *statements; + SourceLocation defaultToken; + SourceLocation colonToken; +}; + +class LabelledStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(LabelledStatement) + + LabelledStatement(NameId *l, Statement *stmt): + label (l), statement (stmt) + { kind = K; } + + virtual ~LabelledStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + NameId *label; + Statement *statement; + SourceLocation identifierToken; + SourceLocation colonToken; +}; + +class ThrowStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ThrowStatement) + + ThrowStatement(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~ThrowStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return throwToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + + // attributes + ExpressionNode *expression; + SourceLocation throwToken; + SourceLocation semicolonToken; +}; + +class Catch: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Catch) + + Catch(NameId *n, Block *stmt): + name (n), statement (stmt) + { kind = K; } + + virtual ~Catch() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *name; + Block *statement; + SourceLocation catchToken; + SourceLocation lparenToken; + SourceLocation identifierToken; + SourceLocation rparenToken; +}; + +class Finally: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Finally) + + Finally(Block *stmt): + statement (stmt) + { kind = K; } + + virtual ~Finally() {} + + virtual void accept0(Visitor *visitor); + +// attributes + Block *statement; + SourceLocation finallyToken; +}; + +class TryStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(TryStatement) + + TryStatement(Statement *stmt, Catch *c, Finally *f): + statement (stmt), catchExpression (c), finallyExpression (f) + { kind = K; } + + TryStatement(Statement *stmt, Finally *f): + statement (stmt), catchExpression (0), finallyExpression (f) + { kind = K; } + + TryStatement(Statement *stmt, Catch *c): + statement (stmt), catchExpression (c), finallyExpression (0) + { kind = K; } + + virtual ~TryStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return tryToken; } + + virtual SourceLocation lastSourceLocation() const + { + if (finallyExpression) + return finallyExpression->statement->rbraceToken; + else if (catchExpression) + return catchExpression->statement->rbraceToken; + + return statement->lastSourceLocation(); + } + +// attributes + Statement *statement; + Catch *catchExpression; + Finally *finallyExpression; + SourceLocation tryToken; +}; + +class FunctionExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionExpression) + + FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b): + name (n), formals (f), body (b) + { kind = K; } + + virtual ~FunctionExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return functionToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbraceToken; } + +// attributes + NameId *name; + FormalParameterList *formals; + FunctionBody *body; + SourceLocation functionToken; + SourceLocation identifierToken; + SourceLocation lparenToken; + SourceLocation rparenToken; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class FunctionDeclaration: public FunctionExpression +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionDeclaration) + + FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b): + FunctionExpression(n, f, b) + { kind = K; } + + virtual ~FunctionDeclaration() {} + + virtual void accept0(Visitor *visitor); +}; + +class FormalParameterList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(FormalParameterList) + + FormalParameterList(NameId *n): + name (n), next (this) + { kind = K; } + + FormalParameterList(FormalParameterList *previous, NameId *n): + name (n) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~FormalParameterList() {} + + virtual void accept0(Visitor *visitor); + + inline FormalParameterList *finish () + { + FormalParameterList *front = next; + next = 0; + return front; + } + +// attributes + NameId *name; + FormalParameterList *next; + SourceLocation commaToken; + SourceLocation identifierToken; +}; + +class FunctionBody: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionBody) + + FunctionBody(SourceElements *elts): + elements (elts) + { kind = K; } + + virtual ~FunctionBody() {} + + virtual void accept0(Visitor *visitor); + +// attributes + SourceElements *elements; +}; + +class Program: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Program) + + Program(SourceElements *elts): + elements (elts) + { kind = K; } + + virtual ~Program() {} + + virtual void accept0(Visitor *visitor); + +// attributes + SourceElements *elements; +}; + +class SourceElements: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(SourceElements) + + SourceElements(SourceElement *elt): + element (elt), next (this) + { kind = K; } + + SourceElements(SourceElements *previous, SourceElement *elt): + element (elt) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~SourceElements() {} + + virtual void accept0(Visitor *visitor); + + inline SourceElements *finish () + { + SourceElements *front = next; + next = 0; + return front; + } + +// attributes + SourceElement *element; + SourceElements *next; +}; + +class SourceElement: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(SourceElement) + + inline SourceElement() + { kind = K; } + + virtual ~SourceElement() {} +}; + +class FunctionSourceElement: public SourceElement +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionSourceElement) + + FunctionSourceElement(FunctionDeclaration *f): + declaration (f) + { kind = K; } + + virtual ~FunctionSourceElement() {} + + virtual void accept0(Visitor *visitor); + +// attributes + FunctionDeclaration *declaration; +}; + +class StatementSourceElement: public SourceElement +{ +public: + QMLJS_DECLARE_AST_NODE(StatementSourceElement) + + StatementSourceElement(Statement *stmt): + statement (stmt) + { kind = K; } + + virtual ~StatementSourceElement() {} + + virtual void accept0(Visitor *visitor); + +// attributes + Statement *statement; +}; + +class DebuggerStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(DebuggerStatement) + + DebuggerStatement() + { kind = K; } + + virtual ~DebuggerStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return debuggerToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + SourceLocation debuggerToken; + SourceLocation semicolonToken; +}; + +class UiProgram: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiProgram) + + UiProgram(UiImportList *imports, UiObjectMemberList *members) + : imports(imports), members(members) + { kind = K; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiImportList *imports; + UiObjectMemberList *members; +}; + +class UiQualifiedId: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiQualifiedId) + + UiQualifiedId(NameId *name) + : next(this), name(name) + { kind = K; } + + UiQualifiedId(UiQualifiedId *previous, NameId *name) + : name(name) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~UiQualifiedId() {} + + UiQualifiedId *finish() + { + UiQualifiedId *head = next; + next = 0; + return head; + } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *next; + NameId *name; + SourceLocation identifierToken; +}; + +class UiImport: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiImport) + + UiImport(NameId *fileName) + : fileName(fileName) + { kind = K; } + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *fileName; + SourceLocation importToken; + SourceLocation fileNameToken; + SourceLocation semicolonToken; +}; + +class UiImportList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiImportList) + + UiImportList(UiImport *import) + : import(import), + next(this) + { kind = K; } + + UiImportList(UiImportList *previous, UiImport *import) + : import(import) + { + kind = K; + next = previous->next; + previous->next = this; + } + + UiImportList *finish() + { + UiImportList *head = next; + next = 0; + return head; + } + + virtual void accept0(Visitor *visitor); + +// attributes + UiImport *import; + UiImportList *next; +}; + +class UiObjectMember: public Node +{ +public: + virtual SourceLocation firstSourceLocation() const = 0; + virtual SourceLocation lastSourceLocation() const = 0; +}; + +class UiObjectMemberList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectMemberList) + + UiObjectMemberList(UiObjectMember *member) + : next(this), member(member) + { kind = K; } + + UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member) + : member(member) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual void accept0(Visitor *visitor); + + UiObjectMemberList *finish() + { + UiObjectMemberList *head = next; + next = 0; + return head; + } + +// attributes + UiObjectMemberList *next; + UiObjectMember *member; +}; + +class UiArrayMemberList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiArrayMemberList) + + UiArrayMemberList(UiObjectMember *member) + : next(this), member(member) + { kind = K; } + + UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member) + : member(member) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual void accept0(Visitor *visitor); + + UiArrayMemberList *finish() + { + UiArrayMemberList *head = next; + next = 0; + return head; + } + +// attributes + UiArrayMemberList *next; + UiObjectMember *member; + SourceLocation commaToken; +}; + +class UiObjectInitializer: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectInitializer) + + UiObjectInitializer(UiObjectMemberList *members) + : members(members) + { kind = K; } + + virtual void accept0(Visitor *visitor); + +// attributes + SourceLocation lbraceToken; + UiObjectMemberList *members; + SourceLocation rbraceToken; +}; + +class UiPublicMember: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiPublicMember) + + UiPublicMember(NameId *memberType, + NameId *name) + : type(Property), memberType(memberType), name(name), expression(0), isDefaultMember(false) + { kind = K; } + + UiPublicMember(NameId *memberType, + NameId *name, + ExpressionNode *expression) + : type(Property), memberType(memberType), name(name), expression(expression), isDefaultMember(false) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { + if (defaultToken.isValid()) + return defaultToken; + + return propertyToken; + } + + virtual SourceLocation lastSourceLocation() const + { + return semicolonToken; + } + + virtual void accept0(Visitor *visitor); + +// attributes + enum { Signal, Property } type; + NameId *memberType; + NameId *name; + ExpressionNode *expression; + bool isDefaultMember; + SourceLocation defaultToken; + SourceLocation propertyToken; + SourceLocation typeToken; + SourceLocation identifierToken; + SourceLocation colonToken; + SourceLocation semicolonToken; +}; + +class UiObjectDefinition: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectDefinition) + + UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId, + UiObjectInitializer *initializer) + : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return qualifiedTypeNameId->identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return initializer->rbraceToken; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedTypeNameId; + UiObjectInitializer *initializer; +}; + +class UiSourceElement: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiSourceElement) + + UiSourceElement(Node *sourceElement) + : sourceElement(sourceElement) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { + if (FunctionDeclaration *funDecl = cast(sourceElement)) + return funDecl->firstSourceLocation(); + else if (VariableStatement *varStmt = cast(sourceElement)) + return varStmt->firstSourceLocation(); + + return SourceLocation(); + } + + virtual SourceLocation lastSourceLocation() const + { + if (FunctionDeclaration *funDecl = cast(sourceElement)) + return funDecl->lastSourceLocation(); + else if (VariableStatement *varStmt = cast(sourceElement)) + return varStmt->lastSourceLocation(); + + return SourceLocation(); + } + + + virtual void accept0(Visitor *visitor); + +// attributes + Node *sourceElement; +}; + +class UiObjectBinding: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectBinding) + + UiObjectBinding(UiQualifiedId *qualifiedId, + UiQualifiedId *qualifiedTypeNameId, + UiObjectInitializer *initializer) + : qualifiedId(qualifiedId), + qualifiedTypeNameId(qualifiedTypeNameId), + initializer(initializer) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return qualifiedId->identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return initializer->rbraceToken; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedId; + UiQualifiedId *qualifiedTypeNameId; + UiObjectInitializer *initializer; + SourceLocation colonToken; +}; + +class UiScriptBinding: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiScriptBinding) + + UiScriptBinding(UiQualifiedId *qualifiedId, + Statement *statement) + : qualifiedId(qualifiedId), + statement(statement) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return qualifiedId->identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedId; + Statement *statement; + SourceLocation colonToken; +}; + +class UiArrayBinding: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiArrayBinding) + + UiArrayBinding(UiQualifiedId *qualifiedId, + UiArrayMemberList *members) + : qualifiedId(qualifiedId), + members(members) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return lbracketToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbracketToken; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedId; + UiArrayMemberList *members; + SourceLocation colonToken; + SourceLocation lbracketToken; + SourceLocation rbracketToken; +}; + +} } // namespace AST + + + +QT_END_NAMESPACE + +#endif diff --git a/src/declarative/qml/parser/qmljsastfwd_p.h b/src/declarative/qml/parser/qmljsastfwd_p.h new file mode 100644 index 0000000..339bea4 --- /dev/null +++ b/src/declarative/qml/parser/qmljsastfwd_p.h @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 QMLJSAST_FWD_P_H +#define QMLJSAST_FWD_P_H + +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +class SourceLocation +{ +public: + SourceLocation(quint32 offset = 0, quint32 length = 0) + : offset(offset), length(length), + startLine(0), startColumn(0) + { } + + bool isValid() const { return length != 0; } + + quint32 begin() const { return offset; } + quint32 end() const { return offset + length; } + +// attributes + // ### encode + quint32 offset; + quint32 length; + quint32 startLine; + quint32 startColumn; +}; + +class Visitor; +class Node; +class ExpressionNode; +class Statement; +class ThisExpression; +class IdentifierExpression; +class NullExpression; +class TrueLiteral; +class FalseLiteral; +class NumericLiteral; +class StringLiteral; +class RegExpLiteral; +class ArrayLiteral; +class ObjectLiteral; +class ElementList; +class Elision; +class PropertyNameAndValueList; +class PropertyName; +class IdentifierPropertyName; +class StringLiteralPropertyName; +class NumericLiteralPropertyName; +class ArrayMemberExpression; +class FieldMemberExpression; +class NewMemberExpression; +class NewExpression; +class CallExpression; +class ArgumentList; +class PostIncrementExpression; +class PostDecrementExpression; +class DeleteExpression; +class VoidExpression; +class TypeOfExpression; +class PreIncrementExpression; +class PreDecrementExpression; +class UnaryPlusExpression; +class UnaryMinusExpression; +class TildeExpression; +class NotExpression; +class BinaryExpression; +class ConditionalExpression; +class Expression; // ### rename +class Block; +class StatementList; +class VariableStatement; +class VariableDeclarationList; +class VariableDeclaration; +class EmptyStatement; +class ExpressionStatement; +class IfStatement; +class DoWhileStatement; +class WhileStatement; +class ForStatement; +class LocalForStatement; +class ForEachStatement; +class LocalForEachStatement; +class ContinueStatement; +class BreakStatement; +class ReturnStatement; +class WithStatement; +class SwitchStatement; +class CaseBlock; +class CaseClauses; +class CaseClause; +class DefaultClause; +class LabelledStatement; +class ThrowStatement; +class TryStatement; +class Catch; +class Finally; +class FunctionDeclaration; +class FunctionExpression; +class FormalParameterList; +class FunctionBody; +class Program; +class SourceElements; +class SourceElement; +class FunctionSourceElement; +class StatementSourceElement; +class DebuggerStatement; +class NestedExpression; + +// ui elements +class UiProgram; +class UiImportList; +class UiImport; +class UiPublicMember; +class UiObjectDefinition; +class UiObjectInitializer; +class UiObjectBinding; +class UiScriptBinding; +class UiSourceElement; +class UiArrayBinding; +class UiObjectMember; +class UiObjectMemberList; +class UiArrayMemberList; +class UiQualifiedId; + +} } // namespace AST + +QT_END_NAMESPACE + +#endif diff --git a/src/declarative/qml/parser/qmljsastvisitor.cpp b/src/declarative/qml/parser/qmljsastvisitor.cpp new file mode 100644 index 0000000..642bcee --- /dev/null +++ b/src/declarative/qml/parser/qmljsastvisitor.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 "qmljsastvisitor_p.h" + +QT_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +Visitor::Visitor() +{ +} + +Visitor::~Visitor() +{ +} + +} } // namespace QmlJS::AST + +QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/qmljsastvisitor_p.h b/src/declarative/qml/parser/qmljsastvisitor_p.h new file mode 100644 index 0000000..3677b1a --- /dev/null +++ b/src/declarative/qml/parser/qmljsastvisitor_p.h @@ -0,0 +1,328 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 QMLJSASTVISITOR_P_H +#define QMLJSASTVISITOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qmljsastfwd_p.h" + +QT_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +class Visitor +{ +public: + Visitor(); + virtual ~Visitor(); + + virtual bool preVisit(Node *) { return true; } + virtual void postVisit(Node *) {} + + // Ui + virtual bool visit(UiProgram *) { return true; } + virtual bool visit(UiImportList *) { return true; } + virtual bool visit(UiImport *) { return true; } + virtual bool visit(UiPublicMember *) { return true; } + virtual bool visit(UiSourceElement *) { return true; } + virtual bool visit(UiObjectDefinition *) { return true; } + virtual bool visit(UiObjectInitializer *) { return true; } + virtual bool visit(UiObjectBinding *) { return true; } + virtual bool visit(UiScriptBinding *) { return true; } + virtual bool visit(UiArrayBinding *) { return true; } + virtual bool visit(UiObjectMemberList *) { return true; } + virtual bool visit(UiArrayMemberList *) { return true; } + virtual bool visit(UiQualifiedId *) { return true; } + + virtual void endVisit(UiProgram *) {} + virtual void endVisit(UiImportList *) {} + virtual void endVisit(UiImport *) {} + virtual void endVisit(UiPublicMember *) {} + virtual void endVisit(UiSourceElement *) {} + virtual void endVisit(UiObjectDefinition *) {} + virtual void endVisit(UiObjectInitializer *) {} + virtual void endVisit(UiObjectBinding *) {} + virtual void endVisit(UiScriptBinding *) {} + virtual void endVisit(UiArrayBinding *) {} + virtual void endVisit(UiObjectMemberList *) {} + virtual void endVisit(UiArrayMemberList *) {} + virtual void endVisit(UiQualifiedId *) {} + + // QmlJS + virtual bool visit(ThisExpression *) { return true; } + virtual void endVisit(ThisExpression *) {} + + virtual bool visit(IdentifierExpression *) { return true; } + virtual void endVisit(IdentifierExpression *) {} + + virtual bool visit(NullExpression *) { return true; } + virtual void endVisit(NullExpression *) {} + + virtual bool visit(TrueLiteral *) { return true; } + virtual void endVisit(TrueLiteral *) {} + + virtual bool visit(FalseLiteral *) { return true; } + virtual void endVisit(FalseLiteral *) {} + + virtual bool visit(StringLiteral *) { return true; } + virtual void endVisit(StringLiteral *) {} + + virtual bool visit(NumericLiteral *) { return true; } + virtual void endVisit(NumericLiteral *) {} + + virtual bool visit(RegExpLiteral *) { return true; } + virtual void endVisit(RegExpLiteral *) {} + + virtual bool visit(ArrayLiteral *) { return true; } + virtual void endVisit(ArrayLiteral *) {} + + virtual bool visit(ObjectLiteral *) { return true; } + virtual void endVisit(ObjectLiteral *) {} + + virtual bool visit(ElementList *) { return true; } + virtual void endVisit(ElementList *) {} + + virtual bool visit(Elision *) { return true; } + virtual void endVisit(Elision *) {} + + virtual bool visit(PropertyNameAndValueList *) { return true; } + virtual void endVisit(PropertyNameAndValueList *) {} + + virtual bool visit(NestedExpression *) { return true; } + virtual void endVisit(NestedExpression *) {} + + virtual bool visit(IdentifierPropertyName *) { return true; } + virtual void endVisit(IdentifierPropertyName *) {} + + virtual bool visit(StringLiteralPropertyName *) { return true; } + virtual void endVisit(StringLiteralPropertyName *) {} + + virtual bool visit(NumericLiteralPropertyName *) { return true; } + virtual void endVisit(NumericLiteralPropertyName *) {} + + virtual bool visit(ArrayMemberExpression *) { return true; } + virtual void endVisit(ArrayMemberExpression *) {} + + virtual bool visit(FieldMemberExpression *) { return true; } + virtual void endVisit(FieldMemberExpression *) {} + + virtual bool visit(NewMemberExpression *) { return true; } + virtual void endVisit(NewMemberExpression *) {} + + virtual bool visit(NewExpression *) { return true; } + virtual void endVisit(NewExpression *) {} + + virtual bool visit(CallExpression *) { return true; } + virtual void endVisit(CallExpression *) {} + + virtual bool visit(ArgumentList *) { return true; } + virtual void endVisit(ArgumentList *) {} + + virtual bool visit(PostIncrementExpression *) { return true; } + virtual void endVisit(PostIncrementExpression *) {} + + virtual bool visit(PostDecrementExpression *) { return true; } + virtual void endVisit(PostDecrementExpression *) {} + + virtual bool visit(DeleteExpression *) { return true; } + virtual void endVisit(DeleteExpression *) {} + + virtual bool visit(VoidExpression *) { return true; } + virtual void endVisit(VoidExpression *) {} + + virtual bool visit(TypeOfExpression *) { return true; } + virtual void endVisit(TypeOfExpression *) {} + + virtual bool visit(PreIncrementExpression *) { return true; } + virtual void endVisit(PreIncrementExpression *) {} + + virtual bool visit(PreDecrementExpression *) { return true; } + virtual void endVisit(PreDecrementExpression *) {} + + virtual bool visit(UnaryPlusExpression *) { return true; } + virtual void endVisit(UnaryPlusExpression *) {} + + virtual bool visit(UnaryMinusExpression *) { return true; } + virtual void endVisit(UnaryMinusExpression *) {} + + virtual bool visit(TildeExpression *) { return true; } + virtual void endVisit(TildeExpression *) {} + + virtual bool visit(NotExpression *) { return true; } + virtual void endVisit(NotExpression *) {} + + virtual bool visit(BinaryExpression *) { return true; } + virtual void endVisit(BinaryExpression *) {} + + virtual bool visit(ConditionalExpression *) { return true; } + virtual void endVisit(ConditionalExpression *) {} + + virtual bool visit(Expression *) { return true; } + virtual void endVisit(Expression *) {} + + virtual bool visit(Block *) { return true; } + virtual void endVisit(Block *) {} + + virtual bool visit(StatementList *) { return true; } + virtual void endVisit(StatementList *) {} + + virtual bool visit(VariableStatement *) { return true; } + virtual void endVisit(VariableStatement *) {} + + virtual bool visit(VariableDeclarationList *) { return true; } + virtual void endVisit(VariableDeclarationList *) {} + + virtual bool visit(VariableDeclaration *) { return true; } + virtual void endVisit(VariableDeclaration *) {} + + virtual bool visit(EmptyStatement *) { return true; } + virtual void endVisit(EmptyStatement *) {} + + virtual bool visit(ExpressionStatement *) { return true; } + virtual void endVisit(ExpressionStatement *) {} + + virtual bool visit(IfStatement *) { return true; } + virtual void endVisit(IfStatement *) {} + + virtual bool visit(DoWhileStatement *) { return true; } + virtual void endVisit(DoWhileStatement *) {} + + virtual bool visit(WhileStatement *) { return true; } + virtual void endVisit(WhileStatement *) {} + + virtual bool visit(ForStatement *) { return true; } + virtual void endVisit(ForStatement *) {} + + virtual bool visit(LocalForStatement *) { return true; } + virtual void endVisit(LocalForStatement *) {} + + virtual bool visit(ForEachStatement *) { return true; } + virtual void endVisit(ForEachStatement *) {} + + virtual bool visit(LocalForEachStatement *) { return true; } + virtual void endVisit(LocalForEachStatement *) {} + + virtual bool visit(ContinueStatement *) { return true; } + virtual void endVisit(ContinueStatement *) {} + + virtual bool visit(BreakStatement *) { return true; } + virtual void endVisit(BreakStatement *) {} + + virtual bool visit(ReturnStatement *) { return true; } + virtual void endVisit(ReturnStatement *) {} + + virtual bool visit(WithStatement *) { return true; } + virtual void endVisit(WithStatement *) {} + + virtual bool visit(SwitchStatement *) { return true; } + virtual void endVisit(SwitchStatement *) {} + + virtual bool visit(CaseBlock *) { return true; } + virtual void endVisit(CaseBlock *) {} + + virtual bool visit(CaseClauses *) { return true; } + virtual void endVisit(CaseClauses *) {} + + virtual bool visit(CaseClause *) { return true; } + virtual void endVisit(CaseClause *) {} + + virtual bool visit(DefaultClause *) { return true; } + virtual void endVisit(DefaultClause *) {} + + virtual bool visit(LabelledStatement *) { return true; } + virtual void endVisit(LabelledStatement *) {} + + virtual bool visit(ThrowStatement *) { return true; } + virtual void endVisit(ThrowStatement *) {} + + virtual bool visit(TryStatement *) { return true; } + virtual void endVisit(TryStatement *) {} + + virtual bool visit(Catch *) { return true; } + virtual void endVisit(Catch *) {} + + virtual bool visit(Finally *) { return true; } + virtual void endVisit(Finally *) {} + + virtual bool visit(FunctionDeclaration *) { return true; } + virtual void endVisit(FunctionDeclaration *) {} + + virtual bool visit(FunctionExpression *) { return true; } + virtual void endVisit(FunctionExpression *) {} + + virtual bool visit(FormalParameterList *) { return true; } + virtual void endVisit(FormalParameterList *) {} + + virtual bool visit(FunctionBody *) { return true; } + virtual void endVisit(FunctionBody *) {} + + virtual bool visit(Program *) { return true; } + virtual void endVisit(Program *) {} + + virtual bool visit(SourceElements *) { return true; } + virtual void endVisit(SourceElements *) {} + + virtual bool visit(FunctionSourceElement *) { return true; } + virtual void endVisit(FunctionSourceElement *) {} + + virtual bool visit(StatementSourceElement *) { return true; } + virtual void endVisit(StatementSourceElement *) {} + + virtual bool visit(DebuggerStatement *) { return true; } + virtual void endVisit(DebuggerStatement *) {} +}; + +} } // namespace AST + +QT_END_NAMESPACE + +#endif // QMLJSASTVISITOR_P_H diff --git a/src/declarative/qml/parser/qmljsengine_p.cpp b/src/declarative/qml/parser/qmljsengine_p.cpp new file mode 100644 index 0000000..42885d8 --- /dev/null +++ b/src/declarative/qml/parser/qmljsengine_p.cpp @@ -0,0 +1,191 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "qmljsengine_p.h" +#include "qmljsnodepool_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QmlJS { + +uint qHash(const QmlJS::NameId &id) +{ return qHash(id.asString()); } + +QString numberToString(double value) +{ return QString::number(value); } + +int Ecma::RegExp::flagFromChar(const QChar &ch) +{ + static QHash flagsHash; + if (flagsHash.isEmpty()) { + flagsHash[QLatin1Char('g')] = Global; + flagsHash[QLatin1Char('i')] = IgnoreCase; + flagsHash[QLatin1Char('m')] = Multiline; + } + QHash::const_iterator it; + it = flagsHash.constFind(ch); + if (it == flagsHash.constEnd()) + return 0; + return it.value(); +} + +QString Ecma::RegExp::flagsToString(int flags) +{ + QString result; + if (flags & Global) + result += QLatin1Char('g'); + if (flags & IgnoreCase) + result += QLatin1Char('i'); + if (flags & Multiline) + result += QLatin1Char('m'); + return result; +} + +NodePool::NodePool(const QString &fileName, Engine *engine) + : m_fileName(fileName), m_engine(engine) +{ + m_engine->setNodePool(this); +} + +NodePool::~NodePool() +{ +} + +Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &) +{ + Q_ASSERT(0); + return 0; +} + +static int toDigit(char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + else if ((c >= 'a') && (c <= 'z')) + return 10 + c - 'a'; + else if ((c >= 'A') && (c <= 'Z')) + return 10 + c - 'A'; + return -1; +} + +double integerFromString(const char *buf, int size, int radix) +{ + if (size == 0) + return qSNaN(); + + double sign = 1.0; + int i = 0; + if (buf[0] == '+') { + ++i; + } else if (buf[0] == '-') { + sign = -1.0; + ++i; + } + + if (((size-i) >= 2) && (buf[i] == '0')) { + if (((buf[i+1] == 'x') || (buf[i+1] == 'X')) + && (radix < 34)) { + if ((radix != 0) && (radix != 16)) + return 0; + radix = 16; + i += 2; + } else { + if (radix == 0) { + radix = 8; + ++i; + } + } + } else if (radix == 0) { + radix = 10; + } + + int j = i; + for ( ; i < size; ++i) { + int d = toDigit(buf[i]); + if ((d == -1) || (d >= radix)) + break; + } + double result; + if (j == i) { + if (!qstrcmp(buf, "Infinity")) + result = qInf(); + else + result = qSNaN(); + } else { + result = 0; + double multiplier = 1; + for (--i ; i >= j; --i, multiplier *= radix) + result += toDigit(buf[i]) * multiplier; + } + result *= sign; + return result; +} + +double integerFromString(const QString &str, int radix) +{ + QByteArray ba = str.trimmed().toUtf8(); + return integerFromString(ba.constData(), ba.size(), radix); +} + + +Engine::Engine() + : _lexer(0), _nodePool(0) +{ } + +Engine::~Engine() +{ } + +QSet Engine::literals() const +{ return _literals; } + +NameId *Engine::intern(const QChar *u, int s) +{ return const_cast(&*_literals.insert(NameId(u, s))); } + +QString Engine::toString(NameId *id) +{ return id->asString(); } + +Lexer *Engine::lexer() const +{ return _lexer; } + +void Engine::setLexer(Lexer *lexer) +{ _lexer = lexer; } + +NodePool *Engine::nodePool() const +{ return _nodePool; } + +void Engine::setNodePool(NodePool *nodePool) +{ _nodePool = nodePool; } + + + +} // end of namespace QmlJS + +QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/qmljsengine_p.h b/src/declarative/qml/parser/qmljsengine_p.h new file mode 100644 index 0000000..b9ff042 --- /dev/null +++ b/src/declarative/qml/parser/qmljsengine_p.h @@ -0,0 +1,145 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef QMLJSENGINE_P_H +#define QMLJSENGINE_P_H + +#include +#include + +#include "qmljsastfwd_p.h" + +QT_BEGIN_NAMESPACE + +namespace QmlJS { +class NameId +{ + QString _text; + +public: + NameId(const QChar *u, int s) + : _text(u, s) + { } + + const QString asString() const + { return _text; } + + bool operator == (const NameId &other) const + { return _text == other._text; } + + bool operator != (const NameId &other) const + { return _text != other._text; } + + bool operator < (const NameId &other) const + { return _text < other._text; } +}; + +uint qHash(const QmlJS::NameId &id); + +} // end of namespace QmlJS + +#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 +//this ensures that code outside QmlJS can use the hash function +//it also a workaround for some compilers +inline uint qHash(const QmlJS::NameId &nameId) { return QmlJS::qHash(nameId); } +#endif + +namespace QmlJS { + +class Lexer; +class NodePool; + +namespace Ecma { + +class RegExp +{ +public: + enum RegExpFlag { + Global = 0x01, + IgnoreCase = 0x02, + Multiline = 0x04 + }; + +public: + static int flagFromChar(const QChar &); + static QString flagsToString(int flags); +}; + +} // end of namespace Ecma + +class DiagnosticMessage +{ +public: + enum Kind { Warning, Error }; + + DiagnosticMessage() + : kind(Error) {} + + DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) + : kind(kind), loc(loc), message(message) {} + + bool isWarning() const + { return kind == Warning; } + + bool isError() const + { return kind == Error; } + + Kind kind; + AST::SourceLocation loc; + QString message; +}; + +class Engine +{ + Lexer *_lexer; + NodePool *_nodePool; + QSet _literals; + +public: + Engine(); + ~Engine(); + + QSet literals() const; + + NameId *intern(const QChar *u, int s); + + static QString toString(NameId *id); + + Lexer *lexer() const; + void setLexer(Lexer *lexer); + + NodePool *nodePool() const; + void setNodePool(NodePool *nodePool); +}; + +} // end of namespace QmlJS + +QT_END_NAMESPACE + +#endif // QMLJSENGINE_P_H diff --git a/src/declarative/qml/parser/qmljsgrammar.cpp b/src/declarative/qml/parser/qmljsgrammar.cpp new file mode 100644 index 0000000..835ee44 --- /dev/null +++ b/src/declarative/qml/parser/qmljsgrammar.cpp @@ -0,0 +1,829 @@ +// This file was generated by qlalr - DO NOT EDIT! +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module 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 "qmljsgrammar_p.h" + +const char *const QmlJSGrammar::spell [] = { + "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue", + "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", + "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier", + "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=", + "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=", + "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return", + ")", ";", 0, "*", "*=", "string literal", "property", "signal", "switch", "this", + "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=", + "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "public", "import", 0, + 0}; + +const int QmlJSGrammar::lhs [] = { + 91, 92, 92, 95, 95, 96, 96, 94, 93, 98, + 98, 100, 100, 101, 101, 97, 99, 99, 103, 104, + 104, 99, 99, 99, 99, 99, 99, 99, 111, 111, + 111, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 102, 102, 114, 114, 114, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 102, 102, 117, 117, 117, 117, + 116, 116, 119, 119, 121, 121, 121, 121, 121, 121, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 123, 123, 124, 124, 124, 124, 124, 127, 127, + 128, 128, 128, 128, 126, 126, 129, 129, 130, 130, + 131, 131, 131, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, + 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, + 136, 137, 137, 137, 137, 137, 137, 138, 138, 138, + 138, 138, 139, 139, 139, 139, 139, 140, 140, 141, + 141, 142, 142, 143, 143, 144, 144, 145, 145, 146, + 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, + 151, 120, 120, 152, 152, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 105, 105, 154, + 154, 155, 155, 156, 156, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 106, 168, 168, 167, 167, 113, 113, 169, 169, 170, + 170, 172, 172, 171, 173, 176, 174, 174, 177, 175, + 175, 107, 108, 108, 110, 110, 158, 158, 158, 158, + 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, + 160, 161, 161, 162, 164, 178, 178, 181, 181, 179, + 179, 182, 180, 163, 163, 163, 165, 165, 166, 166, + 166, 183, 184, 109, 109, 112, 125, 188, 188, 185, + 185, 186, 186, 189, 190, 190, 191, 191, 187, 187, + 118, 118, 192}; + +const int QmlJSGrammar:: rhs[] = { + 2, 1, 1, 1, 2, 3, 3, 0, 1, 1, + 2, 1, 3, 2, 3, 2, 1, 5, 1, 2, + 2, 4, 3, 3, 3, 3, 3, 3, 1, 1, + 1, 2, 4, 4, 5, 5, 6, 6, 7, 7, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, + 5, 3, 4, 3, 1, 3, 1, 2, 3, 4, + 1, 2, 3, 5, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 4, 3, 5, 1, 2, + 4, 4, 4, 3, 0, 1, 1, 3, 1, 1, + 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, + 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, + 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, + 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, + 5, 1, 3, 1, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, + 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 2, 0, 1, 3, 3, 1, 1, 1, + 3, 1, 3, 2, 2, 2, 0, 1, 2, 0, + 1, 1, 2, 2, 7, 5, 7, 7, 5, 9, + 10, 7, 8, 2, 2, 3, 3, 2, 2, 3, + 3, 3, 3, 5, 5, 3, 5, 1, 2, 0, + 1, 4, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 5, 2, 2, 2, 8, 8, 1, 3, 0, + 1, 0, 1, 1, 1, 2, 1, 1, 0, 1, + 0, 1, 2}; + +const int QmlJSGrammar::action_default [] = { + 8, 2, 0, 4, 3, 0, 0, 0, 6, 7, + 5, 65, 45, 46, 43, 44, 47, 9, 0, 1, + 0, 0, 16, 66, 41, 248, 0, 0, 46, 14, + 47, 249, 17, 10, 0, 0, 0, 42, 0, 31, + 30, 29, 0, 0, 35, 0, 36, 151, 218, 182, + 190, 186, 130, 202, 178, 0, 115, 49, 131, 194, + 198, 119, 148, 129, 134, 114, 168, 155, 0, 55, + 56, 52, 319, 321, 0, 0, 0, 0, 0, 0, + 50, 53, 0, 0, 54, 48, 0, 51, 0, 0, + 144, 0, 0, 131, 150, 133, 132, 0, 0, 0, + 146, 147, 145, 149, 0, 179, 0, 0, 0, 0, + 169, 0, 0, 0, 0, 0, 0, 159, 0, 0, + 0, 153, 154, 152, 157, 161, 160, 158, 156, 171, + 170, 172, 0, 187, 0, 183, 0, 0, 125, 112, + 124, 113, 81, 82, 83, 108, 84, 109, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 110, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 111, 0, 0, 123, 219, 126, 0, 127, + 0, 128, 122, 39, 40, 0, 215, 208, 206, 213, + 214, 212, 211, 217, 210, 209, 207, 216, 203, 0, + 191, 0, 0, 195, 0, 0, 199, 0, 0, 125, + 117, 0, 116, 0, 121, 135, 0, 320, 310, 311, + 0, 308, 0, 309, 0, 312, 226, 233, 232, 240, + 228, 0, 229, 313, 0, 318, 230, 231, 236, 234, + 315, 314, 317, 237, 0, 0, 0, 0, 0, 319, + 45, 0, 321, 46, 220, 262, 47, 0, 0, 0, + 0, 0, 238, 239, 227, 235, 263, 264, 307, 316, + 0, 278, 279, 280, 281, 0, 274, 275, 276, 277, + 304, 305, 0, 0, 0, 0, 0, 267, 268, 224, + 222, 184, 192, 188, 204, 180, 225, 0, 131, 196, + 200, 173, 162, 0, 0, 181, 0, 0, 0, 0, + 174, 0, 0, 0, 0, 0, 166, 164, 167, 165, + 163, 176, 175, 177, 0, 189, 0, 185, 0, 223, + 131, 0, 205, 220, 221, 0, 220, 0, 0, 270, + 0, 0, 0, 272, 0, 193, 0, 0, 197, 0, + 0, 201, 260, 0, 252, 261, 255, 0, 259, 0, + 220, 253, 0, 220, 0, 0, 271, 0, 0, 0, + 273, 320, 310, 0, 0, 312, 0, 306, 0, 296, + 0, 0, 0, 266, 0, 265, 0, 322, 0, 80, + 242, 245, 0, 81, 248, 84, 109, 86, 87, 52, + 91, 92, 45, 93, 96, 50, 53, 46, 220, 47, + 54, 99, 48, 101, 51, 103, 104, 249, 106, 107, + 111, 0, 73, 0, 0, 75, 79, 77, 63, 76, + 78, 0, 74, 62, 243, 241, 119, 120, 125, 0, + 118, 0, 295, 0, 282, 283, 0, 294, 0, 0, + 0, 285, 290, 288, 291, 0, 0, 289, 290, 0, + 286, 0, 287, 244, 293, 0, 244, 292, 0, 297, + 298, 0, 244, 299, 300, 0, 0, 301, 0, 0, + 0, 302, 303, 137, 136, 0, 0, 0, 269, 0, + 0, 0, 284, 67, 0, 0, 71, 57, 0, 59, + 69, 0, 60, 70, 72, 61, 68, 58, 0, 64, + 141, 139, 143, 140, 138, 142, 0, 0, 0, 33, + 0, 34, 0, 37, 38, 32, 15, 11, 0, 23, + 26, 24, 0, 25, 28, 244, 0, 19, 0, 27, + 22, 81, 248, 84, 109, 86, 87, 52, 91, 92, + 45, 93, 96, 50, 53, 46, 220, 47, 54, 99, + 48, 101, 51, 103, 104, 249, 106, 107, 111, 49, + 0, 12, 0, 18, 13, 20, 21, 257, 250, 0, + 258, 254, 0, 256, 246, 0, 247, 251, 323}; + +const int QmlJSGrammar::goto_default [] = { + 6, 5, 19, 1, 4, 3, 32, 34, 33, 570, + 22, 18, 538, 539, 231, 226, 230, 232, 229, 236, + 517, 235, 264, 57, 65, 495, 494, 388, 387, 48, + 386, 389, 140, 61, 56, 178, 63, 52, 177, 58, + 64, 90, 62, 47, 67, 66, 301, 54, 295, 49, + 291, 51, 293, 50, 292, 59, 299, 60, 300, 53, + 294, 290, 331, 443, 296, 297, 390, 237, 228, 227, + 239, 265, 238, 243, 262, 263, 392, 391, 36, 579, + 578, 353, 354, 581, 356, 580, 355, 451, 455, 458, + 454, 453, 473, 474, 220, 234, 216, 219, 233, 241, + 240, 0}; + +const int QmlJSGrammar::action_index [] = { + 8, -91, 14, -91, -15, 296, 67, 94, -91, -91, + -91, -91, -91, -91, -91, -91, -91, -91, 109, -91, + 184, 408, -91, -91, -91, -91, 45, 125, 170, -91, + 46, -91, -91, -91, 429, 171, 130, -91, 120, -91, + -91, -91, -19, 169, -91, 733, -91, 72, -91, 22, + -26, -59, 173, -91, 278, 174, -91, -91, 574, 51, + 112, 183, 177, -91, -91, -91, 412, 214, 733, -91, + -91, -91, 161, 1566, 980, 733, 733, 733, 653, 733, + -91, -91, 733, 733, -91, -91, 733, -91, 733, 733, + -91, 733, 733, 98, 235, -91, -91, 733, 733, 733, + -91, -91, -91, 230, 733, 276, 733, 733, 733, 733, + 396, 733, 733, 733, 733, 733, 733, 288, 733, 733, + 733, 88, 87, 74, 288, 288, 288, 218, 221, 486, + 372, 362, 733, 4, 733, 76, 1479, 733, 733, -91, + -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, + -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, + -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, + -91, -91, -91, 102, 733, -91, -91, 60, 3, -91, + 733, -91, -91, -91, -91, 733, -91, -91, -91, -91, + -91, -91, -91, -91, -91, -91, -91, -91, -91, 733, + -6, 733, 733, 30, 32, 733, -91, 1479, 733, 733, + -91, 107, -91, -14, -91, -91, 69, -91, 191, 49, + 18, -91, 233, -91, 47, 1827, -91, -91, -91, -91, + -91, 204, -91, -91, 39, -91, -91, -91, -91, -91, + -91, 1827, -91, -91, 322, 281, 103, 1740, 50, 203, + 77, 40, 2001, 53, 733, -91, 52, 29, 733, 25, + 28, 35, -91, -91, -91, -91, -91, -91, -91, -91, + 113, -91, -91, -91, -91, 106, -91, -91, -91, -91, + -91, -91, 15, 68, 733, 135, 119, -91, -91, 897, + -91, 82, 58, 17, -91, 261, 84, 42, 494, 91, + 79, 304, 288, 208, 733, 245, 733, 733, 733, 733, + 418, 733, 733, 733, 733, 733, 288, 288, 288, 288, + 288, 343, 336, 279, 733, -57, 733, 19, 733, -91, + 574, 733, -91, 733, -7, -30, 733, -60, 1740, -91, + 733, 111, 1740, -91, 733, 2, 733, 733, 43, 37, + 733, -91, 34, 118, 23, -91, -91, 733, -91, 238, + 733, -91, -5, 733, -17, 1740, -91, 733, 133, 1740, + -91, -9, 194, -32, -8, 1827, -25, -91, 1740, -91, + 733, 100, 1740, 21, 1740, -91, 31, 26, -20, -91, + -91, 1740, -38, 283, 41, 291, 85, 733, 1740, -1, + -34, 252, 54, -27, 653, 9, 5, -91, 817, -91, + 6, -21, 7, 733, 11, -28, 733, 1, 733, -33, + -10, 733, -91, 1653, 33, -91, -91, -91, -91, -91, + -91, 733, -91, -91, -91, -91, 172, -91, 733, -24, + -91, 1740, -91, 73, -91, -91, 1740, -91, 733, 93, + 0, -91, 24, -91, 36, 122, 733, -91, 44, 48, + -91, -3, -91, 1740, -91, 110, 1740, -91, 192, -91, + -91, 124, 1740, 27, -91, -12, -29, -91, 155, -53, + -22, -91, -91, -91, -91, 733, 123, 1740, -91, 733, + 92, 1740, -91, -91, 105, 1229, -91, -91, 1146, -91, + -91, 1063, -91, -91, -91, -91, -91, -91, 90, -91, + -91, -91, -91, -91, -91, -91, 71, 70, 222, -91, + 733, -91, 164, -91, -91, -91, -91, -91, 1392, -91, + -91, -91, 268, -91, -91, 1914, 1312, -91, 75, -91, + -91, 350, 55, 303, 108, 733, 1740, 59, 38, 242, + 62, 40, 527, 63, 81, -91, 817, -91, 138, 29, + 65, 733, 78, 56, 733, 80, 733, 61, 66, 57, + 101, -91, 347, -91, -91, -91, -91, 64, -91, 140, + -91, -91, 733, -91, -91, 144, -91, -91, -91, + + -102, -102, -102, -102, 19, 103, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -4, 249, -102, -102, -102, -102, -102, -7, -102, -102, + -102, -102, -102, -102, 257, -102, -13, -102, -11, -102, + -102, -102, -102, -102, -102, -3, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -44, -102, + -102, -102, -102, -102, -102, -102, -102, -102, 141, -102, + -102, -102, -8, -102, 0, 16, 116, 122, 129, 119, + -102, -102, 90, 64, -102, -102, 94, -102, 91, 86, + -102, 71, 79, -102, -102, -102, -102, 159, 81, 76, + -102, -102, -102, -102, 98, -102, 67, 63, 47, 163, + -102, 160, 115, 104, 105, 127, 133, -102, 151, 144, + 130, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, 145, -102, 152, -102, 162, 31, 21, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, 23, -102, -102, -102, -102, -102, + 29, -102, -102, -102, -102, 34, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, 89, + -102, 68, 36, -102, -102, 42, -102, 235, 46, 49, + -102, -102, -102, -102, -102, -102, -102, -102, 33, -102, + -102, -102, 26, -102, -102, -18, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, 53, -102, -102, 8, 20, -102, -5, -102, 32, + -102, -102, -102, -102, 39, -102, -102, -102, 37, 73, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, 40, -102, -102, -102, -102, 97, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, 41, 213, -102, 186, 199, 203, 209, + -102, 50, 51, 38, 57, 60, -102, -102, -102, -102, + -102, -102, -102, -102, 212, -102, 174, -102, 166, -102, + -102, 168, -102, 125, -102, -102, 61, -102, 1, -102, + 45, -102, -9, -102, 172, -102, 184, 176, -102, -102, + 170, -102, -102, -102, -102, -102, -102, 215, -102, 124, + 132, -102, -102, 178, -102, -29, -102, 25, -102, 2, + -102, -102, 62, -102, -102, 102, -102, -102, -28, -102, + 22, -102, -31, -102, -33, -102, -102, -102, -102, -102, + -102, -34, -102, 17, -102, 18, -102, 111, -20, -102, + -102, 24, -102, -102, 153, -102, -102, -102, 30, -102, + -102, -102, -102, 28, -102, 73, 140, -102, 205, -102, + -102, 5, -102, 44, -102, -102, -102, -102, -102, -102, + -102, 43, -102, -102, -102, -102, -102, -102, 135, -102, + -102, 7, -102, -102, -102, -102, 4, -102, 55, -102, + -102, -102, -102, -102, -25, -102, 48, -102, 9, -102, + -102, -102, -102, -69, -102, -102, -70, -102, -102, -102, + -102, -102, -102, -92, -102, -102, -12, -102, -10, -102, + -1, -102, -102, -102, -102, 11, -102, -40, -102, 14, + -102, -39, -102, -102, -102, -17, -102, -102, 54, -102, + -102, -24, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + 3, -102, -102, -102, -102, -102, -102, -102, 267, -102, + -102, -102, 12, -102, -102, -102, 301, -102, -102, -102, + -102, -19, -102, -15, -102, 59, -64, -102, -102, -2, + -102, -102, 142, -102, -102, -102, -14, -102, -102, -102, + -102, 6, -102, 73, 52, -102, 75, -102, -102, -102, + -102, -102, 128, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -6, -102, -102, 58, -102, -102, -102}; + +const int QmlJSGrammar::action_info [] = { + 338, 174, 289, 485, 472, 472, -89, 480, -105, 380, + 43, 472, -79, -78, -100, 448, -97, 435, -102, 134, + 304, 326, 132, 104, 478, 375, 489, 372, 374, 456, + 377, 336, 199, 452, 423, 433, 440, 384, 421, 205, + 431, 456, 132, 365, 350, 344, 214, 476, -108, 456, + 324, 357, 462, 199, 367, 463, 363, 222, 472, 446, + 441, -75, -108, 182, 485, 448, -89, 588, 180, -75, + -97, 489, -100, 2, 289, 525, 380, 104, 224, 7, + 225, 582, 134, 304, 378, -102, 289, -105, -79, 472, + -65, 283, 328, 344, 268, 326, 2, 485, 174, 518, + 174, 174, 489, 333, 284, 218, 324, 372, 174, 572, + 174, 38, 91, 498, 91, 174, 0, 466, 174, 174, + 0, 0, 0, 92, 20, 92, 359, 91, 91, 346, + 475, 174, 459, 347, 445, 444, 576, 575, 92, 92, + 95, 174, 21, 174, 476, -78, 281, 280, 585, 39, + 509, 96, 491, 450, 12, 9, 8, 573, 175, 12, + 382, 499, 201, 212, 281, 280, 202, 279, 278, 281, + 280, 342, 174, 12, 274, 273, 45, 460, 528, 360, + 288, 287, 174, 487, 12, 0, 20, 207, 136, 97, + 12, 13, 16, 369, 41, 286, 13, 16, 207, 39, + 174, 586, 584, 0, 21, 40, 208, 137, 438, 138, + 13, 16, 174, 12, 0, 0, 0, 208, 0, 209, + 12, 13, 16, 12, 0, 524, 523, 13, 16, 520, + 46, 44, 12, 0, 98, 184, 183, 12, 0, 118, + 99, 119, 97, 118, 41, 119, 118, 97, 119, 0, + 13, 16, 120, 470, 469, 40, 120, 13, 16, 120, + 13, 16, 12, 306, 307, 267, 266, 12, 0, 13, + 16, 12, 0, 0, 13, 16, 174, 0, -319, 306, + 307, 12, 0, 521, 519, 0, 0, 98, -319, 0, + 308, 309, 98, 99, 106, 107, 106, 107, 99, 13, + 16, 21, 311, 312, 13, 16, 308, 309, 13, 16, + 12, 313, 12, 118, 314, 119, 315, 0, 13, 16, + 12, 108, 109, 108, 109, 12, 120, 311, 312, 267, + 266, 0, 12, 0, 0, 0, 313, 0, 0, 314, + 0, 315, 277, 276, 272, 271, 0, 13, 16, 13, + 16, 12, 277, 276, 0, 15, 0, 13, 16, 311, + 312, 0, 13, 16, 277, 276, 311, 312, 313, 13, + 16, 314, 0, 315, 0, 313, 12, 0, 314, 12, + 315, 14, 0, 272, 271, 111, 112, 0, 13, 16, + 0, 0, 0, 113, 114, 111, 112, 115, 0, 116, + 0, 0, 0, 113, 114, 0, 15, 115, 0, 116, + 0, 272, 271, 13, 16, 0, 13, 16, 26, 111, + 112, 0, 0, 0, 0, 0, 0, 113, 114, 0, + 27, 115, 14, 116, 0, 111, 112, 12, 0, 26, + 0, 311, 312, 113, 114, 0, 0, 115, 0, 116, + 313, 27, 0, 314, 0, 315, 0, 0, 12, 0, + 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, + 0, 0, 0, 0, 28, 30, 0, 0, 0, 0, + 0, 0, 31, 0, 526, 0, 0, 0, 15, 0, + 0, 25, 0, 14, 0, 28, 30, 186, 0, 0, + 0, 0, 0, 31, 0, 0, 0, 187, 0, 111, + 112, 188, 25, 0, 14, 0, 0, 113, 114, 0, + 189, 115, 190, 116, 0, 340, 0, 0, 0, 0, + 0, 0, 0, 191, 0, 192, 95, 0, 0, 69, + 70, 0, 0, 193, 0, 0, 194, 96, 0, 72, + 0, 0, 195, 0, 0, 0, 12, 0, 196, 0, + 73, 74, 0, 75, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 197, 81, 0, 0, 186, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 187, 0, 0, + 0, 188, 84, 13, 16, 0, 85, 0, 0, 0, + 189, 0, 190, 0, 0, 0, 0, 80, 87, 71, + 0, 0, 0, 191, 0, 192, 95, 0, 0, 0, + 0, 0, 0, 193, 0, 0, 194, 96, 0, 0, + 0, 0, 195, 0, 0, 0, 0, 0, 196, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, + 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, + 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, + 16, 0, 85, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, + 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, + 81, 0, 0, 0, 82, 0, 83, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, + 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, + 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, + 0, 0, 0, 0, -98, 0, 0, 0, 68, 69, + 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, + 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, + 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, + 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, + 88, 0, 89, 0, 0, 0, 0, 80, 87, 71, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 69, + 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, + 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, + 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, + 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, + 88, 303, 89, 0, 0, 0, 0, 80, 87, 71, + 0, 0, 0, 0, 0, 0, 0, 0, 496, 0, + 0, 68, 69, 70, 0, 0, 0, 0, 0, 0, + 0, 0, 72, 0, 0, 0, 0, 0, 0, 12, + 0, 0, 0, 73, 74, 0, 75, 0, 0, 0, + 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, + 0, 82, 0, 83, 0, 0, 497, 0, 0, 0, + 0, 0, 0, 0, 0, 84, 13, 16, 0, 85, + 0, 86, 0, 88, 0, 89, 0, 0, 0, 0, + 80, 87, 71, 0, 0, 0, 0, 0, 0, 0, + 0, 504, 0, 0, 68, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, + 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, + 81, 0, 0, 0, 82, 0, 83, 0, 0, 505, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, + 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, + 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, + 0, 0, 0, 0, 496, 0, 0, 68, 69, 70, + 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, + 0, 0, 0, 0, 0, 12, 0, 0, 0, 73, + 74, 0, 75, 0, 0, 0, 76, 0, 77, 78, + 79, 0, 0, 81, 0, 0, 0, 82, 0, 83, + 0, 0, 502, 0, 0, 0, 0, 0, 0, 0, + 0, 84, 13, 16, 0, 85, 0, 86, 0, 88, + 0, 89, 0, 0, 0, 0, 80, 87, 71, 0, + 0, 0, 0, 0, 0, 0, 0, 504, 0, 0, + 68, 69, 70, 0, 0, 0, 0, 0, 0, 0, + 0, 72, 0, 0, 0, 0, 0, 0, 12, 0, + 0, 0, 73, 74, 0, 75, 0, 0, 0, 76, + 0, 77, 78, 79, 0, 0, 81, 0, 0, 0, + 82, 0, 83, 0, 0, 507, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 13, 16, 0, 85, 0, + 86, 0, 88, 0, 89, 0, 0, 0, 0, 80, + 87, 71, 0, 0, 0, 0, 0, 0, 0, 0, + 496, 0, 0, 68, 69, 70, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 73, 74, 0, 75, 0, + 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, + 0, 0, 0, 82, 0, 83, 0, 0, 497, 0, + 0, 15, 0, 0, 0, 0, 0, 84, 13, 16, + 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, + 0, 0, 80, 87, 71, 0, 0, 14, 0, 0, + 0, 0, 0, 68, 69, 70, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, + 0, 12, 251, 0, 0, 535, 536, 0, 75, 0, + 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, + 0, 0, 0, 82, 0, 83, 0, 0, 0, 0, + 0, 0, 0, 255, 0, 0, 0, 84, 13, 16, + 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, + 0, 0, 80, 87, 71, 0, 246, 0, 537, 0, + 0, 0, 0, 142, 143, 144, 0, 0, 146, 148, + 149, 0, 0, 150, 0, 151, 0, 0, 0, 153, + 154, 155, 0, 0, 0, 0, 0, 0, 12, 156, + 157, 158, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, + 0, 0, 0, 0, 0, 13, 16, 163, 164, 165, + 0, 167, 168, 169, 170, 171, 172, 0, 0, 160, + 166, 152, 145, 147, 161, 0, 0, 0, 0, 0, + 142, 143, 144, 0, 0, 146, 148, 149, 0, 0, + 150, 0, 151, 0, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 425, 156, 157, 158, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, + 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, + 0, 430, 427, 429, 163, 164, 165, 0, 167, 168, + 169, 170, 171, 172, 0, 0, 160, 166, 152, 145, + 147, 161, 0, 0, 0, 0, 0, 142, 143, 144, + 0, 0, 146, 148, 149, 0, 0, 150, 0, 151, + 0, 0, 0, 153, 154, 155, 0, 0, 0, 0, + 0, 0, 425, 156, 157, 158, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, + 426, 0, 0, 0, 0, 0, 0, 0, 428, 0, + 0, 0, 162, 0, 0, 0, 0, 0, 430, 427, + 429, 163, 164, 165, 0, 167, 168, 169, 170, 171, + 172, 0, 0, 160, 166, 152, 145, 147, 161, 0, + 0, 0, 0, 0, 244, 0, 0, 0, 0, 245, + 0, 68, 69, 70, 247, 0, 0, 0, 0, 0, + 0, 248, 72, 0, 0, 0, 0, 0, 0, 250, + 251, 0, 0, 252, 74, 0, 75, 0, 0, 0, + 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, + 0, 82, 0, 83, 0, 0, 0, 0, 0, 254, + 0, 255, 0, 0, 0, 84, 253, 256, 257, 85, + 258, 86, 259, 88, 31, 89, 260, 261, 0, 0, + 80, 87, 71, 25, 246, 0, 0, 0, 0, 0, + 0, 244, 0, 0, 0, 0, 245, 0, 68, 69, + 70, 247, 0, 0, 0, 0, 0, 0, 248, 249, + 0, 0, 0, 0, 0, 0, 250, 251, 0, 0, + 252, 74, 0, 75, 0, 0, 0, 76, 0, 77, + 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, + 83, 0, 0, 0, 0, 0, 254, 0, 255, 0, + 0, 0, 84, 253, 256, 257, 85, 258, 86, 259, + 88, 31, 89, 260, 261, 0, 0, 80, 87, 71, + 25, 246, 0, 0, 0, 0, 0, 0, 541, 143, + 144, 0, 0, 543, 148, 545, 69, 70, 546, 0, + 151, 0, 0, 0, 153, 548, 549, 0, 0, 0, + 0, 0, 0, 550, 551, 157, 158, 252, 74, 0, + 75, 0, 0, 0, 76, 0, 77, 552, 79, 0, + 0, 554, 0, 0, 0, 82, 0, 83, 0, 0, + 0, 0, 0, 556, 0, 255, 0, 0, 0, 558, + 555, 557, 559, 560, 561, 86, 563, 564, 565, 566, + 567, 568, 0, 0, 553, 562, 547, 542, 544, 161, + 0, 0, 0, 0, 0, 393, 143, 144, 0, 0, + 395, 148, 397, 69, 70, 398, 0, 151, 0, 0, + 0, 153, 400, 401, 0, 0, 0, 0, 0, 0, + 402, 403, 157, 158, 252, 74, 0, 75, 0, 0, + 0, 76, 0, 77, 404, 79, 0, 0, 406, 0, + 0, 0, 82, 0, 83, 0, -244, 0, 0, 0, + 408, 0, 255, 0, 0, 0, 410, 407, 409, 411, + 412, 413, 86, 415, 416, 417, 418, 419, 420, 0, + 0, 405, 414, 399, 394, 396, 161, 0, 0, 0, + 0, 0, + + 334, 477, 282, 482, 270, 503, 467, 464, 275, 42, + 577, 55, 506, 479, 481, 217, 516, 522, 185, 23, + 468, 217, 540, 583, 10, 486, 488, 492, 490, 493, + 508, 270, 434, 385, 422, 383, 381, 366, 379, 368, + 270, 275, 468, 275, 334, 173, 282, 217, 242, 223, + 179, 468, 176, 334, 285, 371, 221, 343, 181, 341, + 211, 282, 465, 198, 352, 204, 457, 339, 370, 449, + 447, 206, 432, 442, 424, 334, 0, 93, 179, 501, + 0, 577, 318, 500, 213, 221, 93, 0, 471, 93, + 93, 93, 130, 483, 316, 317, 93, 461, 93, 93, + 215, 319, 93, 93, 320, 514, 93, 93, 129, 17, + 93, 0, 110, 94, 93, 93, 484, 102, 93, 242, + 93, 103, 101, 203, 337, 93, 11, 484, 93, 93, + 93, 513, 483, 93, 574, 515, 298, 93, 587, 334, + 0, 302, 200, 93, 93, 105, 334, 352, 125, 126, + 93, 11, 215, 269, 93, 93, 373, 510, 93, 124, + 512, 93, 436, 511, 179, 437, 93, 0, 242, 93, + 439, 127, 93, 123, 0, 436, 0, 128, 437, 93, + 93, 483, 215, 93, 93, 139, 436, 122, 335, 437, + 93, 93, 334, 141, 121, 362, 133, 376, 93, 93, + 100, 135, 93, 0, 117, 330, 361, 330, 131, 330, + 302, 93, 302, 93, 302, 330, 302, 0, 302, 0, + 302, 0, 0, 93, 327, 93, 345, 329, 302, 332, + 302, 351, 310, 0, 0, 0, 0, 349, 93, 0, + 348, 364, 93, 302, 93, 321, 484, 302, 93, 322, + 0, 93, 93, 302, 330, 323, 302, 302, 139, 302, + 35, 305, 0, 0, 325, 527, 141, 210, 35, 0, + 24, 37, 11, 0, 0, 0, 358, 0, 24, 37, + 11, 532, 529, 531, 533, 530, 534, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 569, 0, 0, 0, 0, 0, + 493, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0}; + +const int QmlJSGrammar::action_check [] = { + 60, 8, 36, 36, 33, 33, 7, 60, 7, 36, + 29, 33, 7, 7, 7, 36, 7, 55, 7, 78, + 1, 78, 48, 1, 36, 33, 36, 36, 60, 5, + 55, 61, 2, 33, 8, 55, 60, 16, 7, 7, + 7, 5, 48, 60, 7, 2, 60, 20, 7, 5, + 48, 17, 55, 2, 31, 7, 61, 8, 33, 7, + 7, 7, 7, 60, 36, 36, 7, 0, 8, 7, + 7, 36, 7, 88, 36, 29, 36, 1, 60, 65, + 33, 17, 78, 1, 7, 7, 36, 7, 7, 33, + 33, 76, 8, 2, 55, 78, 88, 36, 8, 29, + 8, 8, 36, 61, 36, 36, 48, 36, 8, 8, + 8, 66, 40, 8, 40, 8, -1, 7, 8, 8, + -1, -1, -1, 51, 15, 51, 8, 40, 40, 50, + 6, 8, 10, 54, 61, 62, 61, 62, 51, 51, + 42, 8, 33, 8, 20, 7, 61, 62, 8, 29, + 60, 53, 60, 60, 29, 61, 62, 56, 56, 29, + 60, 56, 50, 56, 61, 62, 54, 61, 62, 61, + 62, 60, 8, 29, 61, 62, 7, 55, 7, 61, + 61, 62, 8, 60, 29, -1, 15, 15, 15, 12, + 29, 66, 67, 60, 74, 60, 66, 67, 15, 29, + 8, 61, 62, -1, 33, 85, 34, 34, 36, 36, + 66, 67, 8, 29, -1, -1, -1, 34, -1, 36, + 29, 66, 67, 29, -1, 61, 62, 66, 67, 7, + 61, 62, 29, -1, 57, 61, 62, 29, -1, 25, + 63, 27, 12, 25, 74, 27, 25, 12, 27, -1, + 66, 67, 38, 61, 62, 85, 38, 66, 67, 38, + 66, 67, 29, 18, 19, 61, 62, 29, -1, 66, + 67, 29, -1, -1, 66, 67, 8, -1, 36, 18, + 19, 29, -1, 61, 62, -1, -1, 57, 36, -1, + 45, 46, 57, 63, 18, 19, 18, 19, 63, 66, + 67, 33, 23, 24, 66, 67, 45, 46, 66, 67, + 29, 32, 29, 25, 35, 27, 37, -1, 66, 67, + 29, 45, 46, 45, 46, 29, 38, 23, 24, 61, + 62, -1, 29, -1, -1, -1, 32, -1, -1, 35, + -1, 37, 61, 62, 61, 62, -1, 66, 67, 66, + 67, 29, 61, 62, -1, 59, -1, 66, 67, 23, + 24, -1, 66, 67, 61, 62, 23, 24, 32, 66, + 67, 35, -1, 37, -1, 32, 29, -1, 35, 29, + 37, 85, -1, 61, 62, 23, 24, -1, 66, 67, + -1, -1, -1, 31, 32, 23, 24, 35, -1, 37, + -1, -1, -1, 31, 32, -1, 59, 35, -1, 37, + -1, 61, 62, 66, 67, -1, 66, 67, 10, 23, + 24, -1, -1, -1, -1, -1, -1, 31, 32, -1, + 22, 35, 85, 37, -1, 23, 24, 29, -1, 10, + -1, 23, 24, 31, 32, -1, -1, 35, -1, 37, + 32, 22, -1, 35, -1, 37, -1, -1, 29, -1, + -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, + -1, -1, -1, -1, 66, 67, -1, -1, -1, -1, + -1, -1, 74, -1, 55, -1, -1, -1, 59, -1, + -1, 83, -1, 85, -1, 66, 67, 3, -1, -1, + -1, -1, -1, 74, -1, -1, -1, 13, -1, 23, + 24, 17, 83, -1, 85, -1, -1, 31, 32, -1, + 26, 35, 28, 37, -1, 31, -1, -1, -1, -1, + -1, -1, -1, 39, -1, 41, 42, -1, -1, 12, + 13, -1, -1, 49, -1, -1, 52, 53, -1, 22, + -1, -1, 58, -1, -1, -1, 29, -1, 64, -1, + 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, + 43, -1, -1, 79, 47, -1, -1, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, + -1, 17, 65, 66, 67, -1, 69, -1, -1, -1, + 26, -1, 28, -1, -1, -1, -1, 80, 81, 82, + -1, -1, -1, 39, -1, 41, 42, -1, -1, -1, + -1, -1, -1, 49, -1, -1, 52, 53, -1, -1, + -1, -1, 58, -1, -1, -1, -1, -1, 64, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 79, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, + -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, + 67, -1, 69, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, + -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, + -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, + 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, + 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, + -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, + -1, -1, -1, -1, 7, -1, -1, -1, 11, 12, + 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, + 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, + 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, + 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, + -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, + 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, + 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, + 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, + 73, 74, 75, -1, -1, -1, -1, 80, 81, 82, + -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, + -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, + -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, + 80, 81, 82, -1, -1, -1, -1, -1, -1, -1, + -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, + -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, + 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, + -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, + 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, + -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, + -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, + -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, + -1, 75, -1, -1, -1, -1, 80, 81, 82, -1, + -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, + 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, + -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, + -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, + 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, + -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, + 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, + 81, 82, -1, -1, -1, -1, -1, -1, -1, -1, + 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, + -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, + -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, + -1, -1, 80, 81, 82, -1, -1, 85, -1, -1, + -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, + -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, + -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, + -1, -1, 80, 81, 82, -1, 84, -1, 86, -1, + -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, + 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, + 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, + -1, -1, -1, -1, -1, 66, 67, 68, 69, 70, + -1, 72, 73, 74, 75, 76, 77, -1, -1, 80, + 81, 82, 83, 84, 85, -1, -1, -1, -1, -1, + 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, + 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, + -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, + -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, + 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, + 84, 85, -1, -1, -1, -1, -1, 4, 5, 6, + -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, + -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, + -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, + -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, + 77, -1, -1, 80, 81, 82, 83, 84, 85, -1, + -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, + -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, + -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, + 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, + -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, -1, -1, + 80, 81, 82, 83, 84, -1, -1, -1, -1, -1, + -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, + 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, + -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, + 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, + 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, + 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, + -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, + 83, 84, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, + 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, + -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, -1, -1, 80, 81, 82, 83, 84, 85, + -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, + 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, + -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, + 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, 55, -1, -1, -1, + 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, -1, + -1, 80, 81, 82, 83, 84, 85, -1, -1, -1, + -1, -1, + + 14, 93, 66, 15, 23, 29, 76, 76, 23, 20, + 23, 14, 29, 23, 15, 23, 23, 14, 62, 23, + 14, 23, 10, 29, 5, 14, 66, 66, 14, 29, + 14, 23, 66, 66, 29, 66, 14, 66, 66, 14, + 23, 23, 14, 23, 14, 14, 66, 23, 66, 23, + 29, 14, 29, 14, 14, 23, 23, 66, 29, 14, + 14, 66, 14, 29, 23, 29, 91, 66, 66, 14, + 66, 29, 29, 66, 30, 14, -1, 39, 29, 25, + -1, 23, 44, 29, 35, 23, 39, -1, 15, 39, + 39, 39, 45, 41, 44, 44, 39, 88, 39, 39, + 41, 44, 39, 39, 44, 41, 39, 39, 45, 6, + 39, -1, 45, 42, 39, 39, 41, 41, 39, 66, + 39, 42, 41, 55, 63, 39, 23, 41, 39, 39, + 39, 41, 41, 39, 6, 41, 39, 39, 80, 14, + -1, 44, 53, 39, 39, 47, 14, 23, 44, 44, + 39, 23, 41, 100, 39, 39, 94, 41, 39, 44, + 41, 39, 33, 41, 29, 36, 39, -1, 66, 39, + 35, 44, 39, 43, -1, 33, -1, 44, 36, 39, + 39, 41, 41, 39, 39, 23, 33, 43, 63, 36, + 39, 39, 14, 31, 43, 63, 51, 95, 39, 39, + 41, 49, 39, -1, 44, 39, 82, 39, 45, 39, + 44, 39, 44, 39, 44, 39, 44, -1, 44, -1, + 44, -1, -1, 39, 50, 39, 54, 61, 44, 61, + 44, 61, 46, -1, -1, -1, -1, 61, 39, -1, + 56, 63, 39, 44, 39, 46, 41, 44, 39, 46, + -1, 39, 39, 44, 39, 46, 44, 44, 23, 44, + 11, 48, -1, -1, 52, 8, 31, 32, 11, -1, + 21, 22, 23, -1, -1, -1, 61, -1, 21, 22, + 23, 14, 15, 16, 17, 18, 19, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, + 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1}; + diff --git a/src/declarative/qml/parser/qmljsgrammar_p.h b/src/declarative/qml/parser/qmljsgrammar_p.h new file mode 100644 index 0000000..c514485 --- /dev/null +++ b/src/declarative/qml/parser/qmljsgrammar_p.h @@ -0,0 +1,200 @@ +// This file was generated by qlalr - DO NOT EDIT! +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QMLJSGRAMMAR_P_H +#define QMLJSGRAMMAR_P_H + +class QmlJSGrammar +{ +public: + enum { + EOF_SYMBOL = 0, + REDUCE_HERE = 90, + SHIFT_THERE = 89, + T_AND = 1, + T_AND_AND = 2, + T_AND_EQ = 3, + T_AUTOMATIC_SEMICOLON = 62, + T_BREAK = 4, + T_CASE = 5, + T_CATCH = 6, + T_COLON = 7, + T_COMMA = 8, + T_CONST = 83, + T_CONTINUE = 9, + T_DEBUGGER = 84, + T_DEFAULT = 10, + T_DELETE = 11, + T_DIVIDE_ = 12, + T_DIVIDE_EQ = 13, + T_DO = 14, + T_DOT = 15, + T_ELSE = 16, + T_EQ = 17, + T_EQ_EQ = 18, + T_EQ_EQ_EQ = 19, + T_FALSE = 82, + T_FINALLY = 20, + T_FOR = 21, + T_FUNCTION = 22, + T_GE = 23, + T_GT = 24, + T_GT_GT = 25, + T_GT_GT_EQ = 26, + T_GT_GT_GT = 27, + T_GT_GT_GT_EQ = 28, + T_IDENTIFIER = 29, + T_IF = 30, + T_IMPORT = 88, + T_IN = 31, + T_INSTANCEOF = 32, + T_LBRACE = 33, + T_LBRACKET = 34, + T_LE = 35, + T_LPAREN = 36, + T_LT = 37, + T_LT_LT = 38, + T_LT_LT_EQ = 39, + T_MINUS = 40, + T_MINUS_EQ = 41, + T_MINUS_MINUS = 42, + T_MULTILINE_STRING_LITERAL = 86, + T_NEW = 43, + T_NOT = 44, + T_NOT_EQ = 45, + T_NOT_EQ_EQ = 46, + T_NULL = 80, + T_NUMERIC_LITERAL = 47, + T_OR = 48, + T_OR_EQ = 49, + T_OR_OR = 50, + T_PLUS = 51, + T_PLUS_EQ = 52, + T_PLUS_PLUS = 53, + T_PROPERTY = 66, + T_PUBLIC = 87, + T_QUESTION = 54, + T_RBRACE = 55, + T_RBRACKET = 56, + T_REMAINDER = 57, + T_REMAINDER_EQ = 58, + T_RESERVED_WORD = 85, + T_RETURN = 59, + T_RPAREN = 60, + T_SEMICOLON = 61, + T_SIGNAL = 67, + T_STAR = 63, + T_STAR_EQ = 64, + T_STRING_LITERAL = 65, + T_SWITCH = 68, + T_THIS = 69, + T_THROW = 70, + T_TILDE = 71, + T_TRUE = 81, + T_TRY = 72, + T_TYPEOF = 73, + T_VAR = 74, + T_VOID = 75, + T_WHILE = 76, + T_WITH = 77, + T_XOR = 78, + T_XOR_EQ = 79, + + ACCEPT_STATE = 588, + RULE_COUNT = 323, + STATE_COUNT = 589, + TERMINAL_COUNT = 91, + NON_TERMINAL_COUNT = 102, + + GOTO_INDEX_OFFSET = 589, + GOTO_INFO_OFFSET = 2092, + GOTO_CHECK_OFFSET = 2092 + }; + + static const char *const spell []; + static const int lhs []; + static const int rhs []; + static const int goto_default []; + static const int action_default []; + static const int action_index []; + static const int action_info []; + static const int action_check []; + + static inline int nt_action (int state, int nt) + { + const int *const goto_index = &action_index [GOTO_INDEX_OFFSET]; + const int *const goto_check = &action_check [GOTO_CHECK_OFFSET]; + + const int yyn = goto_index [state] + nt; + + if (yyn < 0 || goto_check [yyn] != nt) + return goto_default [nt]; + + const int *const goto_info = &action_info [GOTO_INFO_OFFSET]; + return goto_info [yyn]; + } + + static inline int t_action (int state, int token) + { + const int yyn = action_index [state] + token; + + if (yyn < 0 || action_check [yyn] != token) + return - action_default [state]; + + return action_info [yyn]; + } +}; + + +#endif // QMLJSGRAMMAR_P_H + diff --git a/src/declarative/qml/parser/qmljslexer.cpp b/src/declarative/qml/parser/qmljslexer.cpp new file mode 100644 index 0000000..843f6ae --- /dev/null +++ b/src/declarative/qml/parser/qmljslexer.cpp @@ -0,0 +1,1196 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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$ +** +****************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "qmljsengine_p.h" +#include "qmljslexer_p.h" +#include "qmljsgrammar_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +extern double qstrtod(const char *s00, char const **se, bool *ok); + +#define shiftWindowsLineBreak() \ + do { \ + if (((current == '\r') && (next1 == '\n')) \ + || ((current == '\n') && (next1 == '\r'))) { \ + shift(1); \ + } \ + } \ + while (0) + +namespace QmlJS { +extern double integerFromString(const char *buf, int size, int radix); +} + +using namespace QmlJS; + +Lexer::Lexer(Engine *eng) + : driver(eng), + yylineno(0), + done(false), + size8(128), size16(128), + pos8(0), pos16(0), + terminator(false), + restrKeyword(false), + delimited(false), + stackToken(-1), + state(Start), + pos(0), + code(0), length(0), + yycolumn(0), + startpos(0), + startlineno(0), startcolumn(0), + bol(true), + current(0), next1(0), next2(0), next3(0), + err(NoError), + wantRx(false), + check_reserved(true), + parenthesesState(IgnoreParentheses), + parenthesesCount(0), + prohibitAutomaticSemicolon(false) +{ + driver->setLexer(this); + // allocate space for read buffers + buffer8 = new char[size8]; + buffer16 = new QChar[size16]; + pattern = 0; + flags = 0; + +} + +Lexer::~Lexer() +{ + delete [] buffer8; + delete [] buffer16; +} + +void Lexer::setCode(const QString &c, int lineno) +{ + errmsg = QString(); + yylineno = lineno; + yycolumn = 1; + restrKeyword = false; + delimited = false; + stackToken = -1; + pos = 0; + code = c.unicode(); + length = c.length(); + bol = true; + + // read first characters + current = (length > 0) ? code[0].unicode() : 0; + next1 = (length > 1) ? code[1].unicode() : 0; + next2 = (length > 2) ? code[2].unicode() : 0; + next3 = (length > 3) ? code[3].unicode() : 0; +} + +void Lexer::shift(uint p) +{ + while (p--) { + ++pos; + ++yycolumn; + current = next1; + next1 = next2; + next2 = next3; + next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0; + } +} + +void Lexer::setDone(State s) +{ + state = s; + done = true; +} + +int Lexer::findReservedWord(const QChar *c, int size) const +{ + switch (size) { + case 2: { + if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')) + return QmlJSGrammar::T_DO; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f')) + return QmlJSGrammar::T_IF; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')) + return QmlJSGrammar::T_IN; + } break; + + case 3: { + if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r')) + return QmlJSGrammar::T_FOR; + else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w')) + return QmlJSGrammar::T_NEW; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y')) + return QmlJSGrammar::T_TRY; + else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r')) + return QmlJSGrammar::T_VAR; + else if (check_reserved) { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 4: { + if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_CASE; + else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_ELSE; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s')) + return QmlJSGrammar::T_THIS; + else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d')) + return QmlJSGrammar::T_VOID; + else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h')) + return QmlJSGrammar::T_WITH; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_TRUE; + else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l')) + return QmlJSGrammar::T_NULL; + else if (check_reserved) { + if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n') + && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 5: { + if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('k')) + return QmlJSGrammar::T_BREAK; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c') + && c[4] == QLatin1Char('h')) + return QmlJSGrammar::T_CATCH; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('w')) + return QmlJSGrammar::T_THROW; + else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('e')) + return QmlJSGrammar::T_WHILE; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s') + && c[4] == QLatin1Char('t')) + return QmlJSGrammar::T_CONST; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s') + && c[4] == QLatin1Char('e')) + return QmlJSGrammar::T_FALSE; + else if (check_reserved) { + if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r') + && c[4] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('r')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('l')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s') + && c[4] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 6: { + if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e')) + return QmlJSGrammar::T_DELETE; + else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n')) + return QmlJSGrammar::T_RETURN; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h')) + return QmlJSGrammar::T_SWITCH; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f')) + return QmlJSGrammar::T_TYPEOF; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) + return QmlJSGrammar::T_IMPORT; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l')) + return QmlJSGrammar::T_SIGNAL; + else if (check_reserved) { + if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b') + && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) + return QmlJSGrammar::T_PUBLIC; + else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i') + && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 7: { + if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l') + && c[6] == QLatin1Char('t')) + return QmlJSGrammar::T_DEFAULT; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l') + && c[6] == QLatin1Char('y')) + return QmlJSGrammar::T_FINALLY; + else if (check_reserved) { + if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a') + && c[6] == QLatin1Char('n')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d') + && c[6] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g') + && c[6] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t') + && c[6] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 8: { + if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n') + && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e')) + return QmlJSGrammar::T_CONTINUE; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') + && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') + && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')) + return QmlJSGrammar::T_FUNCTION; + else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u') + && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g') + && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r')) + return QmlJSGrammar::T_DEBUGGER; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r') + && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y')) + return QmlJSGrammar::T_PROPERTY; + else if (check_reserved) { + if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a') + && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') + && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 9: { + if (check_reserved) { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f') + && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c') + && c[8] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n') + && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i') + && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') + && c[8] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c') + && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e') + && c[8] == QLatin1Char('d')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 10: { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n') + && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e') + && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f')) + return QmlJSGrammar::T_INSTANCEOF; + else if (check_reserved) { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m') + && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') + && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 12: { + if (check_reserved) { + if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') + && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r') + && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n') + && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z') + && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + } // switch + + return -1; +} + +int Lexer::lex() +{ + int token = 0; + state = Start; + ushort stringType = 0; // either single or double quotes + bool multiLineString = false; + pos8 = pos16 = 0; + done = false; + terminator = false; + + // did we push a token on the stack previously ? + // (after an automatic semicolon insertion) + if (stackToken >= 0) { + setDone(Other); + token = stackToken; + stackToken = -1; + } + + while (!done) { + switch (state) { + case Start: + if (isWhiteSpace()) { + // do nothing + } else if (current == '/' && next1 == '/') { + recordStartPos(); + shift(1); + state = InSingleLineComment; + } else if (current == '/' && next1 == '*') { + recordStartPos(); + shift(1); + state = InMultiLineComment; + } else if (current == 0) { + syncProhibitAutomaticSemicolon(); + if (!terminator && !delimited && !prohibitAutomaticSemicolon) { + // automatic semicolon insertion if program incomplete + token = QmlJSGrammar::T_SEMICOLON; + stackToken = 0; + setDone(Other); + } else { + setDone(Eof); + } + } else if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + yycolumn = 0; + bol = true; + terminator = true; + syncProhibitAutomaticSemicolon(); + if (restrKeyword) { + token = QmlJSGrammar::T_SEMICOLON; + setDone(Other); + } + } else if (current == '"' || current == '\'') { + recordStartPos(); + state = InString; + multiLineString = false; + stringType = current; + } else if (isIdentLetter(current)) { + recordStartPos(); + record16(current); + state = InIdentifier; + } else if (current == '0') { + recordStartPos(); + record8(current); + state = InNum0; + } else if (isDecimalDigit(current)) { + recordStartPos(); + record8(current); + state = InNum; + } else if (current == '.' && isDecimalDigit(next1)) { + recordStartPos(); + record8(current); + state = InDecimal; + } else { + recordStartPos(); + token = matchPunctuator(current, next1, next2, next3); + if (token != -1) { + if (terminator && !delimited && !prohibitAutomaticSemicolon + && (token == QmlJSGrammar::T_PLUS_PLUS + || token == QmlJSGrammar::T_MINUS_MINUS)) { + // automatic semicolon insertion + stackToken = token; + token = QmlJSGrammar::T_SEMICOLON; + } + setDone(Other); + } + else { + setDone(Bad); + err = IllegalCharacter; + errmsg = QLatin1String("Illegal character"); + } + } + break; + case InString: + if (current == stringType) { + shift(1); + setDone(String); + } else if (isLineTerminator()) { + multiLineString = true; + record16(current); + } else if (current == 0 || isLineTerminator()) { + setDone(Bad); + err = UnclosedStringLiteral; + errmsg = QLatin1String("Unclosed string at end of line"); + } else if (current == '\\') { + state = InEscapeSequence; + } else { + record16(current); + } + break; + // Escape Sequences inside of strings + case InEscapeSequence: + if (isOctalDigit(current)) { + if (current >= '0' && current <= '3' && + isOctalDigit(next1) && isOctalDigit(next2)) { + record16(convertOctal(current, next1, next2)); + shift(2); + state = InString; + } else if (isOctalDigit(current) && + isOctalDigit(next1)) { + record16(convertOctal('0', current, next1)); + shift(1); + state = InString; + } else if (isOctalDigit(current)) { + record16(convertOctal('0', '0', current)); + state = InString; + } else { + setDone(Bad); + err = IllegalEscapeSequence; + errmsg = QLatin1String("Illegal escape squence"); + } + } else if (current == 'x') + state = InHexEscape; + else if (current == 'u') + state = InUnicodeEscape; + else { + if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + yycolumn = 0; + bol = true; + } else { + record16(singleEscape(current)); + } + state = InString; + } + break; + case InHexEscape: + if (isHexDigit(current) && isHexDigit(next1)) { + state = InString; + record16(QLatin1Char(convertHex(current, next1))); + shift(1); + } else if (current == stringType) { + record16(QLatin1Char('x')); + shift(1); + setDone(String); + } else { + record16(QLatin1Char('x')); + record16(current); + state = InString; + } + break; + case InUnicodeEscape: + if (isHexDigit(current) && isHexDigit(next1) && + isHexDigit(next2) && isHexDigit(next3)) { + record16(convertUnicode(current, next1, next2, next3)); + shift(3); + state = InString; + } else if (current == stringType) { + record16(QLatin1Char('u')); + shift(1); + setDone(String); + } else { + setDone(Bad); + err = IllegalUnicodeEscapeSequence; + errmsg = QLatin1String("Illegal unicode escape sequence"); + } + break; + case InSingleLineComment: + if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + yycolumn = 0; + terminator = true; + bol = true; + if (restrKeyword) { + token = QmlJSGrammar::T_SEMICOLON; + setDone(Other); + } else + state = Start; + } else if (current == 0) { + setDone(Eof); + } + break; + case InMultiLineComment: + if (current == 0) { + setDone(Bad); + err = UnclosedComment; + errmsg = QLatin1String("Unclosed comment at end of file"); + } else if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + } else if (current == '*' && next1 == '/') { + state = Start; + shift(1); + } + break; + case InIdentifier: + if (isIdentLetter(current) || isDecimalDigit(current)) { + record16(current); + break; + } + setDone(Identifier); + break; + case InNum0: + if (current == 'x' || current == 'X') { + record8(current); + state = InHex; + } else if (current == '.') { + record8(current); + state = InDecimal; + } else if (current == 'e' || current == 'E') { + record8(current); + state = InExponentIndicator; + } else if (isOctalDigit(current)) { + record8(current); + state = InOctal; + } else if (isDecimalDigit(current)) { + record8(current); + state = InDecimal; + } else { + setDone(Number); + } + break; + case InHex: + if (isHexDigit(current)) + record8(current); + else + setDone(Hex); + break; + case InOctal: + if (isOctalDigit(current)) { + record8(current); + } else if (isDecimalDigit(current)) { + record8(current); + state = InDecimal; + } else { + setDone(Octal); + } + break; + case InNum: + if (isDecimalDigit(current)) { + record8(current); + } else if (current == '.') { + record8(current); + state = InDecimal; + } else if (current == 'e' || current == 'E') { + record8(current); + state = InExponentIndicator; + } else { + setDone(Number); + } + break; + case InDecimal: + if (isDecimalDigit(current)) { + record8(current); + } else if (current == 'e' || current == 'E') { + record8(current); + state = InExponentIndicator; + } else { + setDone(Number); + } + break; + case InExponentIndicator: + if (current == '+' || current == '-') { + record8(current); + } else if (isDecimalDigit(current)) { + record8(current); + state = InExponent; + } else { + setDone(Bad); + err = IllegalExponentIndicator; + errmsg = QLatin1String("Illegal syntax for exponential number"); + } + break; + case InExponent: + if (isDecimalDigit(current)) { + record8(current); + } else { + setDone(Number); + } + break; + default: + Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement"); + } + + // move on to the next character + if (!done) + shift(1); + if (state != Start && state != InSingleLineComment) + bol = false; + } + + if (state == Number) { + // CSS-style suffix for numeric literals + + flags = noSuffix; + + const ushort c = QChar::toLower(current); + const ushort n1 = QChar::toLower(next1); + const ushort n2 = QChar::toLower(next2); + const ushort n3 = QChar::toLower(next3); + + if (c == 'e' && n1 == 'm') { + flags = emSuffix; + shift(2); + } else if (c == 'e' && n1 == 'x') { + flags = exSuffix; + shift(2); + } else if (c == 'p' && n1 == 'x') { + flags = pxSuffix; + shift(2); + } else if (c == 'c' && n1 == 'm') { + flags = cmSuffix; + shift(2); + } else if (c == 'm' && n1 == 'm') { + flags = mmSuffix; + shift(2); + } else if (c == 'i' && n1 == 'n') { + flags = inSuffix; + shift(2); + } else if (c == 'p' && n1 == 't') { + flags = ptSuffix; + shift(2); + } else if (c == 'p' && n1 == 'c') { + flags = pcSuffix; + shift(1); + } else if (c == 'd' && n1 == 'e' && n2 == 'g') { + flags = degSuffix; + shift(3); + } else if (c == 'r' && n1 == 'a' && n2 == 'd') { + flags = radSuffix; + shift(3); + } else if (c == 'g' && n1 == 'r' && n2 == 'a' && n3 == 'd') { + flags = gradSuffix; + shift(4); + } else if (c == 'm' && n1 == 's') { + flags = msSuffix; + shift(2); + } else if (c == 's') { + flags = sSuffix; + shift(1); + } else if (c == 'h' && n1 == 'z') { + flags = hzSuffix; + shift(2); + } else if (c == 'k' && n1 == 'h' && n2 == 'z') { + flags = khzSuffix; + shift(3); + } + } + + // no identifiers allowed directly after numeric literal, e.g. "3in" is bad + if ((state == Number || state == Octal || state == Hex) + && isIdentLetter(current)) { + state = Bad; + err = IllegalIdentifier; + errmsg = QLatin1String("Identifier cannot start with numeric literal"); + } + + // terminate string + buffer8[pos8] = '\0'; + + double dval = 0; + if (state == Number) { + dval = qstrtod(buffer8, 0, 0); + } else if (state == Hex) { // scan hex numbers + dval = integerFromString(buffer8, pos8, 16); + state = Number; + } else if (state == Octal) { // scan octal number + dval = integerFromString(buffer8, pos8, 8); + state = Number; + } + + restrKeyword = false; + delimited = false; + + switch (parenthesesState) { + case IgnoreParentheses: + break; + case CountParentheses: + if (token == QmlJSGrammar::T_RPAREN) { + --parenthesesCount; + if (parenthesesCount == 0) + parenthesesState = BalancedParentheses; + } else if (token == QmlJSGrammar::T_LPAREN) { + ++parenthesesCount; + } + break; + case BalancedParentheses: + parenthesesState = IgnoreParentheses; + break; + } + + switch (state) { + case Eof: + return 0; + case Other: + if (token == QmlJSGrammar::T_RBRACE || token == QmlJSGrammar::T_SEMICOLON) + delimited = true; + return token; + case Identifier: + if ((token = findReservedWord(buffer16, pos16)) < 0) { + /* TODO: close leak on parse error. same holds true for String */ + if (driver) + qsyylval.ustr = driver->intern(buffer16, pos16); + else + qsyylval.ustr = 0; + return QmlJSGrammar::T_IDENTIFIER; + } + if (token == QmlJSGrammar::T_CONTINUE || token == QmlJSGrammar::T_BREAK + || token == QmlJSGrammar::T_RETURN || token == QmlJSGrammar::T_THROW) { + restrKeyword = true; + } else if (token == QmlJSGrammar::T_IF || token == QmlJSGrammar::T_FOR + || token == QmlJSGrammar::T_WHILE || token == QmlJSGrammar::T_WITH) { + parenthesesState = CountParentheses; + parenthesesCount = 0; + } else if (token == QmlJSGrammar::T_DO) { + parenthesesState = BalancedParentheses; + } + return token; + case String: + if (driver) + qsyylval.ustr = driver->intern(buffer16, pos16); + else + qsyylval.ustr = 0; + return multiLineString?QmlJSGrammar::T_MULTILINE_STRING_LITERAL:QmlJSGrammar::T_STRING_LITERAL; + case Number: + qsyylval.dval = dval; + return QmlJSGrammar::T_NUMERIC_LITERAL; + case Bad: + return -1; + default: + Q_ASSERT(!"unhandled numeration value in switch"); + return -1; + } +} + +bool Lexer::isWhiteSpace() const +{ + return (current == ' ' || current == '\t' || + current == 0x0b || current == 0x0c); +} + +bool Lexer::isLineTerminator() const +{ + return (current == '\n' || current == '\r'); +} + +bool Lexer::isIdentLetter(ushort c) +{ + /* TODO: allow other legitimate unicode chars */ + return ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || c == '$' + || c == '_'); +} + +bool Lexer::isDecimalDigit(ushort c) +{ + return (c >= '0' && c <= '9'); +} + +bool Lexer::isHexDigit(ushort c) const +{ + return ((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F')); +} + +bool Lexer::isOctalDigit(ushort c) const +{ + return (c >= '0' && c <= '7'); +} + +int Lexer::matchPunctuator(ushort c1, ushort c2, + ushort c3, ushort c4) +{ + if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { + shift(4); + return QmlJSGrammar::T_GT_GT_GT_EQ; + } else if (c1 == '=' && c2 == '=' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_EQ_EQ_EQ; + } else if (c1 == '!' && c2 == '=' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_NOT_EQ_EQ; + } else if (c1 == '>' && c2 == '>' && c3 == '>') { + shift(3); + return QmlJSGrammar::T_GT_GT_GT; + } else if (c1 == '<' && c2 == '<' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_LT_LT_EQ; + } else if (c1 == '>' && c2 == '>' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_GT_GT_EQ; + } else if (c1 == '<' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_LE; + } else if (c1 == '>' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_GE; + } else if (c1 == '!' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_NOT_EQ; + } else if (c1 == '+' && c2 == '+') { + shift(2); + return QmlJSGrammar::T_PLUS_PLUS; + } else if (c1 == '-' && c2 == '-') { + shift(2); + return QmlJSGrammar::T_MINUS_MINUS; + } else if (c1 == '=' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_EQ_EQ; + } else if (c1 == '+' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_PLUS_EQ; + } else if (c1 == '-' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_MINUS_EQ; + } else if (c1 == '*' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_STAR_EQ; + } else if (c1 == '/' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_DIVIDE_EQ; + } else if (c1 == '&' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_AND_EQ; + } else if (c1 == '^' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_XOR_EQ; + } else if (c1 == '%' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_REMAINDER_EQ; + } else if (c1 == '|' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_OR_EQ; + } else if (c1 == '<' && c2 == '<') { + shift(2); + return QmlJSGrammar::T_LT_LT; + } else if (c1 == '>' && c2 == '>') { + shift(2); + return QmlJSGrammar::T_GT_GT; + } else if (c1 == '&' && c2 == '&') { + shift(2); + return QmlJSGrammar::T_AND_AND; + } else if (c1 == '|' && c2 == '|') { + shift(2); + return QmlJSGrammar::T_OR_OR; + } + + switch(c1) { + case '=': shift(1); return QmlJSGrammar::T_EQ; + case '>': shift(1); return QmlJSGrammar::T_GT; + case '<': shift(1); return QmlJSGrammar::T_LT; + case ',': shift(1); return QmlJSGrammar::T_COMMA; + case '!': shift(1); return QmlJSGrammar::T_NOT; + case '~': shift(1); return QmlJSGrammar::T_TILDE; + case '?': shift(1); return QmlJSGrammar::T_QUESTION; + case ':': shift(1); return QmlJSGrammar::T_COLON; + case '.': shift(1); return QmlJSGrammar::T_DOT; + case '+': shift(1); return QmlJSGrammar::T_PLUS; + case '-': shift(1); return QmlJSGrammar::T_MINUS; + case '*': shift(1); return QmlJSGrammar::T_STAR; + case '/': shift(1); return QmlJSGrammar::T_DIVIDE_; + case '&': shift(1); return QmlJSGrammar::T_AND; + case '|': shift(1); return QmlJSGrammar::T_OR; + case '^': shift(1); return QmlJSGrammar::T_XOR; + case '%': shift(1); return QmlJSGrammar::T_REMAINDER; + case '(': shift(1); return QmlJSGrammar::T_LPAREN; + case ')': shift(1); return QmlJSGrammar::T_RPAREN; + case '{': shift(1); return QmlJSGrammar::T_LBRACE; + case '}': shift(1); return QmlJSGrammar::T_RBRACE; + case '[': shift(1); return QmlJSGrammar::T_LBRACKET; + case ']': shift(1); return QmlJSGrammar::T_RBRACKET; + case ';': shift(1); return QmlJSGrammar::T_SEMICOLON; + + default: return -1; + } +} + +ushort Lexer::singleEscape(ushort c) const +{ + switch(c) { + case 'b': + return 0x08; + case 't': + return 0x09; + case 'n': + return 0x0A; + case 'v': + return 0x0B; + case 'f': + return 0x0C; + case 'r': + return 0x0D; + case '"': + return 0x22; + case '\'': + return 0x27; + case '\\': + return 0x5C; + default: + return c; + } +} + +ushort Lexer::convertOctal(ushort c1, ushort c2, + ushort c3) const +{ + return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); +} + +unsigned char Lexer::convertHex(ushort c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'a' && c <= 'f') + return (c - 'a' + 10); + else + return (c - 'A' + 10); +} + +unsigned char Lexer::convertHex(ushort c1, ushort c2) +{ + return ((convertHex(c1) << 4) + convertHex(c2)); +} + +QChar Lexer::convertUnicode(ushort c1, ushort c2, + ushort c3, ushort c4) +{ + return QChar((convertHex(c3) << 4) + convertHex(c4), + (convertHex(c1) << 4) + convertHex(c2)); +} + +void Lexer::record8(ushort c) +{ + Q_ASSERT(c <= 0xff); + + // enlarge buffer if full + if (pos8 >= size8 - 1) { + char *tmp = new char[2 * size8]; + memcpy(tmp, buffer8, size8 * sizeof(char)); + delete [] buffer8; + buffer8 = tmp; + size8 *= 2; + } + + buffer8[pos8++] = (char) c; +} + +void Lexer::record16(QChar c) +{ + // enlarge buffer if full + if (pos16 >= size16 - 1) { + QChar *tmp = new QChar[2 * size16]; + memcpy(tmp, buffer16, size16 * sizeof(QChar)); + delete [] buffer16; + buffer16 = tmp; + size16 *= 2; + } + + buffer16[pos16++] = c; +} + +void Lexer::recordStartPos() +{ + startpos = pos; + startlineno = yylineno; + startcolumn = yycolumn; +} + +bool Lexer::scanRegExp(RegExpBodyPrefix prefix) +{ + pos16 = 0; + bool lastWasEscape = false; + + if (prefix == EqualPrefix) + record16(QLatin1Char('=')); + + while (1) { + if (isLineTerminator() || current == 0) { + errmsg = QLatin1String("Unterminated regular expression literal"); + return false; + } + else if (current != '/' || lastWasEscape == true) + { + record16(current); + lastWasEscape = !lastWasEscape && (current == '\\'); + } + else { + if (driver) + pattern = driver->intern(buffer16, pos16); + else + pattern = 0; + pos16 = 0; + shift(1); + break; + } + shift(1); + } + + flags = 0; + while (isIdentLetter(current)) { + int flag = Ecma::RegExp::flagFromChar(current); + if (flag == 0) { + errmsg = QString::fromLatin1("Invalid regular expression flag '%0'") + .arg(QChar(current)); + return false; + } + flags |= flag; + record16(current); + shift(1); + } + + return true; +} + +void Lexer::syncProhibitAutomaticSemicolon() +{ + if (parenthesesState == BalancedParentheses) { + // we have seen something like "if (foo)", which means we should + // never insert an automatic semicolon at this point, since it would + // then be expanded into an empty statement (ECMA-262 7.9.1) + prohibitAutomaticSemicolon = true; + parenthesesState = IgnoreParentheses; + } else { + prohibitAutomaticSemicolon = false; + } +} + +QT_END_NAMESPACE + + diff --git a/src/declarative/qml/parser/qmljslexer_p.h b/src/declarative/qml/parser/qmljslexer_p.h new file mode 100644 index 0000000..e1ff23e --- /dev/null +++ b/src/declarative/qml/parser/qmljslexer_p.h @@ -0,0 +1,269 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 QMLJSLEXER_P_H +#define QMLJSLEXER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + + + +QT_BEGIN_NAMESPACE + +namespace QmlJS { + +class Engine; +class NameId; + +class Lexer +{ +public: + Lexer(Engine *eng); + ~Lexer(); + + void setCode(const QString &c, int lineno); + int lex(); + + int currentLineNo() const { return yylineno; } + int currentColumnNo() const { return yycolumn; } + + int tokenOffset() const { return startpos; } + int tokenLength() const { return pos - startpos; } + + int startLineNo() const { return startlineno; } + int startColumnNo() const { return startcolumn; } + + int endLineNo() const { return currentLineNo(); } + int endColumnNo() const + { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; } + + bool prevTerminator() const { return terminator; } + + enum State { Start, + Identifier, + InIdentifier, + InSingleLineComment, + InMultiLineComment, + InNum, + InNum0, + InHex, + InOctal, + InDecimal, + InExponentIndicator, + InExponent, + Hex, + Octal, + Number, + String, + Eof, + InString, + InEscapeSequence, + InHexEscape, + InUnicodeEscape, + Other, + Bad }; + + enum Suffix { + noSuffix, + emSuffix, + exSuffix, + pxSuffix, + cmSuffix, + mmSuffix, + inSuffix, + ptSuffix, + pcSuffix, + degSuffix, + radSuffix, + gradSuffix, + msSuffix, + sSuffix, + hzSuffix, + khzSuffix + }; + + enum Error { + NoError, + IllegalCharacter, + UnclosedStringLiteral, + IllegalEscapeSequence, + IllegalUnicodeEscapeSequence, + UnclosedComment, + IllegalExponentIndicator, + IllegalIdentifier + }; + + enum ParenthesesState { + IgnoreParentheses, + CountParentheses, + BalancedParentheses + }; + + enum RegExpBodyPrefix { + NoPrefix, + EqualPrefix + }; + + bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); + + NameId *pattern; + int flags; + + State lexerState() const + { return state; } + + QString errorMessage() const + { return errmsg; } + void setErrorMessage(const QString &err) + { errmsg = err; } + void setErrorMessage(const char *err) + { setErrorMessage(QString::fromLatin1(err)); } + + Error error() const + { return err; } + void clearError() + { err = NoError; } + +private: + Engine *driver; + int yylineno; + bool done; + char *buffer8; + QChar *buffer16; + uint size8, size16; + uint pos8, pos16; + bool terminator; + bool restrKeyword; + // encountered delimiter like "'" and "}" on last run + bool delimited; + int stackToken; + + State state; + void setDone(State s); + uint pos; + void shift(uint p); + int lookupKeyword(const char *); + + bool isWhiteSpace() const; + bool isLineTerminator() const; + bool isHexDigit(ushort c) const; + bool isOctalDigit(ushort c) const; + + int matchPunctuator(ushort c1, ushort c2, + ushort c3, ushort c4); + ushort singleEscape(ushort c) const; + ushort convertOctal(ushort c1, ushort c2, + ushort c3) const; +public: + static unsigned char convertHex(ushort c1); + static unsigned char convertHex(ushort c1, ushort c2); + static QChar convertUnicode(ushort c1, ushort c2, + ushort c3, ushort c4); + static bool isIdentLetter(ushort c); + static bool isDecimalDigit(ushort c); + + inline int ival() const { return qsyylval.ival; } + inline double dval() const { return qsyylval.dval; } + inline NameId *ustr() const { return qsyylval.ustr; } + + const QChar *characterBuffer() const { return buffer16; } + int characterCount() const { return pos16; } + +private: + void record8(ushort c); + void record16(QChar c); + void recordStartPos(); + + int findReservedWord(const QChar *buffer, int size) const; + + void syncProhibitAutomaticSemicolon(); + + const QChar *code; + uint length; + int yycolumn; + int startpos; + int startlineno; + int startcolumn; + int bol; // begin of line + + union { + int ival; + double dval; + NameId *ustr; + } qsyylval; + + // current and following unicode characters + ushort current, next1, next2, next3; + + struct keyword { + const char *name; + int token; + }; + + QString errmsg; + Error err; + + bool wantRx; + bool check_reserved; + + ParenthesesState parenthesesState; + int parenthesesCount; + bool prohibitAutomaticSemicolon; +}; + +} // namespace QmlJS + +QT_END_NAMESPACE + + + +#endif diff --git a/src/declarative/qml/parser/qmljsmemorypool_p.h b/src/declarative/qml/parser/qmljsmemorypool_p.h new file mode 100644 index 0000000..d7506be --- /dev/null +++ b/src/declarative/qml/parser/qmljsmemorypool_p.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 QMLJSMEMORYPOOL_P_H +#define QMLJSMEMORYPOOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QmlJS { + +class MemoryPool : public QSharedData +{ +public: + enum { maxBlockCount = -1 }; + enum { defaultBlockSize = 1 << 12 }; + + MemoryPool() { + m_blockIndex = maxBlockCount; + m_currentIndex = 0; + m_storage = 0; + m_currentBlock = 0; + m_currentBlockSize = 0; + } + + virtual ~MemoryPool() { + for (int index = 0; index < m_blockIndex + 1; ++index) + qFree(m_storage[index]); + + qFree(m_storage); + } + + char *allocate(int bytes) { + bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment) + if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) { + ++m_blockIndex; + m_currentBlockSize = defaultBlockSize << m_blockIndex; + + m_storage = reinterpret_cast(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex))); + m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast(qMalloc(m_currentBlockSize)); + ::memset(m_currentBlock, 0, m_currentBlockSize); + + m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned + Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize); + } + + char *p = reinterpret_cast + (m_currentBlock + m_currentIndex); + + m_currentIndex += bytes; + + return p; + } + + int bytesAllocated() const { + int bytes = 0; + for (int index = 0; index < m_blockIndex; ++index) + bytes += (defaultBlockSize << index); + bytes += m_currentIndex; + return bytes; + } + +private: + int m_blockIndex; + int m_currentIndex; + char *m_currentBlock; + int m_currentBlockSize; + char **m_storage; + +private: + Q_DISABLE_COPY(MemoryPool) +}; + +} // namespace QmlJS + +QT_END_NAMESPACE + +#endif diff --git a/src/declarative/qml/parser/qmljsnodepool_p.h b/src/declarative/qml/parser/qmljsnodepool_p.h new file mode 100644 index 0000000..1a5b7f6 --- /dev/null +++ b/src/declarative/qml/parser/qmljsnodepool_p.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 QMLJSNODEPOOL_P_H +#define QMLJSNODEPOOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qmljsmemorypool_p.h" + +QT_BEGIN_NAMESPACE + +namespace QmlJS { + +namespace AST { +class Node; +} // namespace AST + +class Code; +class CompilationUnit; +class Engine; + +template +inline NodeType *makeAstNode(MemoryPool *storage) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(); + return node; +} + +template +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1); + return node; +} + +template +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2); + return node; +} + +template +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3); + return node; +} + +template +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4); + return node; +} + +class NodePool : public MemoryPool +{ +public: + NodePool(const QString &fileName, Engine *engine); + virtual ~NodePool(); + + Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation); + + inline QString fileName() const { return m_fileName; } + inline Engine *engine() const { return m_engine; } +#ifndef J_SCRIPT_NO_EVENT_NOTIFY + inline qint64 id() const { return m_id; } +#endif + +private: + QHash m_codeCache; + QString m_fileName; + Engine *m_engine; +#ifndef J_SCRIPT_NO_EVENT_NOTIFY + qint64 m_id; +#endif + +private: + Q_DISABLE_COPY(NodePool) +}; + +} // namespace QmlJS + +QT_END_NAMESPACE + +#endif diff --git a/src/declarative/qml/parser/qmljsparser.cpp b/src/declarative/qml/parser/qmljsparser.cpp new file mode 100644 index 0000000..6ecff3d --- /dev/null +++ b/src/declarative/qml/parser/qmljsparser.cpp @@ -0,0 +1,1717 @@ +// This file was generated by qlalr - DO NOT EDIT! + +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 + +#include + +#include "qmljsengine_p.h" +#include "qmljslexer_p.h" +#include "qmljsast_p.h" +#include "qmljsnodepool_p.h" + + + +#include "qmljsparser_p.h" +#include + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +using namespace QmlJS; + +QT_BEGIN_NAMESPACE + +void Parser::reallocateStack() +{ + if (! stack_size) + stack_size = 128; + else + stack_size <<= 1; + + sym_stack = reinterpret_cast (qRealloc(sym_stack, stack_size * sizeof(Value))); + state_stack = reinterpret_cast (qRealloc(state_stack, stack_size * sizeof(int))); + location_stack = reinterpret_cast (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); +} + +inline static bool automatic(Engine *driver, int token) +{ + return token == QmlJSGrammar::T_RBRACE + || token == 0 + || driver->lexer()->prevTerminator(); +} + + +Parser::Parser(Engine *engine): + driver(engine), + tos(0), + stack_size(0), + sym_stack(0), + state_stack(0), + location_stack(0), + first_token(0), + last_token(0) +{ +} + +Parser::~Parser() +{ + if (stack_size) { + qFree(sym_stack); + qFree(state_stack); + qFree(location_stack); + } +} + +static inline AST::SourceLocation location(Lexer *lexer) +{ + AST::SourceLocation loc; + loc.offset = lexer->tokenOffset(); + loc.length = lexer->tokenLength(); + loc.startLine = lexer->startLineNo(); + loc.startColumn = lexer->startColumnNo(); + return loc; +} + +AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) +{ + QVarLengthArray nameIds; + QVarLengthArray locations; + + AST::ExpressionNode *it = expr; + while (AST::FieldMemberExpression *m = AST::cast(it)) { + nameIds.append(m->name); + locations.append(m->identifierToken); + it = m->base; + } + + if (AST::IdentifierExpression *idExpr = AST::cast(it)) { + AST::UiQualifiedId *q = makeAstNode(driver->nodePool(), idExpr->name); + q->identifierToken = idExpr->identifierToken; + + AST::UiQualifiedId *currentId = q; + for (int i = nameIds.size() - 1; i != -1; --i) { + currentId = makeAstNode(driver->nodePool(), currentId, nameIds[i]); + currentId->identifierToken = locations[i]; + } + + return currentId->finish(); + } + + return 0; +} + +bool Parser::parse() +{ + Lexer *lexer = driver->lexer(); + bool hadErrors = false; + int yytoken = -1; + int action = 0; + + first_token = last_token = 0; + + tos = -1; + program = 0; + + do { + if (++tos == stack_size) + reallocateStack(); + + state_stack[tos] = action; + + _Lcheck_token: + if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { + yyprevlloc = yylloc; + + if (first_token == last_token) { + yytoken = lexer->lex(); + yylval = lexer->dval(); + yylloc = location(lexer); + } else { + yytoken = first_token->token; + yylval = first_token->dval; + yylloc = first_token->loc; + ++first_token; + } + } + + action = t_action(action, yytoken); + if (action > 0) { + if (action != ACCEPT_STATE) { + yytoken = -1; + sym(1).dval = yylval; + loc(1) = yylloc; + } else { + --tos; + return ! hadErrors; + } + } else if (action < 0) { + const int r = -action - 1; + tos -= rhs[r]; + + switch (r) { + +case 0: { + program = makeAstNode (driver->nodePool(), sym(1).UiImportList, + sym(2).UiObjectMemberList->finish()); + sym(1).UiProgram = program; +} break; + +case 2: { + sym(1).Node = sym(1).UiImportList->finish(); +} break; + +case 3: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiImport); +} break; + +case 4: { + sym(1).Node = makeAstNode (driver->nodePool(), + sym(1).UiImportList, sym(2).UiImport); +} break; + +case 6: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).sval); + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 7: { + sym(1).Node = 0; +} break; + +case 8: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); +} break; + +case 9: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); +} break; + +case 10: { + AST::UiObjectMemberList *node = makeAstNode (driver->nodePool(), + sym(1).UiObjectMemberList, sym(2).UiObjectMember); + sym(1).Node = node; +} break; + +case 11: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); +} break; + +case 12: { + AST::UiArrayMemberList *node = makeAstNode (driver->nodePool(), + sym(1).UiArrayMemberList, sym(3).UiObjectMember); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 13: { + AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), (AST::UiObjectMemberList*)0); + node->lbraceToken = loc(1); + node->rbraceToken = loc(2); + sym(1).Node = node; +} break; + +case 14: { + AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), sym(2).UiObjectMemberList->finish()); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 15: { + AST::UiObjectDefinition *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), + sym(2).UiObjectInitializer); + sym(1).Node = node; +} break; + +case 17: { + AST::UiArrayBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), + sym(4).UiArrayMemberList->finish()); + node->colonToken = loc(2); + node->lbracketToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; + +case 18: { + AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 20: { + AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 21: { + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { + AST::UiObjectBinding *node = makeAstNode (driver->nodePool(), + sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); + node->colonToken = loc(2); + sym(1).Node = node; + } else { + sym(1).Node = 0; + + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2), + QLatin1String("Expected a type name after token `:'"))); + + return false; // ### recover + } +} break; +case 22:case 23:case 24:case 25:case 26:case 27: +{ + AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), + sym(3).Statement); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 28: + +case 29: { + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); + break; +} + +case 31: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 33: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->semicolonToken = loc(4); + sym(1).Node = node; +} break; + +case 35: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; + +case 37: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, + sym(5).Expression); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->colonToken = loc(4); + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; + +case 39: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, + sym(6).Expression); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; + +case 40: { + sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); +} break; + +case 41: { + sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); +} break; +case 42: +case 43: +{ + AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 45: { + QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} + +case 46: { + QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} + +case 47: { + AST::ThisExpression *node = makeAstNode (driver->nodePool()); + node->thisToken = loc(1); + sym(1).Node = node; +} break; + +case 48: { + AST::IdentifierExpression *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 49: { + AST::NullExpression *node = makeAstNode (driver->nodePool()); + node->nullToken = loc(1); + sym(1).Node = node; +} break; + +case 50: { + AST::TrueLiteral *node = makeAstNode (driver->nodePool()); + node->trueToken = loc(1); + sym(1).Node = node; +} break; + +case 51: { + AST::FalseLiteral *node = makeAstNode (driver->nodePool()); + node->falseToken = loc(1); + sym(1).Node = node; +} break; + +case 52: { + AST::NumericLiteral *node = makeAstNode (driver->nodePool(), sym(1).dval, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 53: { + AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 54: { + bool rx = lexer->scanRegExp(Lexer::NoPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; // ### remove me + } + AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 55: { + bool rx = lexer->scanRegExp(Lexer::EqualPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; + } + AST::RegExpLiteral *node = makeAstNode (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 56: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->rbracketToken = loc(2); + sym(1).Node = node; +} break; + +case 57: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).Elision->finish()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; + +case 58: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish ()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; + +case 59: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), + (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; + +case 60: { + AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), + sym(4).Elision->finish()); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; + +case 61: { + AST::ObjectLiteral *node = 0; + if (sym(2).Node) + node = makeAstNode (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + else + node = makeAstNode (driver->nodePool()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 62: { + AST::ObjectLiteral *node = makeAstNode (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(4); + sym(1).Node = node; +} break; + +case 63: { + AST::NestedExpression *node = makeAstNode(driver->nodePool(), sym(2).Expression); + node->lparenToken = loc(1); + node->rparenToken = loc(3); + sym(1).Node = node; +} break; + +case 64: { + AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 65: { + AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 66: { + sym(1).Node = makeAstNode (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); +} break; + +case 67: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); +} break; + +case 68: { + AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, + (AST::Elision *) 0, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 69: { + AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), + sym(4).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 70: { + AST::Elision *node = makeAstNode (driver->nodePool()); + node->commaToken = loc(1); + sym(1).Node = node; +} break; + +case 71: { + AST::Elision *node = makeAstNode (driver->nodePool(), sym(1).Elision); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 72: { + AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), + sym(1).PropertyName, sym(3).Expression); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 73: { + AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), + sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); + node->commaToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 74: { + AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +case 75: +case 76: { + AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 77: { + AST::StringLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 78: { + AST::NumericLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).dval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 79: { + AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 80: + +case 81: + +case 82: + +case 83: + +case 84: + +case 85: + +case 86: + +case 87: + +case 88: + +case 89: + +case 90: + +case 91: + +case 92: + +case 93: + +case 94: + +case 95: + +case 96: + +case 97: + +case 98: + +case 99: + +case 100: + +case 101: + +case 102: + +case 103: + +case 104: + +case 105: + +case 106: + +case 107: + +case 108: + +case 109: + +case 110: +{ + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); +} break; + +case 115: { + AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; + +case 116: { + AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 117: { + AST::NewMemberExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); + node->newToken = loc(1); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + sym(1).Node = node; +} break; + +case 119: { + AST::NewExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->newToken = loc(1); + sym(1).Node = node; +} break; + +case 120: { + AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 121: { + AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 122: { + AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; + +case 123: { + AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 124: { + sym(1).Node = 0; +} break; + +case 125: { + sym(1).Node = sym(1).ArgumentList->finish(); +} break; + +case 126: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Expression); +} break; + +case 127: { + AST::ArgumentList *node = makeAstNode (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 131: { + AST::PostIncrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->incrementToken = loc(2); + sym(1).Node = node; +} break; + +case 132: { + AST::PostDecrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->decrementToken = loc(2); + sym(1).Node = node; +} break; + +case 134: { + AST::DeleteExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->deleteToken = loc(1); + sym(1).Node = node; +} break; + +case 135: { + AST::VoidExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->voidToken = loc(1); + sym(1).Node = node; +} break; + +case 136: { + AST::TypeOfExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->typeofToken = loc(1); + sym(1).Node = node; +} break; + +case 137: { + AST::PreIncrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->incrementToken = loc(1); + sym(1).Node = node; +} break; + +case 138: { + AST::PreDecrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->decrementToken = loc(1); + sym(1).Node = node; +} break; + +case 139: { + AST::UnaryPlusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->plusToken = loc(1); + sym(1).Node = node; +} break; + +case 140: { + AST::UnaryMinusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->minusToken = loc(1); + sym(1).Node = node; +} break; + +case 141: { + AST::TildeExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->tildeToken = loc(1); + sym(1).Node = node; +} break; + +case 142: { + AST::NotExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->notToken = loc(1); + sym(1).Node = node; +} break; + +case 144: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Mul, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 145: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Div, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 146: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Mod, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 148: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Add, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 149: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Sub, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 151: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::LShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 152: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::RShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 153: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::URShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 155: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 156: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 157: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 158: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 159: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 160: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::In, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 162: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 163: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 164: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 165: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 166: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 168: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 169: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 170: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 171: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 173: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 174: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 175: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 176: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 178: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 180: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 182: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 184: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 186: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 188: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 190: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 192: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 194: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 196: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 198: { + AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 200: { + AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 202: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 204: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 205: { + sym(1).ival = QSOperator::Assign; +} break; + +case 206: { + sym(1).ival = QSOperator::InplaceMul; +} break; + +case 207: { + sym(1).ival = QSOperator::InplaceDiv; +} break; + +case 208: { + sym(1).ival = QSOperator::InplaceMod; +} break; + +case 209: { + sym(1).ival = QSOperator::InplaceAdd; +} break; + +case 210: { + sym(1).ival = QSOperator::InplaceSub; +} break; + +case 211: { + sym(1).ival = QSOperator::InplaceLeftShift; +} break; + +case 212: { + sym(1).ival = QSOperator::InplaceRightShift; +} break; + +case 213: { + sym(1).ival = QSOperator::InplaceURightShift; +} break; + +case 214: { + sym(1).ival = QSOperator::InplaceAnd; +} break; + +case 215: { + sym(1).ival = QSOperator::InplaceXor; +} break; + +case 216: { + sym(1).ival = QSOperator::InplaceOr; +} break; + +case 218: { + AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 219: { + sym(1).Node = 0; +} break; + +case 222: { + AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 223: { + sym(1).Node = 0; +} break; + +case 240: { + AST::Block *node = makeAstNode (driver->nodePool(), sym(2).StatementList); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 241: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); +} break; + +case 242: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).StatementList, sym(2).Statement); +} break; + +case 243: { + sym(1).Node = 0; +} break; + +case 244: { + sym(1).Node = sym(1).StatementList->finish (); +} break; + +case 246: { + AST::VariableStatement *node = makeAstNode (driver->nodePool(), + sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); + node->declarationKindToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 247: { + sym(1).ival = T_CONST; +} break; + +case 248: { + sym(1).ival = T_VAR; +} break; + +case 249: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); +} break; + +case 250: { + AST::VariableDeclarationList *node = makeAstNode (driver->nodePool(), + sym(1).VariableDeclarationList, sym(3).VariableDeclaration); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 251: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); +} break; + +case 252: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); +} break; + +case 253: { + AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 254: { + AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 255: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; + +case 256: { + sym(1).Node = 0; +} break; + +case 258: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; + +case 259: { + sym(1).Node = 0; +} break; + +case 261: { + AST::EmptyStatement *node = makeAstNode (driver->nodePool()); + node->semicolonToken = loc(1); + sym(1).Node = node; +} break; + +case 263: { + AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 264: { + AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + node->elseToken = loc(5); + sym(1).Node = node; +} break; + +case 265: { + AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 267: { + AST::DoWhileStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(5).Expression); + node->doToken = loc(1); + node->whileToken = loc(3); + node->lparenToken = loc(4); + node->rparenToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; + +case 268: { + AST::WhileStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->whileToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 269: { + AST::ForStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Expression, sym(9).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->firstSemicolonToken = loc(4); + node->secondSemicolonToken = loc(6); + node->rparenToken = loc(8); + sym(1).Node = node; +} break; + +case 270: { + AST::LocalForStatement *node = makeAstNode (driver->nodePool(), + sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, + sym(8).Expression, sym(10).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->firstSemicolonToken = loc(5); + node->secondSemicolonToken = loc(7); + node->rparenToken = loc(9); + sym(1).Node = node; +} break; + +case 271: { + AST:: ForEachStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->inToken = loc(4); + node->rparenToken = loc(6); + sym(1).Node = node; +} break; + +case 272: { + AST::LocalForEachStatement *node = makeAstNode (driver->nodePool(), + sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->inToken = loc(5); + node->rparenToken = loc(7); + sym(1).Node = node; +} break; + +case 274: { + AST::ContinueStatement *node = makeAstNode (driver->nodePool()); + node->continueToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 276: { + AST::ContinueStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); + node->continueToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 278: { + AST::BreakStatement *node = makeAstNode (driver->nodePool()); + node->breakToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 280: { + AST::BreakStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); + node->breakToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 282: { + AST::ReturnStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->returnToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 283: { + AST::WithStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->withToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 284: { + AST::SwitchStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); + node->switchToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 285: { + AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 286: { + AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(5); + sym(1).Node = node; +} break; + +case 287: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClause); +} break; + +case 288: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); +} break; + +case 289: { + sym(1).Node = 0; +} break; + +case 290: { + sym(1).Node = sym(1).CaseClauses->finish (); +} break; + +case 291: { + AST::CaseClause *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).StatementList); + node->caseToken = loc(1); + node->colonToken = loc(3); + sym(1).Node = node; +} break; + +case 292: { + AST::DefaultClause *node = makeAstNode (driver->nodePool(), sym(3).StatementList); + node->defaultToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +case 293: +case 294: { + AST::LabelledStatement *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 295: { + AST::LabelledStatement *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 297: { + AST::ThrowStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); + node->throwToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 298: { + AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch); + node->tryToken = loc(1); + sym(1).Node = node; +} break; + +case 299: { + AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; + +case 300: { + AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; + +case 301: { + AST::Catch *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(5).Block); + node->catchToken = loc(1); + node->lparenToken = loc(2); + node->identifierToken = loc(3); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 302: { + AST::Finally *node = makeAstNode (driver->nodePool(), sym(2).Block); + node->finallyToken = loc(1); + sym(1).Node = node; +} break; + +case 304: { + AST::DebuggerStatement *node = makeAstNode (driver->nodePool()); + node->debuggerToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 305: { + AST::FunctionDeclaration *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; + +case 306: { + AST::FunctionExpression *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + if (sym(2).sval) + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; + +case 307: { + AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 308: { + AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); + node->commaToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 309: { + sym(1).Node = 0; +} break; + +case 310: { + sym(1).Node = sym(1).FormalParameterList->finish (); +} break; + +case 311: { + sym(1).Node = 0; +} break; + +case 313: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); +} break; + +case 314: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElement); +} break; + +case 315: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); +} break; + +case 316: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); +} break; + +case 317: { + sym(1).Node = makeAstNode (driver->nodePool(), sym(1).FunctionDeclaration); +} break; + +case 318: { + sym(1).sval = 0; +} break; + +case 320: { + sym(1).Node = 0; +} break; + + } // switch + action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); + } // if + } while (action != 0); + + if (first_token == last_token) { + const int errorState = state_stack[tos]; + + // automatic insertion of `;' + if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { + SavedToken &tk = token_buffer[0]; + tk.token = yytoken; + tk.dval = yylval; + tk.loc = yylloc; + + yylloc = yyprevlloc; + yylloc.offset += yylloc.length; + yylloc.startColumn += yylloc.length; + yylloc.length = 0; + + //const QString msg = QString::fromUtf8("Missing `;'"); + //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); + + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; + + yytoken = T_SEMICOLON; + yylval = 0; + + action = errorState; + + goto _Lcheck_token; + } + + hadErrors = true; + + token_buffer[0].token = yytoken; + token_buffer[0].dval = yylval; + token_buffer[0].loc = yylloc; + + token_buffer[1].token = yytoken = lexer->lex(); + token_buffer[1].dval = yylval = lexer->dval(); + token_buffer[1].loc = yylloc = location(lexer); + + if (t_action(errorState, yytoken)) { + const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + action = errorState; + goto _Lcheck_token; + } + + static int tokens[] = { + T_PLUS, + T_EQ, + + T_COMMA, + T_COLON, + T_SEMICOLON, + + T_RPAREN, T_RBRACKET, T_RBRACE, + + T_NUMERIC_LITERAL, + T_IDENTIFIER, + + T_LPAREN, T_LBRACKET, T_LBRACE, + + EOF_SYMBOL + }; + + for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { + int a = t_action(errorState, *tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = *tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + first_token = &token_buffer[0]; + last_token = &token_buffer[2]; + + action = errorState; + goto _Lcheck_token; + } + } + + for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { + if (tk == T_AUTOMATIC_SEMICOLON) + continue; + + int a = t_action(errorState, tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + action = errorState; + goto _Lcheck_token; + } + } + + const QString msg = QString::fromUtf8("Syntax error"); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + } + + return false; +} + +QT_END_NAMESPACE + + diff --git a/src/declarative/qml/parser/qmljsparser_p.h b/src/declarative/qml/parser/qmljsparser_p.h new file mode 100644 index 0000000..cd2c7f5 --- /dev/null +++ b/src/declarative/qml/parser/qmljsparser_p.h @@ -0,0 +1,208 @@ +// This file was generated by qlalr - DO NOT EDIT! + +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +#ifndef QMLJSPARSER_P_H +#define QMLJSPARSER_P_H + +#include "qmljsgrammar_p.h" +#include "qmljsast_p.h" +#include "qmljsengine_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QString; + +namespace QmlJS { + +class Engine; +class NameId; + +class Parser: protected QmlJSGrammar +{ +public: + union Value { + int ival; + double dval; + NameId *sval; + AST::ArgumentList *ArgumentList; + AST::CaseBlock *CaseBlock; + AST::CaseClause *CaseClause; + AST::CaseClauses *CaseClauses; + AST::Catch *Catch; + AST::DefaultClause *DefaultClause; + AST::ElementList *ElementList; + AST::Elision *Elision; + AST::ExpressionNode *Expression; + AST::Finally *Finally; + AST::FormalParameterList *FormalParameterList; + AST::FunctionBody *FunctionBody; + AST::FunctionDeclaration *FunctionDeclaration; + AST::Node *Node; + AST::PropertyName *PropertyName; + AST::PropertyNameAndValueList *PropertyNameAndValueList; + AST::SourceElement *SourceElement; + AST::SourceElements *SourceElements; + AST::Statement *Statement; + AST::StatementList *StatementList; + AST::Block *Block; + AST::VariableDeclaration *VariableDeclaration; + AST::VariableDeclarationList *VariableDeclarationList; + + AST::UiProgram *UiProgram; + AST::UiImportList *UiImportList; + AST::UiImport *UiImport; + AST::UiPublicMember *UiPublicMember; + AST::UiObjectDefinition *UiObjectDefinition; + AST::UiObjectInitializer *UiObjectInitializer; + AST::UiObjectBinding *UiObjectBinding; + AST::UiScriptBinding *UiScriptBinding; + AST::UiArrayBinding *UiArrayBinding; + AST::UiObjectMember *UiObjectMember; + AST::UiObjectMemberList *UiObjectMemberList; + AST::UiArrayMemberList *UiArrayMemberList; + AST::UiQualifiedId *UiQualifiedId; + }; + +public: + Parser(Engine *engine); + ~Parser(); + + bool parse(); + + AST::UiProgram *ast() + { return program; } + + QList diagnosticMessages() const + { return diagnostic_messages; } + + inline DiagnosticMessage diagnosticMessage() const + { + foreach (const DiagnosticMessage &d, diagnostic_messages) { + if (! d.kind == DiagnosticMessage::Warning) + return d; + } + + return DiagnosticMessage(); + } + + inline QString errorMessage() const + { return diagnosticMessage().message; } + + inline int errorLineNumber() const + { return diagnosticMessage().loc.startLine; } + + inline int errorColumnNumber() const + { return diagnosticMessage().loc.startColumn; } + +protected: + void reallocateStack(); + + inline Value &sym(int index) + { return sym_stack [tos + index - 1]; } + + inline AST::SourceLocation &loc(int index) + { return location_stack [tos + index - 1]; } + + AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); + +protected: + Engine *driver; + int tos; + int stack_size; + Value *sym_stack; + int *state_stack; + AST::SourceLocation *location_stack; + + AST::UiProgram *program; + + // error recovery + enum { TOKEN_BUFFER_SIZE = 3 }; + + struct SavedToken { + int token; + double dval; + AST::SourceLocation loc; + }; + + double yylval; + AST::SourceLocation yylloc; + AST::SourceLocation yyprevlloc; + + SavedToken token_buffer[TOKEN_BUFFER_SIZE]; + SavedToken *first_token; + SavedToken *last_token; + + QList diagnostic_messages; +}; + +} // end of namespace QmlJS + + + +#define J_SCRIPT_REGEXPLITERAL_RULE1 54 + +#define J_SCRIPT_REGEXPLITERAL_RULE2 55 + +QT_END_NAMESPACE + + + +#endif // QMLJSPARSER_P_H diff --git a/src/declarative/qml/parser/qmljsprettypretty.cpp b/src/declarative/qml/parser/qmljsprettypretty.cpp new file mode 100644 index 0000000..1045792 --- /dev/null +++ b/src/declarative/qml/parser/qmljsprettypretty.cpp @@ -0,0 +1,1334 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 "qmljsprettypretty_p.h" + + + +#include "qmljsengine_p.h" + + + + +#include "qmljsast_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QmlJS { +QString numberToString(double value); +} + +using namespace QmlJS; + +PrettyPretty::PrettyPretty(QTextStream &o): + out(o), m_indentLevel(0) +{ +} + +PrettyPretty::~PrettyPretty() +{ +} + +void PrettyPretty::acceptAsBlock(AST::Node *node) +{ + out << "{"; + pushIndentLevel(); + newlineAndIndent(); + accept(node); + popIndentLevel(); + newlineAndIndent(); + out << "}"; +} + +int PrettyPretty::operatorPrecedenceLevel(int op) +{ + switch (op) { + case QSOperator::Div: + case QSOperator::Mod: + case QSOperator::Mul: + return 5; + case QSOperator::Add: + case QSOperator::Sub: + return 6; + case QSOperator::LShift: + case QSOperator::RShift: + case QSOperator::URShift: + return 7; + case QSOperator::Ge: + case QSOperator::Gt: + case QSOperator::In: + case QSOperator::InstanceOf: + case QSOperator::Le: + case QSOperator::Lt: + return 8; + case QSOperator::Equal: + case QSOperator::NotEqual: + case QSOperator::StrictEqual: + case QSOperator::StrictNotEqual: + return 9; + case QSOperator::BitAnd: + return 10; + case QSOperator::BitXor: + return 11; + case QSOperator::BitOr: + return 12; + case QSOperator::And: + return 13; + case QSOperator::Or: + return 14; + case QSOperator::InplaceAnd: + case QSOperator::InplaceSub: + case QSOperator::InplaceDiv: + case QSOperator::InplaceAdd: + case QSOperator::InplaceLeftShift: + case QSOperator::InplaceMod: + case QSOperator::InplaceMul: + case QSOperator::InplaceOr: + case QSOperator::InplaceRightShift: + case QSOperator::InplaceURightShift: + case QSOperator::InplaceXor: + case QSOperator::Assign: + return 16; + default: + Q_ASSERT_X(false, "PrettyPretty::operatorPrecedenceLevel()", "bad operator"); + } + return 0; +} + +int PrettyPretty::compareOperatorPrecedence(int op1, int op2) +{ + int prec1 = operatorPrecedenceLevel(op1); + int prec2 = operatorPrecedenceLevel(op2); + if (prec1 == prec2) + return 0; + if (prec1 > prec2) + return -1; + return 1; +} + +QTextStream &PrettyPretty::operator () (AST::Node *node, int level) +{ + int was = indentLevel(level); + accept(node); + indentLevel(was); + return out; +} + +QTextStream &PrettyPretty::newlineAndIndent() +{ + enum { IND = 4 }; + out << endl << QString().fill(QLatin1Char(' '), m_indentLevel * IND); + return out; +} + +void PrettyPretty::accept(AST::Node *node) +{ + AST::Node::acceptChild(node, this); +} + +bool PrettyPretty::visit(AST::ThisExpression *node) +{ + Q_UNUSED(node); + out << "this"; + return true; +} + +void PrettyPretty::endVisit(AST::ThisExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::IdentifierExpression *node) +{ + out << Engine::toString(node->name); + return true; +} + +void PrettyPretty::endVisit(AST::IdentifierExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::NullExpression *node) +{ + Q_UNUSED(node); + out << "null"; + return false; +} + +void PrettyPretty::endVisit(AST::NullExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::TrueLiteral *node) +{ + Q_UNUSED(node); + out << "true"; + return false; +} + +void PrettyPretty::endVisit(AST::TrueLiteral *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::FalseLiteral *node) +{ + Q_UNUSED(node); + out << "false"; + return false; +} + +void PrettyPretty::endVisit(AST::FalseLiteral *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::StringLiteral *node) +{ + QString lit = Engine::toString(node->value); + lit.replace(QLatin1String("\\"), QLatin1String("\\\\")); + out << "\"" << lit << "\""; + return false; +} + +void PrettyPretty::endVisit(AST::StringLiteral *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::NumericLiteral *node) +{ + out << QmlJS::numberToString(node->value); + return true; +} + +void PrettyPretty::endVisit(AST::NumericLiteral *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::RegExpLiteral *node) +{ + out << "/" << Engine::toString(node->pattern) << "/"; + if (node->flags) + out << QmlJS::Ecma::RegExp::flagsToString(node->flags); + + return true; +} + +void PrettyPretty::endVisit(AST::RegExpLiteral *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ArrayLiteral *node) +{ + out << "["; + accept(node->elements); + accept(node->elision); + out << "]"; + return false; +} + +void PrettyPretty::endVisit(AST::ArrayLiteral *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ObjectLiteral *node) +{ + out << "{"; + if (node->properties) { + pushIndentLevel(); + AST::PropertyNameAndValueList *prop; + for (prop = node->properties; prop != 0; prop = prop->next) { + newlineAndIndent(); + accept(prop); + if (prop->next) + out << ","; + } + popIndentLevel(); + newlineAndIndent(); + } + out << "}"; + return false; +} + +void PrettyPretty::endVisit(AST::ObjectLiteral *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ElementList *node) +{ + accept(node->elision); + accept(node->expression); + for (node = node->next; node != 0; node = node->next) { + out << ", "; + accept(node->elision); + accept(node->expression); + } + return false; +} + +void PrettyPretty::endVisit(AST::ElementList *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::Elision *node) +{ + out << ", "; + for (AST::Elision *eit = node->next; eit != 0; eit = eit->next) + out << ", "; + return false; +} + +void PrettyPretty::endVisit(AST::Elision *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::PropertyNameAndValueList *node) +{ + accept(node->name); + out << ": "; + accept(node->value); + return false; +} + +void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::IdentifierPropertyName *node) +{ + out << Engine::toString(node->id); + return false; +} + +void PrettyPretty::endVisit(AST::IdentifierPropertyName *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::StringLiteralPropertyName *node) +{ + QString lit = Engine::toString(node->id); + lit.replace(QLatin1String("\\"), QLatin1String("\\\\")); + out << lit; + return false; +} + +void PrettyPretty::endVisit(AST::StringLiteralPropertyName *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node) +{ + out << node->id; + return false; +} + +void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ArrayMemberExpression *node) +{ + accept(node->base); + out << "["; + accept(node->expression); + out << "]"; + return false; +} + +void PrettyPretty::endVisit(AST::ArrayMemberExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::FieldMemberExpression *node) +{ + accept(node->base); + out << "." << Engine::toString(node->name); + return false; +} + +void PrettyPretty::endVisit(AST::FieldMemberExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::NewMemberExpression *node) +{ + out << "new "; + accept(node->base); + out << "("; + accept(node->arguments); + out << ")"; + return false; +} + +void PrettyPretty::endVisit(AST::NewMemberExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::NewExpression *node) +{ + Q_UNUSED(node); + out << "new "; + return true; +} + +void PrettyPretty::endVisit(AST::NewExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::CallExpression *node) +{ + accept(node->base); + out << "("; + accept(node->arguments); + out << ")"; + return false; +} + +void PrettyPretty::endVisit(AST::CallExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ArgumentList *node) +{ + accept(node->expression); + for (node = node->next; node != 0; node = node->next) { + out << ", "; + accept(node->expression); + } + return false; +} + +void PrettyPretty::endVisit(AST::ArgumentList *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::PostIncrementExpression *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::PostIncrementExpression *node) +{ + Q_UNUSED(node); + out << "++"; +} + +bool PrettyPretty::visit(AST::PostDecrementExpression *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::PostDecrementExpression *node) +{ + Q_UNUSED(node); + out << "--"; +} + +bool PrettyPretty::visit(AST::DeleteExpression *node) +{ + Q_UNUSED(node); + out << "delete "; + return true; +} + +void PrettyPretty::endVisit(AST::DeleteExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::VoidExpression *node) +{ + Q_UNUSED(node); + out << "void "; + return true; +} + +void PrettyPretty::endVisit(AST::VoidExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::TypeOfExpression *node) +{ + Q_UNUSED(node); + out << "typeof "; + return true; +} + +void PrettyPretty::endVisit(AST::TypeOfExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::PreIncrementExpression *node) +{ + Q_UNUSED(node); + out << "++"; + return true; +} + +void PrettyPretty::endVisit(AST::PreIncrementExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::PreDecrementExpression *node) +{ + Q_UNUSED(node); + out << "--"; + return true; +} + +void PrettyPretty::endVisit(AST::PreDecrementExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::UnaryPlusExpression *node) +{ + out << "+"; + bool needParens = (node->expression->binaryExpressionCast() != 0); + if (needParens) + out << "("; + accept(node->expression); + if (needParens) + out << ")"; + return false; +} + +void PrettyPretty::endVisit(AST::UnaryPlusExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::UnaryMinusExpression *node) +{ + out << "-"; + bool needParens = (node->expression->binaryExpressionCast() != 0); + if (needParens) + out << "("; + accept(node->expression); + if (needParens) + out << ")"; + return false; +} + +void PrettyPretty::endVisit(AST::UnaryMinusExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::TildeExpression *node) +{ + out << "~"; + bool needParens = (node->expression->binaryExpressionCast() != 0); + if (needParens) + out << "("; + accept(node->expression); + if (needParens) + out << ")"; + return false; +} + +void PrettyPretty::endVisit(AST::TildeExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::NotExpression *node) +{ + out << "!"; + bool needParens = (node->expression->binaryExpressionCast() != 0); + if (needParens) + out << "("; + accept(node->expression); + if (needParens) + out << ")"; + return false; +} + +void PrettyPretty::endVisit(AST::NotExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::BinaryExpression *node) +{ + bool needParens = node->left->binaryExpressionCast() + && (compareOperatorPrecedence(node->left->binaryExpressionCast()->op, node->op) < 0); + if (needParens) + out << "("; + accept(node->left); + if (needParens) + out << ")"; + QString s; + switch (node->op) { + case QSOperator::Add: + s = QLatin1String("+"); break; + case QSOperator::And: + s = QLatin1String("&&"); break; + case QSOperator::InplaceAnd: + s = QLatin1String("&="); break; + case QSOperator::Assign: + s = QLatin1String("="); break; + case QSOperator::BitAnd: + s = QLatin1String("&"); break; + case QSOperator::BitOr: + s = QLatin1String("|"); break; + case QSOperator::BitXor: + s = QLatin1String("^"); break; + case QSOperator::InplaceSub: + s = QLatin1String("-="); break; + case QSOperator::Div: + s = QLatin1String("/"); break; + case QSOperator::InplaceDiv: + s = QLatin1String("/="); break; + case QSOperator::Equal: + s = QLatin1String("=="); break; + case QSOperator::Ge: + s = QLatin1String(">="); break; + case QSOperator::Gt: + s = QLatin1String(">"); break; + case QSOperator::In: + s = QLatin1String("in"); break; + case QSOperator::InplaceAdd: + s = QLatin1String("+="); break; + case QSOperator::InstanceOf: + s = QLatin1String("instanceof"); break; + case QSOperator::Le: + s = QLatin1String("<="); break; + case QSOperator::LShift: + s = QLatin1String("<<"); break; + case QSOperator::InplaceLeftShift: + s = QLatin1String("<<="); break; + case QSOperator::Lt: + s = QLatin1String("<"); break; + case QSOperator::Mod: + s = QLatin1String("%"); break; + case QSOperator::InplaceMod: + s = QLatin1String("%="); break; + case QSOperator::Mul: + s = QLatin1String("*"); break; + case QSOperator::InplaceMul: + s = QLatin1String("*="); break; + case QSOperator::NotEqual: + s = QLatin1String("!="); break; + case QSOperator::Or: + s = QLatin1String("||"); break; + case QSOperator::InplaceOr: + s = QLatin1String("|="); break; + case QSOperator::RShift: + s = QLatin1String(">>"); break; + case QSOperator::InplaceRightShift: + s = QLatin1String(">>="); break; + case QSOperator::StrictEqual: + s = QLatin1String("==="); break; + case QSOperator::StrictNotEqual: + s = QLatin1String("!=="); break; + case QSOperator::Sub: + s = QLatin1String("-"); break; + case QSOperator::URShift: + s = QLatin1String(">>>"); break; + case QSOperator::InplaceURightShift: + s = QLatin1String(">>>="); break; + case QSOperator::InplaceXor: + s = QLatin1String("^="); break; + default: + Q_ASSERT (0); + } + out << " " << s << " "; + needParens = node->right->binaryExpressionCast() + && (compareOperatorPrecedence(node->right->binaryExpressionCast()->op, node->op) <= 0); + if (needParens) + out << "("; + accept(node->right); + if (needParens) + out << ")"; + return false; +} + +void PrettyPretty::endVisit(AST::BinaryExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ConditionalExpression *node) +{ + accept(node->expression); + out << " ? "; + accept(node->ok); + out << " : "; + accept(node->ko); + return false; +} + +void PrettyPretty::endVisit(AST::ConditionalExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::Expression *node) +{ + accept(node->left); + out << ", "; + accept(node->right); + return false; +} + +void PrettyPretty::endVisit(AST::Expression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::Block *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::Block *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::StatementList *node) +{ + accept(node->statement); + for (node = node->next; node != 0; node = node->next) { + newlineAndIndent(); + accept(node->statement); + } + return false; +} + +void PrettyPretty::endVisit(AST::StatementList *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::VariableDeclarationList *node) +{ + AST::VariableDeclarationList *it = node; + + do { + it->declaration->accept(this); + it = it->next; + if (it) + out << ", "; + } while (it); + + return false; +} + +void PrettyPretty::endVisit(AST::VariableDeclarationList *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::VariableStatement *node) +{ + out << "var "; + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::VariableStatement *node) +{ + Q_UNUSED(node); + out << ";"; +} + +bool PrettyPretty::visit(AST::VariableDeclaration *node) +{ + out << Engine::toString(node->name); + if (node->expression) { + out << " = "; + accept(node->expression); + } + return false; +} + +void PrettyPretty::endVisit(AST::VariableDeclaration *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::EmptyStatement *node) +{ + Q_UNUSED(node); + out << ";"; + return true; +} + +void PrettyPretty::endVisit(AST::EmptyStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ExpressionStatement *node) +{ + accept(node->expression); + out << ";"; + return false; +} + +void PrettyPretty::endVisit(AST::ExpressionStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::IfStatement *node) +{ + out << "if ("; + accept(node->expression); + out << ") "; + acceptAsBlock(node->ok); + if (node->ko) { + out << " else "; + acceptAsBlock(node->ko); + } + return false; +} + +void PrettyPretty::endVisit(AST::IfStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::DoWhileStatement *node) +{ + out << "do "; + acceptAsBlock(node->statement); + out << " while ("; + accept(node->expression); + out << ");"; + return false; +} + +void PrettyPretty::endVisit(AST::DoWhileStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::WhileStatement *node) +{ + out << "while ("; + accept(node->expression); + out << ") "; + acceptAsBlock(node->statement); + return false; +} + +void PrettyPretty::endVisit(AST::WhileStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ForStatement *node) +{ + out << "for ("; + accept(node->initialiser); + out << "; "; + accept(node->condition); + out << "; "; + accept(node->expression); + out << ") "; + acceptAsBlock(node->statement); + return false; +} + +void PrettyPretty::endVisit(AST::ForStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::LocalForStatement *node) +{ + out << "for (var "; + accept(node->declarations); + out << "; "; + accept(node->condition); + out << "; "; + accept(node->expression); + out << ") "; + acceptAsBlock(node->statement); + return false; +} + +void PrettyPretty::endVisit(AST::LocalForStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ForEachStatement *node) +{ + out << "for ("; + accept(node->initialiser); + out << " in "; + accept(node->expression); + out << ") "; + acceptAsBlock(node->statement); + return false; +} + +void PrettyPretty::endVisit(AST::ForEachStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::LocalForEachStatement *node) +{ + out << "for (var "; + accept(node->declaration); + out << " in "; + accept(node->expression); + out << ") "; + acceptAsBlock(node->statement); + return false; +} + +void PrettyPretty::endVisit(AST::LocalForEachStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ContinueStatement *node) +{ + out << "continue"; + if (node->label) { + out << " " << Engine::toString(node->label); + } + out << ";"; + return false; +} + +void PrettyPretty::endVisit(AST::ContinueStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::BreakStatement *node) +{ + out << "break"; + if (node->label) { + out << " " << Engine::toString(node->label); + } + out << ";"; + return false; +} + +void PrettyPretty::endVisit(AST::BreakStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ReturnStatement *node) +{ + out << "return"; + if (node->expression) { + out << " "; + accept(node->expression); + } + out << ";"; + return false; +} + +void PrettyPretty::endVisit(AST::ReturnStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::WithStatement *node) +{ + out << "with ("; + accept(node->expression); + out << ") "; + acceptAsBlock(node->statement); + return false; +} + +void PrettyPretty::endVisit(AST::WithStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::SwitchStatement *node) +{ + out << "switch ("; + accept(node->expression); + out << ") "; + acceptAsBlock(node->block); + return false; +} + +void PrettyPretty::endVisit(AST::SwitchStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::CaseBlock *node) +{ + accept(node->clauses); + if (node->defaultClause) { + newlineAndIndent(); + accept(node->defaultClause); + } + if (node->moreClauses) { + newlineAndIndent(); + accept(node->moreClauses); + } + return false; +} + +void PrettyPretty::endVisit(AST::CaseBlock *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::CaseClauses *node) +{ + accept(node->clause); + for (node = node->next; node != 0; node = node->next) { + newlineAndIndent(); + accept(node->clause); + } + return false; +} + +void PrettyPretty::endVisit(AST::CaseClauses *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::CaseClause *node) +{ + out << "case "; + accept(node->expression); + out << ":"; + if (node->statements) { + newlineAndIndent(); + accept(node->statements); + } + return false; +} + +void PrettyPretty::endVisit(AST::CaseClause *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::DefaultClause *node) +{ + Q_UNUSED(node); + out << "default:"; + newlineAndIndent(); + return true; +} + +void PrettyPretty::endVisit(AST::DefaultClause *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::LabelledStatement *node) +{ + out << Engine::toString(node->label) << ": "; + return true; +} + +void PrettyPretty::endVisit(AST::LabelledStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::ThrowStatement *node) +{ + Q_UNUSED(node); + out << "throw "; + accept(node->expression); + out << ";"; + return false; +} + +void PrettyPretty::endVisit(AST::ThrowStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::TryStatement *node) +{ + out << "try "; + acceptAsBlock(node->statement); + if (node->catchExpression) { + out << " catch (" << Engine::toString(node->catchExpression->name) << ") "; + acceptAsBlock(node->catchExpression->statement); + } + if (node->finallyExpression) { + out << " finally "; + acceptAsBlock(node->finallyExpression->statement); + } + return false; +} + +void PrettyPretty::endVisit(AST::TryStatement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::Catch *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::Catch *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::Finally *node) +{ + Q_UNUSED(node); + out << "finally "; + return true; +} + +void PrettyPretty::endVisit(AST::Finally *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::FunctionDeclaration *node) +{ + out << "function"; + + if (node->name) + out << " " << Engine::toString(node->name); + + // the arguments + out << "("; + for (AST::FormalParameterList *it = node->formals; it; it = it->next) { + if (it->name) + out << Engine::toString(it->name); + + if (it->next) + out << ", "; + } + out << ")"; + + // the function body + out << " {"; + + if (node->body) { + pushIndentLevel(); + newlineAndIndent(); + accept(node->body); + popIndentLevel(); + newlineAndIndent(); + } + + out << "}"; + + return false; +} + +void PrettyPretty::endVisit(AST::FunctionDeclaration *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::FunctionExpression *node) +{ + out << "function"; + + if (node->name) + out << " " << Engine::toString(node->name); + + // the arguments + out << "("; + for (AST::FormalParameterList *it = node->formals; it; it = it->next) { + if (it->name) + out << Engine::toString(it->name); + + if (it->next) + out << ", "; + } + out << ")"; + + // the function body + out << " {"; + + if (node->body) { + pushIndentLevel(); + newlineAndIndent(); + accept(node->body); + popIndentLevel(); + newlineAndIndent(); + } + + out << "}"; + + return false; +} + +void PrettyPretty::endVisit(AST::FunctionExpression *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::FormalParameterList *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::FormalParameterList *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::FunctionBody *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::FunctionBody *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::Program *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::Program *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::SourceElements *node) +{ + Q_UNUSED(node); + accept(node->element); + for (node = node->next; node != 0; node = node->next) { + newlineAndIndent(); + accept(node->element); + } + return false; +} + +void PrettyPretty::endVisit(AST::SourceElements *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::FunctionSourceElement *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::FunctionSourceElement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::StatementSourceElement *node) +{ + Q_UNUSED(node); + return true; +} + +void PrettyPretty::endVisit(AST::StatementSourceElement *node) +{ + Q_UNUSED(node); +} + +bool PrettyPretty::visit(AST::DebuggerStatement *node) +{ + Q_UNUSED(node); + out << "debugger"; + return true; +} + +void PrettyPretty::endVisit(AST::DebuggerStatement *node) +{ + Q_UNUSED(node); + out << ";"; +} + +bool PrettyPretty::preVisit(AST::Node *node) +{ + Q_UNUSED(node); + return true; +} + +QT_END_NAMESPACE + + diff --git a/src/declarative/qml/parser/qmljsprettypretty_p.h b/src/declarative/qml/parser/qmljsprettypretty_p.h new file mode 100644 index 0000000..fe82ca2 --- /dev/null +++ b/src/declarative/qml/parser/qmljsprettypretty_p.h @@ -0,0 +1,329 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtScript module 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 QMLJSPRETTYPRETTY_P_H +#define QMLJSPRETTYPRETTY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include "qmljsastvisitor_p.h" + +QT_BEGIN_NAMESPACE + +class QTextStream; + +namespace QmlJS { + +class PrettyPretty: protected AST::Visitor +{ +public: + PrettyPretty(QTextStream &out); + virtual ~PrettyPretty(); + + QTextStream &operator () (AST::Node *node, int level = 0); + +protected: + void accept(AST::Node *node); + + virtual bool preVisit(AST::Node *node); + + virtual bool visit(AST::ThisExpression *node); + virtual void endVisit(AST::ThisExpression *node); + + virtual bool visit(AST::IdentifierExpression *node); + virtual void endVisit(AST::IdentifierExpression *node); + + virtual bool visit(AST::NullExpression *node); + virtual void endVisit(AST::NullExpression *node); + + virtual bool visit(AST::TrueLiteral *node); + virtual void endVisit(AST::TrueLiteral *node); + + virtual bool visit(AST::FalseLiteral *node); + virtual void endVisit(AST::FalseLiteral *node); + + virtual bool visit(AST::StringLiteral *node); + virtual void endVisit(AST::StringLiteral *node); + + virtual bool visit(AST::NumericLiteral *node); + virtual void endVisit(AST::NumericLiteral *node); + + virtual bool visit(AST::RegExpLiteral *node); + virtual void endVisit(AST::RegExpLiteral *node); + + virtual bool visit(AST::ArrayLiteral *node); + virtual void endVisit(AST::ArrayLiteral *node); + + virtual bool visit(AST::ObjectLiteral *node); + virtual void endVisit(AST::ObjectLiteral *node); + + virtual bool visit(AST::ElementList *node); + virtual void endVisit(AST::ElementList *node); + + virtual bool visit(AST::Elision *node); + virtual void endVisit(AST::Elision *node); + + virtual bool visit(AST::PropertyNameAndValueList *node); + virtual void endVisit(AST::PropertyNameAndValueList *node); + + virtual bool visit(AST::IdentifierPropertyName *node); + virtual void endVisit(AST::IdentifierPropertyName *node); + + virtual bool visit(AST::StringLiteralPropertyName *node); + virtual void endVisit(AST::StringLiteralPropertyName *node); + + virtual bool visit(AST::NumericLiteralPropertyName *node); + virtual void endVisit(AST::NumericLiteralPropertyName *node); + + virtual bool visit(AST::ArrayMemberExpression *node); + virtual void endVisit(AST::ArrayMemberExpression *node); + + virtual bool visit(AST::FieldMemberExpression *node); + virtual void endVisit(AST::FieldMemberExpression *node); + + virtual bool visit(AST::NewMemberExpression *node); + virtual void endVisit(AST::NewMemberExpression *node); + + virtual bool visit(AST::NewExpression *node); + virtual void endVisit(AST::NewExpression *node); + + virtual bool visit(AST::CallExpression *node); + virtual void endVisit(AST::CallExpression *node); + + virtual bool visit(AST::ArgumentList *node); + virtual void endVisit(AST::ArgumentList *node); + + virtual bool visit(AST::PostIncrementExpression *node); + virtual void endVisit(AST::PostIncrementExpression *node); + + virtual bool visit(AST::PostDecrementExpression *node); + virtual void endVisit(AST::PostDecrementExpression *node); + + virtual bool visit(AST::DeleteExpression *node); + virtual void endVisit(AST::DeleteExpression *node); + + virtual bool visit(AST::VoidExpression *node); + virtual void endVisit(AST::VoidExpression *node); + + virtual bool visit(AST::TypeOfExpression *node); + virtual void endVisit(AST::TypeOfExpression *node); + + virtual bool visit(AST::PreIncrementExpression *node); + virtual void endVisit(AST::PreIncrementExpression *node); + + virtual bool visit(AST::PreDecrementExpression *node); + virtual void endVisit(AST::PreDecrementExpression *node); + + virtual bool visit(AST::UnaryPlusExpression *node); + virtual void endVisit(AST::UnaryPlusExpression *node); + + virtual bool visit(AST::UnaryMinusExpression *node); + virtual void endVisit(AST::UnaryMinusExpression *node); + + virtual bool visit(AST::TildeExpression *node); + virtual void endVisit(AST::TildeExpression *node); + + virtual bool visit(AST::NotExpression *node); + virtual void endVisit(AST::NotExpression *node); + + virtual bool visit(AST::BinaryExpression *node); + virtual void endVisit(AST::BinaryExpression *node); + + virtual bool visit(AST::ConditionalExpression *node); + virtual void endVisit(AST::ConditionalExpression *node); + + virtual bool visit(AST::Expression *node); + virtual void endVisit(AST::Expression *node); + + virtual bool visit(AST::Block *node); + virtual void endVisit(AST::Block *node); + + virtual bool visit(AST::StatementList *node); + virtual void endVisit(AST::StatementList *node); + + virtual bool visit(AST::VariableStatement *node); + virtual void endVisit(AST::VariableStatement *node); + + virtual bool visit(AST::VariableDeclarationList *node); + virtual void endVisit(AST::VariableDeclarationList *node); + + virtual bool visit(AST::VariableDeclaration *node); + virtual void endVisit(AST::VariableDeclaration *node); + + virtual bool visit(AST::EmptyStatement *node); + virtual void endVisit(AST::EmptyStatement *node); + + virtual bool visit(AST::ExpressionStatement *node); + virtual void endVisit(AST::ExpressionStatement *node); + + virtual bool visit(AST::IfStatement *node); + virtual void endVisit(AST::IfStatement *node); + + virtual bool visit(AST::DoWhileStatement *node); + virtual void endVisit(AST::DoWhileStatement *node); + + virtual bool visit(AST::WhileStatement *node); + virtual void endVisit(AST::WhileStatement *node); + + virtual bool visit(AST::ForStatement *node); + virtual void endVisit(AST::ForStatement *node); + + virtual bool visit(AST::LocalForStatement *node); + virtual void endVisit(AST::LocalForStatement *node); + + virtual bool visit(AST::ForEachStatement *node); + virtual void endVisit(AST::ForEachStatement *node); + + virtual bool visit(AST::LocalForEachStatement *node); + virtual void endVisit(AST::LocalForEachStatement *node); + + virtual bool visit(AST::ContinueStatement *node); + virtual void endVisit(AST::ContinueStatement *node); + + virtual bool visit(AST::BreakStatement *node); + virtual void endVisit(AST::BreakStatement *node); + + virtual bool visit(AST::ReturnStatement *node); + virtual void endVisit(AST::ReturnStatement *node); + + virtual bool visit(AST::WithStatement *node); + virtual void endVisit(AST::WithStatement *node); + + virtual bool visit(AST::SwitchStatement *node); + virtual void endVisit(AST::SwitchStatement *node); + + virtual bool visit(AST::CaseBlock *node); + virtual void endVisit(AST::CaseBlock *node); + + virtual bool visit(AST::CaseClauses *node); + virtual void endVisit(AST::CaseClauses *node); + + virtual bool visit(AST::CaseClause *node); + virtual void endVisit(AST::CaseClause *node); + + virtual bool visit(AST::DefaultClause *node); + virtual void endVisit(AST::DefaultClause *node); + + virtual bool visit(AST::LabelledStatement *node); + virtual void endVisit(AST::LabelledStatement *node); + + virtual bool visit(AST::ThrowStatement *node); + virtual void endVisit(AST::ThrowStatement *node); + + virtual bool visit(AST::TryStatement *node); + virtual void endVisit(AST::TryStatement *node); + + virtual bool visit(AST::Catch *node); + virtual void endVisit(AST::Catch *node); + + virtual bool visit(AST::Finally *node); + virtual void endVisit(AST::Finally *node); + + virtual bool visit(AST::FunctionDeclaration *node); + virtual void endVisit(AST::FunctionDeclaration *node); + + virtual bool visit(AST::FunctionExpression *node); + virtual void endVisit(AST::FunctionExpression *node); + + virtual bool visit(AST::FormalParameterList *node); + virtual void endVisit(AST::FormalParameterList *node); + + virtual bool visit(AST::FunctionBody *node); + virtual void endVisit(AST::FunctionBody *node); + + virtual bool visit(AST::Program *node); + virtual void endVisit(AST::Program *node); + + virtual bool visit(AST::SourceElements *node); + virtual void endVisit(AST::SourceElements *node); + + virtual bool visit(AST::FunctionSourceElement *node); + virtual void endVisit(AST::FunctionSourceElement *node); + + virtual bool visit(AST::StatementSourceElement *node); + virtual void endVisit(AST::StatementSourceElement *node); + + virtual bool visit(AST::DebuggerStatement *node); + virtual void endVisit(AST::DebuggerStatement *node); + + int indentLevel(int level) + { + int was = m_indentLevel; + m_indentLevel = level; + return was; + } + + void pushIndentLevel() + { ++m_indentLevel; } + + void popIndentLevel() + { --m_indentLevel; } + + QTextStream &newlineAndIndent(); + + void acceptAsBlock(AST::Node *node); + + static int operatorPrecedenceLevel(int op); + static int compareOperatorPrecedence(int op1, int op2); + +private: + QTextStream &out; + int m_indentLevel; + + Q_DISABLE_COPY(PrettyPretty) +}; + +} // namespace QmlJS + +QT_END_NAMESPACE + +#endif diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index d8e65bf..dd6766e 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -17,12 +17,12 @@ #include #include #include -#include -#include +#include +#include QT_BEGIN_NAMESPACE -using namespace JavaScript; +using namespace QmlJS; struct ScriptInstruction { enum { @@ -270,16 +270,16 @@ struct QmlBasicScriptCompiler QmlParser::Object *component; QHash > ids; - bool compile(JavaScript::AST::Node *); + bool compile(QmlJS::AST::Node *); - bool compileExpression(JavaScript::AST::Node *); + bool compileExpression(QmlJS::AST::Node *); - bool tryConstant(JavaScript::AST::Node *); - bool parseConstant(JavaScript::AST::Node *); - bool tryName(JavaScript::AST::Node *); - bool parseName(JavaScript::AST::Node *, QmlParser::Object ** = 0); - bool tryBinaryExpression(JavaScript::AST::Node *); - bool compileBinaryExpression(JavaScript::AST::Node *); + bool tryConstant(QmlJS::AST::Node *); + bool parseConstant(QmlJS::AST::Node *); + bool tryName(QmlJS::AST::Node *); + bool parseName(QmlJS::AST::Node *, QmlParser::Object ** = 0); + bool tryBinaryExpression(QmlJS::AST::Node *); + bool compileBinaryExpression(QmlJS::AST::Node *); QByteArray data; QList bytecode; @@ -288,10 +288,10 @@ struct QmlBasicScriptCompiler /*! \internal \class QmlBasicScript - \brief The QmlBasicScript class provides a fast implementation of a limited subset of JavaScript bindings. + \brief The QmlBasicScript class provides a fast implementation of a limited subset of QmlJS bindings. QmlBasicScript instances are used to accelerate binding. Instead of using - the slower, fully fledged JavaScript engine, many simple bindings can be + the slower, fully fledged QmlJS engine, many simple bindings can be evaluated using the QmlBasicScript engine. To see if the QmlBasicScript engine can handle a binding, call compile() @@ -495,12 +495,12 @@ bool QmlBasicScript::compile(const Expression &expression) return d != 0; } -bool QmlBasicScriptCompiler::compile(JavaScript::AST::Node *node) +bool QmlBasicScriptCompiler::compile(QmlJS::AST::Node *node) { return compileExpression(node); } -bool QmlBasicScriptCompiler::tryConstant(JavaScript::AST::Node *node) +bool QmlBasicScriptCompiler::tryConstant(QmlJS::AST::Node *node) { if (node->kind == AST::Node::Kind_TrueLiteral || node->kind == AST::Node::Kind_FalseLiteral) @@ -516,7 +516,7 @@ bool QmlBasicScriptCompiler::tryConstant(JavaScript::AST::Node *node) return false; } -bool QmlBasicScriptCompiler::parseConstant(JavaScript::AST::Node *node) +bool QmlBasicScriptCompiler::parseConstant(QmlJS::AST::Node *node) { ScriptInstruction instr; @@ -534,7 +534,7 @@ bool QmlBasicScriptCompiler::parseConstant(JavaScript::AST::Node *node) return true; } -bool QmlBasicScriptCompiler::tryName(JavaScript::AST::Node *node) +bool QmlBasicScriptCompiler::tryName(QmlJS::AST::Node *node) { return node->kind == AST::Node::Kind_IdentifierExpression || node->kind == AST::Node::Kind_FieldMemberExpression; @@ -629,7 +629,7 @@ bool QmlBasicScriptCompiler::parseName(AST::Node *node, return true; } -bool QmlBasicScriptCompiler::compileExpression(JavaScript::AST::Node *node) +bool QmlBasicScriptCompiler::compileExpression(QmlJS::AST::Node *node) { if (tryBinaryExpression(node)) return compileBinaryExpression(node); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index d29ac1f..3123254 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -62,7 +62,7 @@ #include "private/qmlcustomparser_p_p.h" #include #include -#include "parser/javascriptast_p.h" +#include "parser/qmljsast_p.h" #include "qmlscriptparser_p.h" @@ -1484,7 +1484,7 @@ bool QmlCompiler::compileBinding(QmlParser::Value *value, //////////////////////////////////////////////////////////////////////////////// // AST Dump //////////////////////////////////////////////////////////////////////////////// -class Dump: protected JavaScript::AST::Visitor +class Dump: protected QmlJS::AST::Visitor { std::ostream &out; int depth; @@ -1494,11 +1494,11 @@ public: : out(out), depth(-1) { } - void operator()(JavaScript::AST::Node *node) - { JavaScript::AST::Node::acceptChild(node, this); } + void operator()(QmlJS::AST::Node *node) + { QmlJS::AST::Node::acceptChild(node, this); } protected: - virtual bool preVisit(JavaScript::AST::Node *node) + virtual bool preVisit(QmlJS::AST::Node *node) { const char *name = typeid(*node).name(); #ifdef Q_CC_GNU @@ -1508,7 +1508,7 @@ protected: return true; } - virtual void postVisit(JavaScript::AST::Node *) + virtual void postVisit(QmlJS::AST::Node *) { --depth; } diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 66781ce..2c1d324 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -823,7 +823,7 @@ QScriptValue QmlEngine::qmlScriptObject(QObject* object, QmlEngine* engine) This function takes the URL of a QML file as its only argument. It returns a component object which can be used to create and load that QML file. - Example JavaScript is below, remember that QML files that might be loaded + Example QmlJS is below, remember that QML files that might be loaded over the network cannot be expected to be ready immediately. \code var component; diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index fadfbb1..5ad4a6e 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -290,7 +290,7 @@ QmlParser::Variant::Variant(const QString &v) { } -QmlParser::Variant::Variant(const QString &v, JavaScript::AST::Node *n) +QmlParser::Variant::Variant(const QString &v, QmlJS::AST::Node *n) : t(Script), n(n), s(v) { } @@ -342,7 +342,7 @@ QString QmlParser::Variant::asScript() const } } -JavaScript::AST::Node *QmlParser::Variant::asAST() const +QmlJS::AST::Node *QmlParser::Variant::asAST() const { if (type() == Script) return n; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 1481391..a38ce69 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -namespace JavaScript { namespace AST { class Node; } } +namespace QmlJS { namespace AST { class Node; } } /* XXX @@ -178,7 +178,7 @@ namespace QmlParser Variant(bool); Variant(double, const QString &asWritten=QString()); Variant(const QString &); - Variant(const QString &, JavaScript::AST::Node *); + Variant(const QString &, QmlJS::AST::Node *); Variant &operator=(const Variant &); Type type() const; @@ -192,14 +192,14 @@ namespace QmlParser QString asString() const; double asNumber() const; QString asScript() const; - JavaScript::AST::Node *asAST() const; + QmlJS::AST::Node *asAST() const; private: Type t; union { bool b; double d; - JavaScript::AST::Node *n; + QmlJS::AST::Node *n; }; QString s; }; diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index ee2981e..6c2e3e0 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -42,12 +42,12 @@ #include "qmlscriptparser_p.h" #include "qmlparser_p.h" -#include "parser/javascriptengine_p.h" -#include "parser/javascriptparser_p.h" -#include "parser/javascriptlexer_p.h" -#include "parser/javascriptnodepool_p.h" -#include "parser/javascriptastvisitor_p.h" -#include "parser/javascriptast_p.h" +#include "parser/qmljsengine_p.h" +#include "parser/qmljsparser_p.h" +#include "parser/qmljslexer_p.h" +#include "parser/qmljsnodepool_p.h" +#include "parser/qmljsastvisitor_p.h" +#include "parser/qmljsast_p.h" #include "rewriter/textwriter_p.h" @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE -using namespace JavaScript; +using namespace QmlJS; using namespace QmlParser; namespace { @@ -715,7 +715,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node) obj->dynamicSlots << slot; } else { QmlError error; - error.setDescription(QCoreApplication::translate("QmlParser","JavaScript declaration outside Script element")); + error.setDescription(QCoreApplication::translate("QmlParser","QmlJS declaration outside Script element")); error.setLine(node->firstSourceLocation().startLine); error.setColumn(node->firstSourceLocation().startColumn); _parser->_errors << error; diff --git a/src/declarative/qml/rewriter/rewriter.cpp b/src/declarative/qml/rewriter/rewriter.cpp index fce4fdf..2ce927c 100644 --- a/src/declarative/qml/rewriter/rewriter.cpp +++ b/src/declarative/qml/rewriter/rewriter.cpp @@ -40,11 +40,11 @@ ****************************************************************************/ #include "rewriter_p.h" -#include "javascriptast_p.h" +#include "qmljsast_p.h" QT_BEGIN_NAMESPACE -using namespace JavaScript; +using namespace QmlJS; void Rewriter::replace(const AST::SourceLocation &loc, const QString &text) { replace(loc.offset, loc.length, text); } @@ -76,8 +76,8 @@ QString Rewriter::textAt(const AST::SourceLocation &loc) const QString Rewriter::textAt(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc) const { return _code.mid(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset); } -void Rewriter::accept(JavaScript::AST::Node *node) -{ JavaScript::AST::Node::acceptChild(node, this); } +void Rewriter::accept(QmlJS::AST::Node *node) +{ QmlJS::AST::Node::acceptChild(node, this); } void Rewriter::moveTextBefore(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc, diff --git a/src/declarative/qml/rewriter/rewriter_p.h b/src/declarative/qml/rewriter/rewriter_p.h index 02b4ee4..fcb9ca5 100644 --- a/src/declarative/qml/rewriter/rewriter_p.h +++ b/src/declarative/qml/rewriter/rewriter_p.h @@ -46,12 +46,12 @@ #include #include "textwriter_p.h" -#include "javascriptastvisitor_p.h" +#include "qmljsastvisitor_p.h" QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -namespace JavaScript { +namespace QmlJS { //////////////////////////////////////////////////////////////////////////////// // Replacement @@ -143,7 +143,7 @@ private: QList _replacementList; }; -} // end of namespace JavaScript +} // end of namespace QmlJS QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/qml/rewriter/textwriter.cpp b/src/declarative/qml/rewriter/textwriter.cpp index 21122ff..fbbdb2bbab 100644 --- a/src/declarative/qml/rewriter/textwriter.cpp +++ b/src/declarative/qml/rewriter/textwriter.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE -using namespace JavaScript; +using namespace QmlJS; TextWriter::TextWriter() :string(0), cursor(0) diff --git a/src/declarative/qml/rewriter/textwriter_p.h b/src/declarative/qml/rewriter/textwriter_p.h index 57800bf..3041e04 100644 --- a/src/declarative/qml/rewriter/textwriter_p.h +++ b/src/declarative/qml/rewriter/textwriter_p.h @@ -49,7 +49,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -namespace JavaScript { +namespace QmlJS { class TextWriter { @@ -91,7 +91,7 @@ public: }; -} // end of namespace JavaScript +} // end of namespace QmlJS QT_END_NAMESPACE QT_END_HEADER diff --git a/tools/linguist/lupdate/qml.cpp b/tools/linguist/lupdate/qml.cpp index 78a9afd..f33eae3 100644 --- a/tools/linguist/lupdate/qml.cpp +++ b/tools/linguist/lupdate/qml.cpp @@ -49,12 +49,12 @@ QT_BEGIN_NAMESPACE -#include "parser/javascriptengine_p.h" -#include "parser/javascriptparser_p.h" -#include "parser/javascriptlexer_p.h" -#include "parser/javascriptnodepool_p.h" -#include "parser/javascriptastvisitor_p.h" -#include "parser/javascriptast_p.h" +#include "parser/qmljsengine_p.h" +#include "parser/qmljsparser_p.h" +#include "parser/qmljslexer_p.h" +#include "parser/qmljsnodepool_p.h" +#include "parser/qmljsastvisitor_p.h" +#include "parser/qmljsast_p.h" #include #include @@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE #include #include -using namespace JavaScript; +using namespace QmlJS; class FindTrCalls: protected AST::Visitor { -- cgit v0.12 From f10791eb1c45b090f60a2c2ecca3cc5fd237278e Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 11 Jun 2009 11:30:37 +0200 Subject: Getting kinetic compiling again on MacOS. --- src/gui/painting/qpaintengineex.cpp | 83 ++----------------------------------- src/gui/painting/qpaintengineex_p.h | 34 +++++++-------- src/gui/painting/qpainter.cpp | 71 +++++++++++++++++-------------- src/gui/painting/qpainter.h | 1 - src/gui/painting/qpainter_p.h | 6 +-- 5 files changed, 61 insertions(+), 134 deletions(-) diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index d2671c8..8eaad60 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -105,7 +105,7 @@ QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path) vectorPathBounds.x2 - vectorPathBounds.x1, vectorPathBounds.y2 - vectorPathBounds.y1); s << "QVectorPath(size:" << path.elementCount() << " hints:" << hex << path.hints() - << rf << ')'; + << rf << ")"; return s; } #endif @@ -138,75 +138,6 @@ QPaintEngineExPrivate::~QPaintEngineExPrivate() } -void QPaintEngineExPrivate::replayClipOperations() -{ - Q_Q(QPaintEngineEx); - - QPainter *p = q->painter(); - if (!p || !p->d_ptr) - return; - - QPainterPrivate *pp = p->d_ptr; - QList clipInfo = pp->state->clipInfo; - - QTransform transform = q->state()->matrix; - - const QTransform &redirection = q->state()->redirectionMatrix; - - for (int i = 0; i < clipInfo.size(); ++i) { - const QPainterClipInfo &info = clipInfo.at(i); - - QTransform combined = info.matrix * redirection; - - if (combined != q->state()->matrix) { - q->state()->matrix = combined; - q->transformChanged(); - } - - switch (info.clipType) { - case QPainterClipInfo::RegionClip: - q->clip(info.region, info.operation); - break; - case QPainterClipInfo::PathClip: - q->clip(info.path, info.operation); - break; - case QPainterClipInfo::RectClip: - q->clip(info.rect, info.operation); - break; - case QPainterClipInfo::RectFClip: { - qreal right = info.rectf.x() + info.rectf.width(); - qreal bottom = info.rectf.y() + info.rectf.height(); - qreal pts[] = { info.rectf.x(), info.rectf.y(), - right, info.rectf.y(), - right, bottom, - info.rectf.x(), bottom }; - QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint); - q->clip(vp, info.operation); - break; - } - } - } - - if (transform != q->state()->matrix) { - q->state()->matrix = transform; - q->transformChanged(); - } -} - - -bool QPaintEngineExPrivate::hasClipOperations() const -{ - Q_Q(const QPaintEngineEx); - - QPainter *p = q->painter(); - if (!p || !p->d_ptr) - return false; - - QPainterPrivate *pp = p->d_ptr; - QList clipInfo = pp->state->clipInfo; - - return !clipInfo.isEmpty(); -} /******************************************************************************* * @@ -313,18 +244,13 @@ static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, q ((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement); } -QPaintEngineEx::QPaintEngineEx() - : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) -{ - extended = true; -} - QPaintEngineEx::QPaintEngineEx(QPaintEngineExPrivate &data) : QPaintEngine(data, AllFeatures) { extended = true; } + QPainterState *QPaintEngineEx::createState(QPainterState *orig) const { if (!orig) @@ -557,9 +483,6 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op) void QPaintEngineEx::clip(const QRegion ®ion, Qt::ClipOperation op) { - if (region.numRects() == 1) - clip(region.boundingRect(), op); - QVector rects = region.rects(); if (rects.size() <= 32) { qreal pts[2*32*4]; @@ -855,7 +778,7 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con { QBrush brush(state()->pen.color(), pixmap); QTransform xform; - xform.translate(r.x() - s.x(), r.y() - s.y()); + xform.translate(-s.x(), -s.y()); brush.setTransform(xform); qreal pts[] = { r.x(), r.y(), diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 3f64260..593726c 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -139,13 +139,27 @@ public: QDebug Q_GUI_EXPORT &operator<<(QDebug &, const QVectorPath &path); #endif +class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate +{ +public: + QPaintEngineExPrivate(); + ~QPaintEngineExPrivate(); + + QStroker stroker; + QDashStroker dasher; + StrokeHandler *strokeHandler; + QStrokerOps *activeStroker; + QPen strokerPen; +}; + class QPixmapFilter; class Q_GUI_EXPORT QPaintEngineEx : public QPaintEngine { Q_DECLARE_PRIVATE(QPaintEngineEx) public: - QPaintEngineEx(); + inline QPaintEngineEx() + : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) { extended = true; } virtual QPainterState *createState(QPainterState *orig) const; @@ -202,30 +216,12 @@ public: inline QPainterState *state() { return static_cast(QPaintEngine::state); } inline const QPainterState *state() const { return static_cast(QPaintEngine::state); } - virtual void sync() {} - virtual QPixmapFilter *createPixmapFilter(int /*type*/) const { return 0; } protected: QPaintEngineEx(QPaintEngineExPrivate &data); }; -class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QPaintEngineEx) -public: - QPaintEngineExPrivate(); - ~QPaintEngineExPrivate(); - - void replayClipOperations(); - bool hasClipOperations() const; - - QStroker stroker; - QDashStroker dasher; - StrokeHandler *strokeHandler; - QStrokerOps *activeStroker; - QPen strokerPen; -}; inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { switch (mode) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 0ece498..cc48d24 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -281,14 +281,10 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height(); // Update matrix. - if (q->d_ptr->state->WxF) { - q->d_ptr->state->redirectionMatrix *= q->d_ptr->state->worldMatrix; - q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y()); - q->d_ptr->state->worldMatrix = QTransform(); - q->d_ptr->state->WxF = false; - } else { - q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y()); - } + if (q->d_ptr->state->WxF) + q->d_ptr->state->worldMatrix.translate(-offset.x(), -offset.y()); + else + q->d_ptr->state->redirection_offset = offset; q->d_ptr->updateMatrix(); QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func(); @@ -414,7 +410,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio bool old_txinv = txinv; QTransform old_invMatrix = invMatrix; txinv = true; - invMatrix = state->redirectionMatrix; + invMatrix = QTransform().translate(-state->redirection_offset.x(), -state->redirection_offset.y()); QPainterPath clipPath = q->clipPath(); QRectF r = clipPath.boundingRect().intersected(absPathRect); absPathRect = r.toAlignedRect(); @@ -638,7 +634,20 @@ void QPainterPrivate::updateMatrix() state->matrix *= viewTransform(); txinv = false; // no inverted matrix - state->matrix *= state->redirectionMatrix; + if (!state->redirection_offset.isNull()) { + // We want to translate in dev space so we do the adding of the redirection + // offset manually. + if (state->matrix.isAffine()) { + state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(), + state->matrix.m21(), state->matrix.m22(), + state->matrix.dx()-state->redirection_offset.x(), + state->matrix.dy()-state->redirection_offset.y()); + } else { + QTransform temp; + temp.translate(-state->redirection_offset.x(), -state->redirection_offset.y()); + state->matrix *= temp; + } + } if (extended) extended->transformChanged(); else @@ -1563,8 +1572,10 @@ void QPainter::restore() // replay the list of clip states, for (int i=0; istate->clipInfo.size(); ++i) { const QPainterClipInfo &info = d->state->clipInfo.at(i); - tmp->matrix = info.matrix; - tmp->matrix *= d->state->redirectionMatrix; + tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m13(), + info.matrix.m21(), info.matrix.m22(), info.matrix.m23(), + info.matrix.dx() - d->state->redirection_offset.x(), + info.matrix.dy() - d->state->redirection_offset.y(), info.matrix.m33()); tmp->clipOperation = info.operation; if (info.clipType == QPainterClipInfo::RectClip) { tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform; @@ -1678,7 +1689,7 @@ bool QPainter::begin(QPaintDevice *pd) d->state->painter = this; d->states.push_back(d->state); - d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y()); + d->state->redirection_offset = redirectionOffset; d->state->brushOrigin = QPointF(); if (!d->engine) { @@ -1712,8 +1723,7 @@ bool QPainter::begin(QPaintDevice *pd) // Adjust offset for alien widgets painting outside the paint event. if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId() && widget->testAttribute(Qt::WA_WState_Created)) { - const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint()); - d->state->redirectionMatrix.translate(offset.x(), offset.y()); + d->state->redirection_offset -= widget->mapTo(widget->nativeParentWidget(), QPoint()); } break; } @@ -1795,12 +1805,11 @@ bool QPainter::begin(QPaintDevice *pd) d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight); } - const QPoint coordinateOffset = d->engine->coordinateOffset(); - d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y()); + d->state->redirection_offset += d->engine->coordinateOffset(); Q_ASSERT(d->engine->isActive()); - if (!d->state->redirectionMatrix.isIdentity()) + if (!d->state->redirection_offset.isNull()) d->updateMatrix(); Q_ASSERT(d->engine->isActive()); @@ -6073,22 +6082,22 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) const QTransform &m = d->state->matrix; if (d->state->matrix.type() < QTransform::TxShear) { bool isPlain90DegreeRotation = - (qFuzzyIsNull(m.m11()) - && qFuzzyIsNull(m.m12() - qreal(1)) - && qFuzzyIsNull(m.m21() + qreal(1)) - && qFuzzyIsNull(m.m22()) + (qFuzzyCompare(m.m11() + 1, qreal(1)) + && qFuzzyCompare(m.m12(), qreal(1)) + && qFuzzyCompare(m.m21(), qreal(-1)) + && qFuzzyCompare(m.m22() + 1, qreal(1)) ) || - (qFuzzyIsNull(m.m11() + qreal(1)) - && qFuzzyIsNull(m.m12()) - && qFuzzyIsNull(m.m21()) - && qFuzzyIsNull(m.m22() + qreal(1)) + (qFuzzyCompare(m.m11(), qreal(-1)) + && qFuzzyCompare(m.m12() + 1, qreal(1)) + && qFuzzyCompare(m.m21() + 1, qreal(1)) + && qFuzzyCompare(m.m22(), qreal(-1)) ) || - (qFuzzyIsNull(m.m11()) - && qFuzzyIsNull(m.m12() + qreal(1)) - && qFuzzyIsNull(m.m21() - qreal(1)) - && qFuzzyIsNull(m.m22()) + (qFuzzyCompare(m.m11() + 1, qreal(1)) + && qFuzzyCompare(m.m12(), qreal(-1)) + && qFuzzyCompare(m.m21(), qreal(1)) + && qFuzzyCompare(m.m22() + 1, qreal(1)) ) ; aa = !isPlain90DegreeRotation; @@ -7695,7 +7704,7 @@ QPainterState::QPainterState(const QPainterState *s) clipRegion(s->clipRegion), clipPath(s->clipPath), clipOperation(s->clipOperation), renderHints(s->renderHints), clipInfo(s->clipInfo), - worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix), + worldMatrix(s->worldMatrix), matrix(s->matrix), redirection_offset(s->redirection_offset), wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh), vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh), opacity(s->opacity), WxF(s->WxF), VxF(s->VxF), diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 78cd713..f3df7a3 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -507,7 +507,6 @@ private: friend class QFontEngineXLFD; friend class QWSManager; friend class QPaintEngine; - friend class QPaintEngineExPrivate; friend class QOpenGLPaintEngine; friend class QX11PaintEngine; friend class QX11PaintEnginePrivate; diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 8d4e6c5..258b25a 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -92,8 +92,8 @@ inline Qt::PenJoinStyle qpen_joinStyle(const QPen &p) { return data_ptr(p)->join // QBrush inline functions... inline QBrush::DataPtr &data_ptr(const QBrush &p) { return const_cast(p).data_ptr(); } inline bool qbrush_fast_equals(const QBrush &a, const QBrush &b) { return data_ptr(a) == data_ptr(b); } -inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; } -inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; } +inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; }; +inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; }; inline bool qbrush_has_transform(const QBrush &b) { return data_ptr(b)->transform.type() > QTransform::TxNone; } class QPainterClipInfo @@ -158,7 +158,7 @@ public: QList clipInfo; // ### Make me smaller and faster to copy around... QTransform worldMatrix; // World transformation matrix, not window and viewport QTransform matrix; // Complete transformation matrix, - QTransform redirectionMatrix; + QPoint redirection_offset; int wx, wy, ww, wh; // window rectangle int vx, vy, vw, vh; // viewport rectangle qreal opacity; -- cgit v0.12