summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable.cpp20
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable_p.h3
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimagebase.cpp23
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview.cpp3
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstext.cpp36
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstext_p_p.h4
-rw-r--r--src/declarative/qml/qmlbindingvme.cpp261
-rw-r--r--src/declarative/qml/qmlbindingvme_p.h2
-rw-r--r--src/declarative/util/qmlpixmapcache.cpp41
-rw-r--r--tests/benchmarks/declarative/text/tst_text.cpp34
10 files changed, 303 insertions, 124 deletions
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
index 393edb6..ed70b14 100644
--- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
@@ -498,13 +498,16 @@ bool QmlGraphicsFlickable::isInteractive() const
void QmlGraphicsFlickable::setInteractive(bool interactive)
{
Q_D(QmlGraphicsFlickable);
- d->interactive = interactive;
- if (!interactive && d->flicked) {
- d->timeline.clear();
- d->vTime = d->timeline.time();
- d->flicked = false;
- emit flickingChanged();
- emit flickEnded();
+ if (interactive != d->interactive) {
+ d->interactive = interactive;
+ if (!interactive && d->flicked) {
+ d->timeline.clear();
+ d->vTime = d->timeline.time();
+ d->flicked = false;
+ emit flickingChanged();
+ emit flickEnded();
+ }
+ emit interactiveChanged();
}
}
@@ -1147,7 +1150,8 @@ bool QmlGraphicsFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
bool QmlGraphicsFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e)
{
- if (!isVisible())
+ Q_D(QmlGraphicsFlickable);
+ if (!isVisible() || !d->interactive)
return QmlGraphicsItem::sceneEventFilter(i, e);
switch (e->type()) {
case QEvent::GraphicsSceneMousePress:
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable_p.h b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
index aa29f3e..df6f6b1 100644
--- a/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
@@ -72,7 +72,7 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsFlickable : public QmlGraphicsItem
Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
Q_PROPERTY(FlickDirection flickDirection READ flickDirection WRITE setFlickDirection NOTIFY flickDirectionChanged)
- Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay)
Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged)
@@ -159,6 +159,7 @@ Q_SIGNALS:
void isAtBoundaryChanged();
void pageChanged();
void flickDirectionChanged();
+ void interactiveChanged();
protected:
virtual bool sceneEventFilter(QGraphicsItem *, QEvent *);
diff --git a/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
index 9dd9f1b..e3b98aa 100644
--- a/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
@@ -116,9 +116,26 @@ void QmlGraphicsImageBase::setSource(const QUrl &url)
if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url);
d->pendingPixmapCache = true;
- connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
- connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
- this, SLOT(requestProgress(qint64,qint64)));
+
+ static int replyDownloadProgress = -1;
+ static int replyFinished = -1;
+ static int thisRequestProgress = -1;
+ static int thisRequestFinished = -1;
+ if (replyDownloadProgress == -1) {
+ replyDownloadProgress =
+ QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished =
+ QmlPixmapReply::staticMetaObject.indexOfSignal("finished()");
+ thisRequestProgress =
+ QmlGraphicsImageBase::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
+ thisRequestFinished =
+ QmlGraphicsImageBase::staticMetaObject.indexOfSlot("requestFinished()");
+ }
+
+ QMetaObject::connect(reply, replyFinished, this,
+ thisRequestFinished, Qt::DirectConnection);
+ QMetaObject::connect(reply, replyDownloadProgress, this,
+ thisRequestProgress, Qt::DirectConnection);
} else {
//### should be unified with requestFinished
if (status == QmlPixmapReply::Ready) {
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
index 351364e..6460a69 100644
--- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
@@ -552,8 +552,7 @@ void QmlGraphicsListViewPrivate::init()
{
Q_Q(QmlGraphicsListView);
q->setFlag(QGraphicsItem::ItemIsFocusScope);
- QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(refill()));
- QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(refill()));
+ addItemChangeListener(this, Geometry);
QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
q->setFlickDirection(QmlGraphicsFlickable::VerticalFlick);
::memset(sectionCache, 0, sizeof(QmlGraphicsItem*) * sectionCacheSize);
diff --git a/src/declarative/graphicsitems/qmlgraphicstext.cpp b/src/declarative/graphicsitems/qmlgraphicstext.cpp
index 52d68fd..459541e 100644
--- a/src/declarative/graphicsitems/qmlgraphicstext.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicstext.cpp
@@ -50,10 +50,9 @@
#include <QTextCursor>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
+#include <QAbstractTextDocumentLayout>
#include <qmath.h>
-#include <private/qtextcontrol_p.h>
-
QT_BEGIN_NAMESPACE
QML_DEFINE_TYPE(Qt,4,6,Text,QmlGraphicsText)
@@ -159,11 +158,8 @@ void QmlGraphicsText::setText(const QString &n)
d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
if (d->richText) {
- if (!d->doc)
- {
- d->control = new QTextControl(this);
- d->control->setTextInteractionFlags(Qt::TextBrowserInteraction);
- d->doc = d->control->document();
+ if (!d->doc) {
+ d->doc = new QTextDocument(this);
d->doc->setDocumentMargin(0);
}
d->doc->setHtml(n);
@@ -399,11 +395,8 @@ void QmlGraphicsText::setTextFormat(TextFormat format)
d->updateSize();
d->markImgDirty();
} else if (!wasRich && d->richText) {
- if (!d->doc)
- {
- d->control = new QTextControl(this);
- d->control->setTextInteractionFlags(Qt::TextBrowserInteraction);
- d->doc = d->control->document();
+ if (!d->doc) {
+ d->doc = new QTextDocument(this);
d->doc->setDocumentMargin(0);
}
d->doc->setHtml(d->text);
@@ -643,19 +636,18 @@ QPixmap QmlGraphicsTextPrivate::richTextImage(bool drawStyle)
img.fill(Qt::transparent);
QPainter p(&img);
+ QAbstractTextDocumentLayout::PaintContext context;
+
if (drawStyle) {
- QPalette pal = control->palette();
- pal.setColor(QPalette::Text, styleColor);
- control->setPalette(pal);
+ context.palette.setColor(QPalette::Text, styleColor);
+ // ### Do we really want this?
QTextOption colorOption;
colorOption.setFlags(QTextOption::SuppressColors);
doc->setDefaultTextOption(colorOption);
} else {
- QPalette pal = control->palette();
- pal.setColor(QPalette::Text, color);
- control->setPalette(pal);
+ context.palette.setColor(QPalette::Text, color);
}
- control->drawContents(&p, QRectF(QPointF(0, 0), QSizeF(size)));
+ doc->documentLayout()->draw(&p, context);
if (drawStyle)
doc->setDefaultTextOption(QTextOption());
return img;
@@ -790,11 +782,11 @@ void QmlGraphicsText::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QmlGraphicsText);
- if (!d->richText || !d->doc || d->control->anchorAt(event->pos()).isEmpty()) {
+ if (!d->richText || !d->doc || d->doc->documentLayout()->anchorAt(event->pos()).isEmpty()) {
event->setAccepted(false);
d->activeLink = QString();
} else {
- d->activeLink = d->control->anchorAt(event->pos());
+ d->activeLink = d->doc->documentLayout()->anchorAt(event->pos());
}
// ### may malfunction if two of the same links are clicked & dragged onto each other)
@@ -819,7 +811,7 @@ void QmlGraphicsText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
Q_D(QmlGraphicsText);
// ### confirm the link, and send a signal out
- if (d->richText && d->doc && d->activeLink == d->control->anchorAt(event->pos()))
+ if (d->richText && d->doc && d->activeLink == d->doc->documentLayout()->anchorAt(event->pos()))
emit linkActivated(d->activeLink);
else
event->setAccepted(false);
diff --git a/src/declarative/graphicsitems/qmlgraphicstext_p_p.h b/src/declarative/graphicsitems/qmlgraphicstext_p_p.h
index 7e77c69..79d1a4f 100644
--- a/src/declarative/graphicsitems/qmlgraphicstext_p_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicstext_p_p.h
@@ -64,7 +64,6 @@ QT_BEGIN_NAMESPACE
class QTextLayout;
class QTextDocument;
-class QTextControl;
class QmlGraphicsTextPrivate : public QmlGraphicsItemPrivate
{
@@ -73,7 +72,7 @@ public:
QmlGraphicsTextPrivate()
: color((QRgb)0), style(QmlGraphicsText::Normal), imgDirty(true),
hAlign(QmlGraphicsText::AlignLeft), vAlign(QmlGraphicsText::AlignTop), elideMode(QmlGraphicsText::ElideNone),
- dirty(true), wrap(false), richText(false), singleline(false), control(0), doc(0),
+ dirty(true), wrap(false), richText(false), singleline(false), doc(0),
format(QmlGraphicsText::AutoText)
{
}
@@ -112,7 +111,6 @@ public:
bool wrap:1;
bool richText:1;
bool singleline:1;
- QTextControl *control;
QTextDocument *doc;
QTextLayout layout;
QSize cachedLayoutSize;
diff --git a/src/declarative/qml/qmlbindingvme.cpp b/src/declarative/qml/qmlbindingvme.cpp
index ab2aed5..01c7a4b 100644
--- a/src/declarative/qml/qmlbindingvme.cpp
+++ b/src/declarative/qml/qmlbindingvme.cpp
@@ -72,6 +72,10 @@ struct Register {
void *typeDataPtr() { return (void *)&data; }
void *typeMemory() { return (void *)data; }
+ int gettype() { return type; }
+ void settype(int t) { type = t; }
+
+ int type; // Optional type
void *data[2]; // Object stored here
};
@@ -93,9 +97,11 @@ struct Instr {
Real, // real_value
Int, // int_value
Bool, // bool_value
+ String, // string_value
AddReal, // binaryop
AddInt, // binaryop
+ AddString, // binaryop
MinusReal, // binaryop
MinusInt, // binaryop
@@ -187,6 +193,11 @@ struct Instr {
bool value;
} bool_value;
struct {
+ int reg;
+ int offset;
+ int length;
+ } string_value;
+ struct {
int output;
int src1;
int src2;
@@ -198,7 +209,6 @@ struct Instr {
struct {
int output;
int src;
- int srcType;
} genericunaryop;
struct {
int reg;
@@ -207,13 +217,11 @@ struct Instr {
struct {
int reg;
int src;
- int typeReg;
int name;
int subscribeIndex;
} find;
struct {
int reg;
- int typeReg;
} cleanup;
struct {
int offset;
@@ -229,6 +237,8 @@ struct Program {
quint32 signalTableOffset;
quint16 subscriptions;
quint16 identifiers;
+ quint16 instructionCount;
+ quint16 dummy;
const char *data() const { return ((const char *)this) + sizeof(Program); }
const Instr *instructions() const { return (const Instr *)(data() + dataLength); }
@@ -279,6 +289,8 @@ struct QmlBindingCompilerPrivate
bool tryArith(QmlJS::AST::Node *);
bool parseArith(QmlJS::AST::Node *, Result &);
+ bool numberArith(Result &, const Result &, const Result &, QSOperator::Op op);
+ bool stringArith(Result &, const Result &, const Result &, QSOperator::Op op);
bool tryLogic(QmlJS::AST::Node *);
bool parseLogic(QmlJS::AST::Node *, Result &);
@@ -301,6 +313,7 @@ struct QmlBindingCompilerPrivate
void registerCleanup(int reg, int cleanup, int cleanupType = 0);
void releaseReg(int);
+ int registerLiteralString(const QString &);
int registerString(const QString &);
QHash<QString, QPair<int, int> > registeredStrings;
QByteArray data;
@@ -383,8 +396,7 @@ static QmlPropertyCache::Data *findproperty(QObject *obj,
return property;
}
-static bool findproperty(QObject *obj,
- Register *output, Register *type,
+static bool findproperty(QObject *obj, Register *output,
QmlEnginePrivate *enginePriv,
QmlBindingVME::Config *config, int subIdx,
const QScriptDeclarativeClass::Identifier &name,
@@ -397,10 +409,13 @@ static bool findproperty(QObject *obj,
QmlPropertyCache::Data *property = findproperty(obj, name, enginePriv, local);
if (property) {
+ if (subIdx != -1)
+ subscribe(obj, property->notifyIndex, subIdx, config);
+
if (property->flags & QmlPropertyCache::Data::IsQObjectDerived) {
void *args[] = { output->typeDataPtr(), 0 };
QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
- type->setint(QMetaType::QObjectStar);
+ output->settype(QMetaType::QObjectStar);
} else if (property->propType == qMetaTypeId<QVariant>()) {
QVariant v;
void *args[] = { &v, 0 };
@@ -408,12 +423,12 @@ static bool findproperty(QObject *obj,
if (isTerminal) {
new (output->typeDataPtr()) QVariant(v);
- type->setint(qMetaTypeId<QVariant>());
+ output->settype(qMetaTypeId<QVariant>());
} else {
bool ok;
output->setQObject(variantToQObject(v, &ok));
if (!ok) return false;
- type->setint(QMetaType::QObjectStar);
+ output->settype(QMetaType::QObjectStar);
}
} else {
@@ -423,18 +438,15 @@ static bool findproperty(QObject *obj,
if (property->propType == QMetaType::QReal) {
void *args[] = { output->typeDataPtr(), 0 };
QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
- type->setint(QMetaType::QReal);
+ output->settype(QMetaType::QReal);
} else {
new (output->typeDataPtr())
QVariant(obj->metaObject()->property(property->coreIndex).read(obj));
- type->setint(qMetaTypeId<QVariant>());
+ output->settype(qMetaTypeId<QVariant>());
}
}
- if (subIdx != -1)
- subscribe(obj, property->notifyIndex, subIdx, config);
-
return true;
} else {
return false;
@@ -442,18 +454,17 @@ static bool findproperty(QObject *obj,
}
static bool findproperty(Register *input,
- Register *output, Register *type,
+ Register *output,
QmlEnginePrivate *enginePriv,
QmlBindingVME::Config *config, int subIdx,
const QScriptDeclarativeClass::Identifier &name,
bool isTerminal)
{
- return findproperty(input->getQObject(), output, type, enginePriv,
+ return findproperty(input->getQObject(), output, enginePriv,
config, subIdx, name, isTerminal);
}
static bool findgeneric(Register *output, // value output
- Register *type, // value type output
QmlBindingVME::Config *config,
int subIdx, // Subscription index in config
QmlContextPrivate *context, // Context to search in
@@ -465,21 +476,26 @@ static bool findgeneric(Register *output, // val
while (context) {
int contextPropertyIndex = context->propertyNames?context->propertyNames->value(name):-1;
+
+
if (contextPropertyIndex != -1) {
+ subscribe(QmlContextPrivate::get(context), contextPropertyIndex + context->notifyIndex,
+ subIdx, config);
+
if (contextPropertyIndex < context->idValueCount) {
output->setQObject(context->idValues[contextPropertyIndex]);
- type->setint(QMetaType::QObjectStar);
+ output->settype(QMetaType::QObjectStar);
} else {
const QVariant &value = context->propertyValues.at(contextPropertyIndex);
if (isTerminal) {
new (output->typeDataPtr()) QVariant(value);
- type->setint(qMetaTypeId<QVariant>());
+ output->settype(qMetaTypeId<QVariant>());
} else {
bool ok;
output->setQObject(variantToQObject(value, &ok));
if (!ok) return false;
- type->setint(QMetaType::QObjectStar);
+ output->settype(QMetaType::QObjectStar);
}
}
@@ -496,7 +512,7 @@ static bool findgeneric(Register *output, // val
if (QObject *root = context->defaultObjects.isEmpty()?0:context->defaultObjects.first()) {
- if (findproperty(root, output, type, enginePriv, config, subIdx, name, isTerminal))
+ if (findproperty(root, output, enginePriv, config, subIdx, name, isTerminal))
return true;
}
@@ -579,7 +595,7 @@ inline static QUrl toUrl(Register *reg, int type, QmlContextPrivate *context, bo
return QUrl();
}
- if (base.isRelative())
+ if (!base.isEmpty() && base.isRelative())
return context->url.resolved(base);
else
return base;
@@ -676,6 +692,11 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
registers[instr->bool_value.reg].setbool(instr->bool_value.value);
break;
+ case Instr::String:
+ new (registers[instr->bool_value.reg].getstringptr())
+ QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
+ break;
+
case Instr::AddReal:
registers[instr->binaryop.output].setqreal(registers[instr->binaryop.src1].getqreal() +
registers[instr->binaryop.src2].getqreal());
@@ -685,6 +706,12 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
registers[instr->binaryop.output].setint(registers[instr->binaryop.src1].getint() +
registers[instr->binaryop.src2].getint());
break;
+
+ case Instr::AddString:
+ new (registers[instr->binaryop.output].getstringptr())
+ QString(*registers[instr->binaryop.src1].getstringptr() +
+ *registers[instr->binaryop.src2].getstringptr());
+ break;
case Instr::MinusReal:
registers[instr->binaryop.output].setqreal(registers[instr->binaryop.src1].getqreal() -
@@ -792,8 +819,8 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
// We start the search in the parent context, as we know that the
// name is not present in the current context or it would have been
// found during the static compile
- if (!findgeneric(registers + instr->find.reg, registers + instr->find.typeReg,
- config, instr->find.subscribeIndex, QmlContextPrivate::get(context->parent),
+ if (!findgeneric(registers + instr->find.reg, config, instr->find.subscribeIndex,
+ QmlContextPrivate::get(context->parent),
config->identifiers[instr->find.name].identifier,
instr->type == Instr::FindGenericTerminal)) {
qWarning() << "ERROR - FindGeneric*";
@@ -803,8 +830,7 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
case Instr::FindPropertyTerminal:
case Instr::FindProperty:
- if (!findproperty(registers + instr->find.src,
- registers + instr->find.reg, registers + instr->find.typeReg,
+ if (!findproperty(registers + instr->find.src, registers + instr->find.reg,
QmlEnginePrivate::get(context->engine),
config, instr->find.subscribeIndex,
config->identifiers[instr->find.name].identifier,
@@ -816,7 +842,7 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
case Instr::CleanupGeneric:
{
- int type = registers[instr->cleanup.typeReg].getint();
+ int type = registers[instr->cleanup.reg].gettype();
if (type == qMetaTypeId<QVariant>()) {
((QVariant *)registers[instr->cleanup.reg].typeDataPtr())->~QVariant();
}
@@ -825,21 +851,21 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
case Instr::ConvertGenericToReal:
{
- int type = registers[instr->genericunaryop.srcType].getint();
+ int type = registers[instr->genericunaryop.src].gettype();
registers[instr->genericunaryop.output].setqreal(toReal(registers + instr->genericunaryop.src, type));
}
break;
case Instr::ConvertGenericToBool:
{
- int type = registers[instr->genericunaryop.srcType].getint();
+ int type = registers[instr->genericunaryop.src].gettype();
registers[instr->genericunaryop.output].setbool(toBool(registers + instr->genericunaryop.src, type));
}
break;
case Instr::ConvertGenericToString:
{
- int type = registers[instr->genericunaryop.srcType].getint();
+ int type = registers[instr->genericunaryop.src].gettype();
void *regPtr = registers[instr->genericunaryop.output].typeDataPtr();
new (regPtr) QString(toString(registers + instr->genericunaryop.src, type));
}
@@ -847,7 +873,7 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
case Instr::ConvertGenericToUrl:
{
- int type = registers[instr->genericunaryop.srcType].getint();
+ int type = registers[instr->genericunaryop.src].gettype();
void *regPtr = registers[instr->genericunaryop.output].typeDataPtr();
new (regPtr) QUrl(toUrl(registers + instr->genericunaryop.src, type, context));
}
@@ -862,16 +888,16 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
}
}
-void QmlBindingVME::dump(const QByteArray &programData)
+void QmlBindingVME::dump(const char *programData)
{
- const Program *program = (const Program *)programData.constData();
+ const Program *program = (const Program *)programData;
qWarning() << "Program.bindings:" << program->bindings;
qWarning() << "Program.dataLength:" << program->dataLength;
qWarning() << "Program.subscriptions:" << program->subscriptions;
qWarning() << "Program.indentifiers:" << program->identifiers;
- int count = (programData.size() - sizeof(Program) - program->dataLength) / sizeof(Instr);
+ int count = program->instructionCount;
const Instr *instr = program->instructions();
while (count--) {
@@ -913,12 +939,18 @@ void QmlBindingVME::dump(const QByteArray &programData)
case Instr::Bool:
qWarning().nospace() << "Bool" << "\t\t\t" << instr->bool_value.reg << "\t" << instr->bool_value.value;
break;
+ case Instr::String:
+ qWarning().nospace() << "String" << "\t\t\t" << instr->string_value.reg << "\t" << instr->string_value.offset << "\t" << instr->string_value.length;
+ break;
case Instr::AddReal:
qWarning().nospace() << "AddReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
break;
case Instr::AddInt:
qWarning().nospace() << "AddInt" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
break;
+ case Instr::AddString:
+ qWarning().nospace() << "AddString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
case Instr::MinusReal:
qWarning().nospace() << "MinusReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
break;
@@ -953,10 +985,10 @@ void QmlBindingVME::dump(const QByteArray &programData)
qWarning().nospace() << "NewUrl" << "\t\t\t" << instr->construct.reg;
break;
case Instr::CleanupString:
- qWarning().nospace() << "CleanupString" << "\t\t" << instr->cleanup.reg << "\t" << instr->cleanup.typeReg;
+ qWarning().nospace() << "CleanupString" << "\t\t" << instr->cleanup.reg;
break;
case Instr::CleanupUrl:
- qWarning().nospace() << "CleanupUrl" << "\t\t" << instr->cleanup.reg << "\t" << instr->cleanup.typeReg;
+ qWarning().nospace() << "CleanupUrl" << "\t\t" << instr->cleanup.reg;
break;
case Instr::Fetch:
qWarning().nospace() << "Fetch" << "\t\t\t" << instr->fetch.output << "\t" << instr->fetch.index << "\t" << instr->fetch.objectReg;
@@ -977,31 +1009,31 @@ void QmlBindingVME::dump(const QByteArray &programData)
qWarning().nospace() << "InitString" << "\t\t" << instr->initstring.offset << "\t" << instr->initstring.dataIdx << "\t" << instr->initstring.length;
break;
case Instr::FindGeneric:
- qWarning().nospace() << "FindGeneric" << "\t\t" << instr->find.reg << "\t" << instr->find.typeReg << "\t" << instr->find.name;
+ qWarning().nospace() << "FindGeneric" << "\t\t" << instr->find.reg << "\t" << instr->find.name;
break;
case Instr::FindGenericTerminal:
- qWarning().nospace() << "FindGenericTerminal" << "\t" << instr->find.reg << "\t" << instr->find.typeReg << "\t" << instr->find.name;
+ qWarning().nospace() << "FindGenericTerminal" << "\t" << instr->find.reg << "\t" << instr->find.name;
break;
case Instr::FindProperty:
- qWarning().nospace() << "FindProperty" << "\t\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.typeReg << "\t" << instr->find.name;
+ qWarning().nospace() << "FindProperty" << "\t\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name;
break;
case Instr::FindPropertyTerminal:
- qWarning().nospace() << "FindPropertyTerminal" << "\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.typeReg << "\t" << instr->find.name;
+ qWarning().nospace() << "FindPropertyTerminal" << "\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name;
break;
case Instr::CleanupGeneric:
- qWarning().nospace() << "CleanupGeneric" << "\t\t" << instr->cleanup.reg << "\t" << instr->cleanup.typeReg;
+ qWarning().nospace() << "CleanupGeneric" << "\t\t" << instr->cleanup.reg;
break;
case Instr::ConvertGenericToReal:
- qWarning().nospace() << "ConvertGenericToReal" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src << "\t" << instr->genericunaryop.srcType;
+ qWarning().nospace() << "ConvertGenericToReal" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src;
break;
case Instr::ConvertGenericToBool:
- qWarning().nospace() << "ConvertGenericToBool" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src << "\t" << instr->genericunaryop.srcType;
+ qWarning().nospace() << "ConvertGenericToBool" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src;
break;
case Instr::ConvertGenericToString:
- qWarning().nospace() << "ConvertGenericToString" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src << "\t" << instr->genericunaryop.srcType;
+ qWarning().nospace() << "ConvertGenericToString" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src;
break;
case Instr::ConvertGenericToUrl:
- qWarning().nospace() << "ConvertGenericToUrl" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src << "\t" << instr->genericunaryop.srcType;
+ qWarning().nospace() << "ConvertGenericToUrl" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src;
break;
default:
qWarning().nospace() << "Unknown";
@@ -1073,35 +1105,30 @@ bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node)
convert.type = Instr::ConvertGenericToReal;
convert.genericunaryop.output = convertReg;
convert.genericunaryop.src = type.reg;
- convert.genericunaryop.srcType = 2; // XXX
bytecode << convert;
} else if (destination->type == QVariant::String) {
Instr convert;
convert.type = Instr::ConvertGenericToString;
convert.genericunaryop.output = convertReg;
convert.genericunaryop.src = type.reg;
- convert.genericunaryop.srcType = 2; // XXX
bytecode << convert;
} else if (destination->type == QMetaType::Bool) {
Instr convert;
convert.type = Instr::ConvertGenericToBool;
convert.genericunaryop.output = convertReg;
convert.genericunaryop.src = type.reg;
- convert.genericunaryop.srcType = 2; // XXX
bytecode << convert;
} else if (destination->type == QVariant::Url) {
Instr convert;
convert.type = Instr::ConvertGenericToUrl;
convert.genericunaryop.output = convertReg;
convert.genericunaryop.src = type.reg;
- convert.genericunaryop.srcType = 2; // XXX
bytecode << convert;
}
Instr cleanup;
cleanup.type = Instr::CleanupGeneric;
cleanup.cleanup.reg = type.reg;
- cleanup.cleanup.typeReg = 2; // XXX
bytecode << cleanup;
Instr instr;
@@ -1115,13 +1142,11 @@ bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node)
Instr cleanup;
cleanup.type = Instr::CleanupString;
cleanup.cleanup.reg = convertReg;
- cleanup.cleanup.typeReg = -1;
bytecode << cleanup;
} else if (destination->type == QVariant::Url) {
Instr cleanup;
cleanup.type = Instr::CleanupUrl;
cleanup.cleanup.reg = convertReg;
- cleanup.cleanup.typeReg = -1;
bytecode << cleanup;
}
@@ -1353,7 +1378,6 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type)
find.find.reg = reg;
find.find.src = -1;
- find.find.typeReg = 2; // XXX
find.find.name = registerString(name);
subscribeName << QString(QLatin1String("$$$Generic_") + name);
@@ -1416,7 +1440,6 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type)
prop.find.reg = reg;
prop.find.src = reg;
- prop.find.typeReg = 2; // XXX
prop.find.name = registerString(name);
if (subscription(subscribeName, &type))
prop.find.subscribeIndex = subscriptionIndex(subscribeName);
@@ -1462,17 +1485,25 @@ bool QmlBindingCompilerPrivate::parseArith(QmlJS::AST::Node *node, Result &type)
if (!parseExpression(expression->left, lhs)) return false;
if (!parseExpression(expression->right, rhs)) return false;
- if (lhs.type != QVariant::Int &
- lhs.type != QMetaType::QReal)
- return false;
-
- if (rhs.type != QVariant::Int &
- rhs.type != QMetaType::QReal)
+ if ((lhs.type == QVariant::Int || lhs.type == QMetaType::QReal) &&
+ (rhs.type == QVariant::Int || rhs.type == QMetaType::QReal))
+ return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op);
+ else if(expression->op == QSOperator::Sub)
+ return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op);
+ else if ((lhs.type == QMetaType::QString || lhs.unknownType) &&
+ (rhs.type == QMetaType::QString || rhs.unknownType) &&
+ (lhs.type == QMetaType::QString || rhs.type == QMetaType::QString))
+ return stringArith(type, lhs, rhs, (QSOperator::Op)expression->op);
+ else
return false;
+}
+bool QmlBindingCompilerPrivate::numberArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op)
+{
bool nativeReal = rhs.type == QMetaType::QReal ||
- lhs.type == QMetaType::QReal;
-
+ lhs.type == QMetaType::QReal ||
+ lhs.unknownType ||
+ rhs.unknownType;
if (nativeReal && lhs.type == QMetaType::Int) {
Instr convert;
@@ -1490,18 +1521,40 @@ bool QmlBindingCompilerPrivate::parseArith(QmlJS::AST::Node *node, Result &type)
bytecode << convert;
}
+ int lhsTmp = -1;
+ int rhsTmp = -1;
+ if (lhs.unknownType) {
+ lhsTmp = acquireReg();
+
+ Instr conv;
+ conv.type = Instr::ConvertGenericToReal;
+ conv.genericunaryop.output = lhsTmp;
+ conv.genericunaryop.src = lhs.reg;
+ bytecode << conv;
+ }
+
+ if (rhs.unknownType) {
+ rhsTmp = acquireReg();
+
+ Instr conv;
+ conv.type = Instr::ConvertGenericToReal;
+ conv.genericunaryop.output = rhsTmp;
+ conv.genericunaryop.src = rhs.reg;
+ bytecode << conv;
+ }
+
Instr arith;
- if (expression->op == QSOperator::Add) {
+ if (op == QSOperator::Add) {
arith.type = nativeReal?Instr::AddReal:Instr::AddInt;
- } else if (expression->op == QSOperator::Sub) {
+ } else if (op == QSOperator::Sub) {
arith.type = nativeReal?Instr::MinusReal:Instr::MinusInt;
} else {
qFatal("Unsupported arithmetic operator");
}
arith.binaryop.output = type.reg;
- arith.binaryop.src1 = lhs.reg;
- arith.binaryop.src2 = rhs.reg;
+ arith.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp;
+ arith.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp;
bytecode << arith;
type.metaObject = 0;
@@ -1509,12 +1562,58 @@ bool QmlBindingCompilerPrivate::parseArith(QmlJS::AST::Node *node, Result &type)
type.subscriptionSet.unite(lhs.subscriptionSet);
type.subscriptionSet.unite(rhs.subscriptionSet);
+ if (lhsTmp != -1) releaseReg(lhsTmp);
+ if (rhsTmp != -1) releaseReg(rhsTmp);
releaseReg(lhs.reg);
releaseReg(rhs.reg);
return true;
}
+bool QmlBindingCompilerPrivate::stringArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op)
+{
+ if (op != QSOperator::Add)
+ return false;
+
+ int lhsTmp = -1;
+ int rhsTmp = -1;
+
+ if (lhs.unknownType) {
+ lhsTmp = acquireReg(Instr::CleanupString);
+
+ Instr convert;
+ convert.type = Instr::ConvertGenericToString;
+ convert.genericunaryop.output = lhsTmp;
+ convert.genericunaryop.src = lhs.reg;
+ bytecode << convert;
+ }
+
+ if (rhs.unknownType) {
+ rhsTmp = acquireReg(Instr::CleanupString);
+
+ Instr convert;
+ convert.type = Instr::ConvertGenericToString;
+ convert.genericunaryop.output = rhsTmp;
+ convert.genericunaryop.src = rhs.reg;
+ bytecode << convert;
+ }
+
+ type.reg = acquireReg(Instr::CleanupString);
+ type.type = QMetaType::QString;
+
+ Instr add;
+ add.type = Instr::AddString;
+ add.binaryop.output = type.reg;
+ add.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp;
+ add.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp;
+ bytecode << add;
+
+ if (lhsTmp != -1) releaseReg(lhsTmp);
+ if (rhsTmp != -1) releaseReg(rhsTmp);
+
+ return true;
+}
+
bool QmlBindingCompilerPrivate::tryLogic(QmlJS::AST::Node *node)
{
if (node->kind != AST::Node::Kind_BinaryExpression)
@@ -1656,7 +1755,8 @@ bool QmlBindingCompilerPrivate::tryConstant(QmlJS::AST::Node *node)
{
return node->kind == AST::Node::Kind_TrueLiteral ||
node->kind == AST::Node::Kind_FalseLiteral ||
- node->kind == AST::Node::Kind_NumericLiteral;
+ node->kind == AST::Node::Kind_NumericLiteral ||
+ node->kind == AST::Node::Kind_StringLiteral;
}
bool QmlBindingCompilerPrivate::parseConstant(QmlJS::AST::Node *node, Result &type)
@@ -1689,6 +1789,11 @@ bool QmlBindingCompilerPrivate::parseConstant(QmlJS::AST::Node *node, Result &ty
instr.real_value.value = qreal(static_cast<AST::NumericLiteral *>(node)->value);
bytecode << instr;
return true;
+ } else if (node->kind == AST::Node::Kind_StringLiteral) {
+ QString str = static_cast<AST::StringLiteral *>(node)->value->asString();
+ type.type = QMetaType::QString;
+ type.reg = registerLiteralString(str);
+ return true;
} else {
return false;
}
@@ -1861,7 +1966,6 @@ void QmlBindingCompilerPrivate::releaseReg(int reg)
Instr cleanup;
(int &)cleanup.type = c.first;
cleanup.cleanup.reg = reg;
- cleanup.cleanup.typeReg = c.second;
bytecode << cleanup;
}
@@ -1869,6 +1973,26 @@ void QmlBindingCompilerPrivate::releaseReg(int reg)
registers &= ~mask;
}
+// Returns a reg
+int QmlBindingCompilerPrivate::registerLiteralString(const QString &str)
+{
+ QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar));
+ int offset = data.count();
+ data += strdata;
+
+ int reg = acquireReg(Instr::CleanupString);
+
+ Instr string;
+ string.type = Instr::String;
+ string.string_value.reg = reg;
+ string.string_value.offset = offset;
+ string.string_value.length = str.length();
+ bytecode << string;
+
+ return reg;
+}
+
+// Returns an identifier offset
int QmlBindingCompilerPrivate::registerString(const QString &string)
{
Q_ASSERT(!string.isEmpty());
@@ -1881,7 +2005,7 @@ int QmlBindingCompilerPrivate::registerString(const QString &string)
data += strdata;
iter = registeredStrings.insert(string, qMakePair(registeredStrings.count(), rv));
- }
+ }
Instr reg;
reg.type = Instr::InitString;
@@ -2030,6 +2154,7 @@ QByteArray QmlBindingCompiler::program() const
prog.dataLength = 4 * ((data.size() + 3) / 4);
prog.subscriptions = d->committed.subscriptionIds.count();
prog.identifiers = d->committed.registeredStrings.count();
+ prog.instructionCount = bytecode.count();
int size = sizeof(Program) + bytecode.count() * sizeof(Instr);
size += prog.dataLength;
diff --git a/src/declarative/qml/qmlbindingvme_p.h b/src/declarative/qml/qmlbindingvme_p.h
index de73037..ceaf2b3 100644
--- a/src/declarative/qml/qmlbindingvme_p.h
+++ b/src/declarative/qml/qmlbindingvme_p.h
@@ -85,7 +85,7 @@ public:
static void run(const char *program, int instr,
Config *config, QmlContextPrivate *context,
QObject **scopes, QObject **outputs);
- static void dump(const QByteArray &);
+ static void dump(const char *);
};
class QmlBindingCompilerPrivate;
diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp
index 99bcb7b..3307ff8 100644
--- a/src/declarative/util/qmlpixmapcache.cpp
+++ b/src/declarative/util/qmlpixmapcache.cpp
@@ -84,7 +84,6 @@ private:
void loadImage(Job &job);
QList<Job> jobs;
- Job runningJob;
QMutex mutex;
QWaitCondition haveJob;
bool quit;
@@ -119,22 +118,21 @@ void QmlImageReader::read(QmlPixmapReply *reply)
Job job;
job.reply = reply;
jobs.append(job);
- haveJob.wakeOne();
+ if (jobs.count() == 1)
+ haveJob.wakeOne();
mutex.unlock();
}
void QmlImageReader::cancel(QmlPixmapReply *reply)
{
mutex.lock();
- if (runningJob.reply != reply) {
- QList<Job>::iterator it = jobs.begin();
- while (it != jobs.end()) {
- if ((*it).reply == reply) {
- jobs.erase(it);
- break;
- }
- ++it;
+ QList<Job>::iterator it = jobs.begin();
+ while (it != jobs.end()) {
+ if ((*it).reply == reply) {
+ jobs.erase(it);
+ break;
}
+ ++it;
}
mutex.unlock();
}
@@ -158,14 +156,12 @@ void QmlImageReader::run()
haveJob.wait(&mutex);
if (quit)
break;
- runningJob = jobs.takeFirst();
+ Job runningJob = jobs.takeFirst();
runningJob.reply->addRef();
mutex.unlock();
+
loadImage(runningJob);
- mutex.lock();
QCoreApplication::postEvent(runningJob.reply, new QmlImageDecodeEvent(runningJob.error, runningJob.img));
- runningJob.reply = 0;
- mutex.unlock();
}
}
@@ -244,8 +240,21 @@ QmlPixmapReply::QmlPixmapReply(const QString &key, QNetworkReply *reply)
: QObject(*new QmlPixmapReplyPrivate(key, reply), 0)
{
Q_D(QmlPixmapReply);
- connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64)));
- connect(d->reply, SIGNAL(finished()), this, SLOT(networkRequestDone()));
+
+ static int replyDownloadProgress = -1;
+ static int replyFinished = -1;
+ static int thisDownloadProgress = -1;
+ static int thisNetworkRequestDone = -1;
+
+ if (replyDownloadProgress == -1) {
+ replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()");
+ thisDownloadProgress = QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ thisNetworkRequestDone = QmlPixmapReply::staticMetaObject.indexOfSlot("networkRequestDone()");
+ }
+
+ QMetaObject::connect(d->reply, replyDownloadProgress, this, thisDownloadProgress, Qt::DirectConnection);
+ QMetaObject::connect(d->reply, replyFinished, this, thisNetworkRequestDone);
}
QmlPixmapReply::~QmlPixmapReply()
diff --git a/tests/benchmarks/declarative/text/tst_text.cpp b/tests/benchmarks/declarative/text/tst_text.cpp
index 5c57633..e69ecd8 100644
--- a/tests/benchmarks/declarative/text/tst_text.cpp
+++ b/tests/benchmarks/declarative/text/tst_text.cpp
@@ -58,8 +58,10 @@ public:
private slots:
void layout();
void paintLayoutToPixmap();
+ void paintLayoutToPixmap_painterFill();
void document();
void paintDocToPixmap();
+ void paintDocToPixmap_painterFill();
private:
QString m_text;
@@ -125,6 +127,21 @@ void tst_text::paintLayoutToPixmap()
}
}
+void tst_text::paintLayoutToPixmap_painterFill()
+{
+ QTextLayout layout(m_text);
+ QSize size = setupTextLayout(&layout);
+
+ QBENCHMARK {
+ QPixmap img(size);
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(0, 0, img.width(), img.height(), Qt::transparent);
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ layout.draw(&p, QPointF(0, 0));
+ }
+}
+
void tst_text::document()
{
QTextControl *control = new QTextControl(m_text);
@@ -151,5 +168,22 @@ void tst_text::paintDocToPixmap()
}
}
+void tst_text::paintDocToPixmap_painterFill()
+{
+ QTextControl *control = new QTextControl;
+ QTextDocument *doc = control->document();
+ doc->setHtml(m_text);
+ QSize size = doc->size().toSize();
+
+ QBENCHMARK {
+ QPixmap img(size);
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(0, 0, img.width(), img.height(), Qt::transparent);
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ control->drawContents(&p, QRectF(QPointF(0, 0), QSizeF(size)));
+ }
+}
+
QTEST_MAIN(tst_text)
#include "tst_text.moc"