summaryrefslogtreecommitdiffstats
path: root/src/declarative/graphicsitems
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@nokia.com>2010-10-22 09:05:17 (GMT)
committerPaul Olav Tvete <paul.tvete@nokia.com>2010-10-22 09:05:17 (GMT)
commit26139fcacc05b4a74fce1ef4e0db819118765310 (patch)
tree75ce453868e95faa72b8f3b871c58969bbeb2a7e /src/declarative/graphicsitems
parent9a216c3f7abeacae8b9e9f78e50ddfcfbb5e2fa3 (diff)
parentb8238ec7e41d483a9166eb7aebbf911f36976cdc (diff)
downloadQt-26139fcacc05b4a74fce1ef4e0db819118765310.zip
Qt-26139fcacc05b4a74fce1ef4e0db819118765310.tar.gz
Qt-26139fcacc05b4a74fce1ef4e0db819118765310.tar.bz2
Merge remote branch 'qt/master' into lighthouse-master
Conflicts: src/gui/kernel/qapplication_win.cpp src/gui/kernel/qwidget.cpp src/gui/text/qfontengine_ft.cpp
Diffstat (limited to 'src/declarative/graphicsitems')
-rw-r--r--src/declarative/graphicsitems/graphicsitems.pri7
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable.cpp4
-rw-r--r--src/declarative/graphicsitems/qdeclarativegridview.cpp11
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage.cpp9
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase.cpp15
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h2
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.cpp9
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp17
-rw-r--r--src/declarative/graphicsitems/qdeclarativeloader.cpp4
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea.cpp12
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea_p_p.h3
-rw-r--r--src/declarative/graphicsitems/qdeclarativepainteditem.cpp1
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview.cpp25
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview_p.h1
-rw-r--r--src/declarative/graphicsitems/qdeclarativerepeater.cpp6
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext.cpp961
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p_p.h64
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit.cpp1
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput.cpp7
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextlayout.cpp358
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextlayout_p.h74
-rw-r--r--src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h1
22 files changed, 1060 insertions, 532 deletions
diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri
index d420595..ffdeb29 100644
--- a/src/declarative/graphicsitems/graphicsitems.pri
+++ b/src/declarative/graphicsitems/graphicsitems.pri
@@ -49,7 +49,8 @@ HEADERS += \
$$PWD/qdeclarativelistview_p.h \
$$PWD/qdeclarativelayoutitem_p.h \
$$PWD/qdeclarativeitemchangelistener_p.h \
- $$PWD/qdeclarativegraphicswidget_p.h
+ $$PWD/qdeclarativegraphicswidget_p.h \
+ $$PWD/qdeclarativetextlayout_p.h
SOURCES += \
$$PWD/qdeclarativeitemsmodule.cpp \
@@ -81,4 +82,6 @@ SOURCES += \
$$PWD/qdeclarativevisualitemmodel.cpp \
$$PWD/qdeclarativelistview.cpp \
$$PWD/qdeclarativelayoutitem.cpp \
- $$PWD/qdeclarativegraphicswidget.cpp
+ $$PWD/qdeclarativegraphicswidget.cpp \
+ $$PWD/qdeclarativetextlayout.cpp
+
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
index 7c43e5b..cdfdc58 100644
--- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
@@ -466,7 +466,7 @@ QDeclarativeFlickable::~QDeclarativeFlickable()
qreal QDeclarativeFlickable::contentX() const
{
Q_D(const QDeclarativeFlickable);
- return -d->hData.move.value();
+ return -d->contentItem->x();
}
void QDeclarativeFlickable::setContentX(qreal pos)
@@ -484,7 +484,7 @@ void QDeclarativeFlickable::setContentX(qreal pos)
qreal QDeclarativeFlickable::contentY() const
{
Q_D(const QDeclarativeFlickable);
- return -d->vData.move.value();
+ return -d->contentItem->y();
}
void QDeclarativeFlickable::setContentY(qreal pos)
diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp
index 8d08c99..6ee6b0d 100644
--- a/src/declarative/graphicsitems/qdeclarativegridview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp
@@ -218,7 +218,14 @@ public:
return visibleItems.last()->rowPos() + rows * rowSize();
}
} else {
- return (modelIndex / columns) * rowSize();
+ qreal pos = (modelIndex / columns) * rowSize();
+ if (header) {
+ qreal headerSize = flow == QDeclarativeGridView::LeftToRight
+ ? header->item->height()
+ : header->item->width();
+ pos += headerSize;
+ }
+ return pos;
}
return 0;
}
@@ -2591,7 +2598,7 @@ void QDeclarativeGridView::itemsMoved(int from, int to, int count)
while (moved.count()) {
int idx = moved.begin().key();
FxGridItem *item = moved.take(idx);
- if (item->item == d->currentItem->item)
+ if (d->currentItem && item->item == d->currentItem->item)
item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
d->releaseItem(item);
}
diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp
index 9cd9ad6..08d237f 100644
--- a/src/declarative/graphicsitems/qdeclarativeimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp
@@ -253,6 +253,15 @@ void QDeclarativeImage::setFillMode(FillMode mode)
emit fillModeChanged();
}
+/*!
+
+ \qmlproperty real Image::paintedWidth
+ \qmlproperty real Image::paintedHeight
+
+ These properties hold the size of the image that is actually painted.
+ In most cases it is the same as \c width and \c height, but when using a \c fillMode like
+ \c PreserveAspectFit \c paintedWidth or \c paintedHeight can be smaller than \c width and \c height.
+*/
qreal QDeclarativeImage::paintedWidth() const
{
Q_D(const QDeclarativeImage);
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
index 02b4807..c3bac2d 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
@@ -46,8 +46,6 @@
#include <qdeclarativeinfo.h>
#include <qdeclarativepixmapcache_p.h>
-#include <QFile>
-
QT_BEGIN_NAMESPACE
QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeImageBasePrivate &dd, QDeclarativeItem *parent)
@@ -115,6 +113,7 @@ void QDeclarativeImageBase::setSourceSize(const QSize& size)
return;
d->sourcesize = size;
+ d->explicitSourceSize = true;
emit sourceSizeChanged();
if (isComponentComplete())
load();
@@ -123,7 +122,10 @@ void QDeclarativeImageBase::setSourceSize(const QSize& size)
QSize QDeclarativeImageBase::sourceSize() const
{
Q_D(const QDeclarativeImageBase);
- return d->sourcesize.isValid() ? d->sourcesize : QSize(implicitWidth(),implicitHeight());
+
+ int width = d->sourcesize.width();
+ int height = d->sourcesize.height();
+ return QSize(width != -1 ? width : implicitWidth(), height != -1 ? height : implicitHeight());
}
void QDeclarativeImageBase::load()
@@ -141,7 +143,7 @@ void QDeclarativeImageBase::load()
pixmapChange();
update();
} else {
- d->pix.load(qmlEngine(this), d->url, d->sourcesize, d->async);
+ d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), d->async);
if (d->pix.isLoading()) {
d->progress = 0.0;
@@ -186,11 +188,8 @@ void QDeclarativeImageBase::requestFinished()
setImplicitWidth(d->pix.width());
setImplicitHeight(d->pix.height());
- if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height()) {
- d->sourcesize.setWidth(d->pix.width());
- d->sourcesize.setHeight(d->pix.height());
+ if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height())
emit sourceSizeChanged();
- }
if (d->status != oldStatus)
emit statusChanged(d->status);
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
index aee8b28..3d23ba9 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
@@ -69,6 +69,7 @@ public:
QDeclarativeImageBasePrivate()
: status(QDeclarativeImageBase::Null),
progress(0.0),
+ explicitSourceSize(false),
async(false)
{
QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
@@ -79,6 +80,7 @@ public:
QUrl url;
qreal progress;
QSize sourcesize;
+ bool explicitSourceSize : 1;
bool async : 1;
};
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp
index 250a43b..51eb5f2 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp
@@ -56,7 +56,6 @@
#include <QDebug>
#include <QPen>
-#include <QFile>
#include <QEvent>
#include <QGraphicsSceneMouseEvent>
#include <QtCore/qnumeric.h>
@@ -1181,7 +1180,7 @@ void QDeclarativeKeysAttached::keyPressed(QKeyEvent *event, bool post)
d->inPress = true;
for (int ii = 0; ii < d->targets.count(); ++ii) {
QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
- if (i) {
+ if (i && i->isVisible()) {
d->item->scene()->sendEvent(i, event);
if (event->isAccepted()) {
d->inPress = false;
@@ -1223,7 +1222,7 @@ void QDeclarativeKeysAttached::keyReleased(QKeyEvent *event, bool post)
d->inRelease = true;
for (int ii = 0; ii < d->targets.count(); ++ii) {
QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
- if (i) {
+ if (i && i->isVisible()) {
d->item->scene()->sendEvent(i, event);
if (event->isAccepted()) {
d->inRelease = false;
@@ -1248,7 +1247,7 @@ void QDeclarativeKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool p
d->inIM = true;
for (int ii = 0; ii < d->targets.count(); ++ii) {
QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
- if (i && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
d->item->scene()->sendEvent(i, event);
if (event->isAccepted()) {
d->imeItem = i;
@@ -1276,7 +1275,7 @@ QVariant QDeclarativeKeysAttached::inputMethodQuery(Qt::InputMethodQuery query)
if (d->item) {
for (int ii = 0; ii < d->targets.count(); ++ii) {
QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
- if (i && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod) && i == d->imeItem) { //### how robust is i == d->imeItem check?
+ if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod) && i == d->imeItem) { //### how robust is i == d->imeItem check?
QVariant v = static_cast<QDeclarativeItemAccessor *>(i)->doInputMethodQuery(query);
if (v.userType() == QVariant::RectF)
v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index 3261dd7..6fd3b71 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -1014,18 +1014,27 @@ void QDeclarativeListViewPrivate::updateSections()
void QDeclarativeListViewPrivate::updateCurrentSection()
{
+ Q_Q(QDeclarativeListView);
if (!sectionCriteria || visibleItems.isEmpty()) {
- currentSection.clear();
+ if (!currentSection.isEmpty()) {
+ currentSection.clear();
+ emit q->currentSectionChanged();
+ }
return;
}
int index = 0;
while (index < visibleItems.count() && visibleItems.at(index)->endPosition() < position())
++index;
+ QString newSection = currentSection;
if (index < visibleItems.count())
- currentSection = visibleItems.at(index)->attached->section();
+ newSection = visibleItems.at(index)->attached->section();
else
- currentSection = visibleItems.first()->attached->section();
+ newSection = visibleItems.first()->attached->section();
+ if (newSection != currentSection) {
+ currentSection = newSection;
+ emit q->currentSectionChanged();
+ }
}
void QDeclarativeListViewPrivate::updateCurrent(int modelIndex)
@@ -3116,7 +3125,7 @@ void QDeclarativeListView::itemsMoved(int from, int to, int count)
while (moved.count()) {
int idx = moved.begin().key();
FxListItem *item = moved.take(idx);
- if (item->item == d->currentItem->item)
+ if (d->currentItem && item->item == d->currentItem->item)
item->setPosition(d->positionAt(idx));
d->releaseItem(item);
}
diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp
index 1066c2b..5647b14 100644
--- a/src/declarative/graphicsitems/qdeclarativeloader.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp
@@ -337,7 +337,9 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded()
return;
}
- QDeclarativeContext *ctxt = new QDeclarativeContext(qmlContext(q));
+ QDeclarativeContext *creationContext = component->creationContext();
+ if (!creationContext) creationContext = qmlContext(q);
+ QDeclarativeContext *ctxt = new QDeclarativeContext(creationContext);
ctxt->setContextObject(q);
QDeclarativeComponent *c = component;
diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp
index a0208ef..1533d55 100644
--- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp
+++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp
@@ -557,6 +557,7 @@ void QDeclarativeMouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
ungrabMouse();
setKeepMouseGrab(false);
}
+ d->doubleClick = false;
}
void QDeclarativeMouseArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
@@ -565,14 +566,12 @@ void QDeclarativeMouseArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *even
if (!d->absorb) {
QDeclarativeItem::mouseDoubleClickEvent(event);
} else {
+ d->doubleClick = true;
d->saveEvent(event);
QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
me.setAccepted(d->isDoubleClickConnected());
emit this->doubleClicked(&me);
- if (!me.isAccepted()) {
- // Only deliver the press event if we haven't accepted the double click.
- QDeclarativeItem::mouseDoubleClickEvent(event);
- }
+ QDeclarativeItem::mouseDoubleClickEvent(event);
}
}
@@ -841,7 +840,8 @@ bool QDeclarativeMouseArea::setPressed(bool p)
d->pressed = p;
QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
if (d->pressed) {
- emit pressed(&me);
+ if (!d->doubleClick)
+ emit pressed(&me);
me.setX(d->lastPos.x());
me.setY(d->lastPos.y());
emit mousePositionChanged(&me);
@@ -849,7 +849,7 @@ bool QDeclarativeMouseArea::setPressed(bool p)
emit released(&me);
me.setX(d->lastPos.x());
me.setY(d->lastPos.y());
- if (isclick && !d->longPress)
+ if (isclick && !d->longPress && !d->doubleClick)
emit clicked(&me);
}
diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h
index 48a56d9..06a01d3 100644
--- a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h
@@ -68,7 +68,7 @@ class QDeclarativeMouseAreaPrivate : public QDeclarativeItemPrivate
public:
QDeclarativeMouseAreaPrivate()
: absorb(true), hovered(false), pressed(false), longPress(false),
- moved(false), stealMouse(false), drag(0)
+ moved(false), stealMouse(false), doubleClick(false), drag(0)
{
}
@@ -109,6 +109,7 @@ public:
bool dragX : 1;
bool dragY : 1;
bool stealMouse : 1;
+ bool doubleClick : 1;
QDeclarativeDrag *drag;
QPointF startScene;
qreal startX;
diff --git a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp
index a6db1fa..b470b3a 100644
--- a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp
@@ -44,7 +44,6 @@
#include <QDebug>
#include <QPen>
-#include <QFile>
#include <QEvent>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>
diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp
index d134929..81c84f5 100644
--- a/src/declarative/graphicsitems/qdeclarativepathview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp
@@ -300,6 +300,19 @@ void QDeclarativePathViewPrivate::setHighlightPosition(qreal pos)
}
}
+void QDeclarativePathView::pathUpdated()
+{
+ Q_D(QDeclarativePathView);
+ QList<QDeclarativeItem*>::iterator it = d->items.begin();
+ while (it != d->items.end()) {
+ QDeclarativeItem *item = *it;
+ if (QDeclarativePathViewAttached *att = d->attached(item))
+ att->m_percent = -1;
+ ++it;
+ }
+ refill();
+}
+
void QDeclarativePathViewPrivate::updateItem(QDeclarativeItem *item, qreal percent)
{
if (QDeclarativePathViewAttached *att = attached(item)) {
@@ -526,9 +539,9 @@ void QDeclarativePathView::setPath(QDeclarativePath *path)
if (d->path == path)
return;
if (d->path)
- disconnect(d->path, SIGNAL(changed()), this, SLOT(refill()));
+ disconnect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
d->path = path;
- connect(d->path, SIGNAL(changed()), this, SLOT(refill()));
+ connect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
if (d->isValid() && isComponentComplete()) {
d->clear();
if (d->attType) {
@@ -1099,16 +1112,16 @@ void QDeclarativePathViewPrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent
if (!interactive || !lastPosTime.isValid())
return;
+ qreal newPc;
+ QPointF pathPoint = pointNear(event->pos(), &newPc);
if (!stealMouse) {
- QPointF delta = event->pos() - startPoint;
+ QPointF delta = pathPoint - startPoint;
if (qAbs(delta.x()) > QApplication::startDragDistance() || qAbs(delta.y()) > QApplication::startDragDistance())
stealMouse = true;
}
if (stealMouse) {
moveReason = QDeclarativePathViewPrivate::Mouse;
- qreal newPc;
- pointNear(event->pos(), &newPc);
qreal diff = (newPc - startPc)*modelCount*mappedRange;
if (diff) {
setOffset(offset + diff);
@@ -1318,6 +1331,8 @@ void QDeclarativePathView::refill()
if (idx >= d->modelCount)
idx = 0;
}
+ if (!d->items.count())
+ d->firstIndex = -1;
if (d->modelCount) {
// add items to beginning and end
diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p.h
index 62a8c44..7775b1c 100644
--- a/src/declarative/graphicsitems/qdeclarativepathview_p.h
+++ b/src/declarative/graphicsitems/qdeclarativepathview_p.h
@@ -186,6 +186,7 @@ private Q_SLOTS:
void modelReset();
void createdItem(int index, QDeclarativeItem *item);
void destroyingItem(QDeclarativeItem *item);
+ void pathUpdated();
private:
friend class QDeclarativePathViewAttached;
diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
index 00f2848..cb64212 100644
--- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp
+++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
@@ -134,13 +134,13 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate()
create items as they are required.
Also, note that Repeater is \l {Item}-based, and can only repeat \l {Item}-derived objects.
- For example, it cannot be used to repeat QObjects:
+ For example, it cannot be used to repeat QtObjects:
\badcode
Item {
- //XXX does not work! Can't repeat QObject as it doesn't derive from Item.
+ //XXX does not work! Can't repeat QtObject as it doesn't derive from Item.
Repeater {
model: 10
- QObject {}
+ QtObject {}
}
}
\endcode
diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp
index 1f4c1c7..308aefa 100644
--- a/src/declarative/graphicsitems/qdeclarativetext.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetext.cpp
@@ -82,6 +82,20 @@ private:
static QSet<QUrl> errors;
};
+DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE);
+
+QDeclarativeTextPrivate::QDeclarativeTextPrivate()
+: color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft),
+ vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone),
+ format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), imageCacheDirty(true),
+ updateOnComponentComplete(true), richText(false), singleline(false), cacheAllTextAsImage(true),
+ internalWidthUpdate(false), doc(0)
+{
+ cacheAllTextAsImage = enableImageCache();
+ QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton;
+ QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
+}
+
QTextDocumentWithImageResources::QTextDocumentWithImageResources(QDeclarativeText *parent)
: QTextDocument(parent), outstanding(0)
{
@@ -138,14 +152,12 @@ void QTextDocumentWithImageResources::requestFinished()
#endif
QDeclarativeTextPrivate *d = QDeclarativeTextPrivate::get(textItem);
d->updateLayout();
- d->markImgDirty();
}
}
void QTextDocumentWithImageResources::setText(const QString &text)
{
if (!m_resources.isEmpty()) {
- qWarning("CLEAR");
qDeleteAll(m_resources);
m_resources.clear();
outstanding = 0;
@@ -160,6 +172,382 @@ void QTextDocumentWithImageResources::setText(const QString &text)
QSet<QUrl> QTextDocumentWithImageResources::errors;
+QDeclarativeTextPrivate::~QDeclarativeTextPrivate()
+{
+}
+
+void QDeclarativeTextPrivate::updateLayout()
+{
+ Q_Q(QDeclarativeText);
+ if (!q->isComponentComplete()) {
+ updateOnComponentComplete = true;
+ return;
+ }
+
+ // Setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ layout.clearLayout();
+ layout.setFont(font);
+ if (format != QDeclarativeText::StyledText) {
+ QString tmp = text;
+ tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ singleline = !tmp.contains(QChar::LineSeparator);
+ if (singleline && elideMode != QDeclarativeText::ElideNone && q->widthValid()) {
+ QFontMetrics fm(font);
+ tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...?
+ }
+ layout.setText(tmp);
+ } else {
+ singleline = false;
+ QDeclarativeStyledText::parse(text, layout);
+ }
+ }
+
+ updateSize();
+}
+
+void QDeclarativeTextPrivate::updateSize()
+{
+ Q_Q(QDeclarativeText);
+
+ if (!q->isComponentComplete()) {
+ updateOnComponentComplete = true;
+ return;
+ }
+
+ invalidateImageCache();
+
+ QFontMetrics fm(font);
+ if (text.isEmpty()) {
+ q->setImplicitHeight(fm.height());
+ emit q->paintedSizeChanged();
+ return;
+ }
+
+ int dy = q->height();
+ QSize size(0, 0);
+
+ //setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ size = setupTextLayout();
+ if (layedOutTextSize != size) {
+ q->prepareGeometryChange();
+ layedOutTextSize = size;
+ }
+ dy -= size.height();
+ } else {
+ singleline = false; // richtext can't elide or be optimized for single-line case
+ ensureDoc();
+ doc->setDefaultFont(font);
+ QTextOption option((Qt::Alignment)int(hAlign | vAlign));
+ option.setWrapMode(QTextOption::WrapMode(wrapMode));
+ doc->setDefaultTextOption(option);
+ if (wrapMode != QDeclarativeText::NoWrap && q->widthValid())
+ doc->setTextWidth(q->width());
+ else
+ doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
+ dy -= (int)doc->size().height();
+ QSize dsize = doc->size().toSize();
+ if (dsize != layedOutTextSize) {
+ q->prepareGeometryChange();
+ layedOutTextSize = dsize;
+ }
+ size = QSize(int(doc->idealWidth()),dsize.height());
+ }
+ int yoff = 0;
+
+ if (q->heightValid()) {
+ if (vAlign == QDeclarativeText::AlignBottom)
+ yoff = dy;
+ else if (vAlign == QDeclarativeText::AlignVCenter)
+ yoff = dy/2;
+ }
+ q->setBaselineOffset(fm.ascent() + yoff);
+
+ //### need to comfirm cost of always setting these for richText
+ internalWidthUpdate = true;
+ q->setImplicitWidth(size.width());
+ internalWidthUpdate = false;
+ q->setImplicitHeight(size.height());
+ emit q->paintedSizeChanged();
+}
+
+/*!
+ Lays out the QDeclarativeTextPrivate::layout QTextLayout in the constraints of the QDeclarativeText.
+
+ Returns the size of the final text. This can be used to position the text vertically (the text is
+ already absolutely positioned horizontally).
+*/
+QSize QDeclarativeTextPrivate::setupTextLayout()
+{
+ // ### text layout handling should be profiled and optimized as needed
+ // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
+
+ Q_Q(QDeclarativeText);
+ layout.setCacheEnabled(true);
+
+ int height = 0;
+ qreal widthUsed = 0;
+ qreal lineWidth = 0;
+
+ //set manual width
+ if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid())
+ lineWidth = q->width();
+
+ QTextOption textOption = layout.textOption();
+ textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
+ layout.setTextOption(textOption);
+
+ layout.beginLayout();
+ while (1) {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+
+ if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid())
+ line.setLineWidth(lineWidth);
+ }
+ layout.endLayout();
+
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ widthUsed = qMax(widthUsed, line.naturalTextWidth());
+ }
+
+ qreal layoutWidth = q->widthValid()?q->width():widthUsed;
+
+ int x = 0;
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ line.setPosition(QPointF(0, height));
+ height += int(line.height());
+
+ if (!cacheAllTextAsImage) {
+ if (hAlign == QDeclarativeText::AlignLeft) {
+ x = 0;
+ } else if (hAlign == QDeclarativeText::AlignRight) {
+ x = layoutWidth - (int)line.naturalTextWidth();
+ } else if (hAlign == QDeclarativeText::AlignHCenter) {
+ x = (layoutWidth - (int)line.naturalTextWidth()) / 2;
+ }
+ line.setPosition(QPoint(x, (int)line.y()));
+ }
+ }
+
+ return QSize(qCeil(widthUsed), height);
+}
+
+/*!
+ Returns a painted version of the QDeclarativeTextPrivate::layout QTextLayout.
+ If \a drawStyle is true, the style color overrides all colors in the document.
+*/
+QPixmap QDeclarativeTextPrivate::textLayoutImage(bool drawStyle)
+{
+ //do layout
+ QSize size = layedOutTextSize;
+
+ int x = 0;
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ if (hAlign == QDeclarativeText::AlignLeft) {
+ x = 0;
+ } else if (hAlign == QDeclarativeText::AlignRight) {
+ x = size.width() - (int)line.naturalTextWidth();
+ } else if (hAlign == QDeclarativeText::AlignHCenter) {
+ x = (size.width() - (int)line.naturalTextWidth()) / 2;
+ }
+ line.setPosition(QPoint(x, (int)line.y()));
+ }
+
+ //paint text
+ QPixmap img(size);
+ if (!size.isEmpty()) {
+ img.fill(Qt::transparent);
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
+ QPainter p(&img);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+ drawTextLayout(&p, QPointF(0,0), drawStyle);
+ }
+ return img;
+}
+
+/*!
+ Paints the QDeclarativeTextPrivate::layout QTextLayout into \a painter at \a pos. If
+ \a drawStyle is true, the style color overrides all colors in the document.
+*/
+void QDeclarativeTextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle)
+{
+ if (drawStyle)
+ painter->setPen(styleColor);
+ else
+ painter->setPen(color);
+ painter->setFont(font);
+ layout.draw(painter, pos);
+}
+
+/*!
+ Returns a painted version of the QDeclarativeTextPrivate::doc QTextDocument.
+ If \a drawStyle is true, the style color overrides all colors in the document.
+*/
+QPixmap QDeclarativeTextPrivate::textDocumentImage(bool drawStyle)
+{
+ QSize size = doc->size().toSize();
+
+ //paint text
+ QPixmap img(size);
+ img.fill(Qt::transparent);
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
+ QPainter p(&img);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+
+ QAbstractTextDocumentLayout::PaintContext context;
+
+ QTextOption oldOption(doc->defaultTextOption());
+ if (drawStyle) {
+ context.palette.setColor(QPalette::Text, styleColor);
+ QTextOption colorOption(doc->defaultTextOption());
+ colorOption.setFlags(QTextOption::SuppressColors);
+ doc->setDefaultTextOption(colorOption);
+ } else {
+ context.palette.setColor(QPalette::Text, color);
+ }
+ doc->documentLayout()->draw(&p, context);
+ if (drawStyle)
+ doc->setDefaultTextOption(oldOption);
+ return img;
+}
+
+/*!
+ Mark the image cache as dirty.
+*/
+void QDeclarativeTextPrivate::invalidateImageCache()
+{
+ Q_Q(QDeclarativeText);
+
+ if (imageCacheDirty)
+ return;
+
+ imageCacheDirty = true;
+ imageCache = QPixmap();
+
+ if (q->isComponentComplete())
+ q->update();
+}
+
+/*!
+ Tests if the image cache is dirty, and repaints it if it is.
+*/
+void QDeclarativeTextPrivate::checkImageCache()
+{
+ if (!imageCacheDirty)
+ return;
+
+ if (text.isEmpty()) {
+
+ imageCache = QPixmap();
+
+ } else {
+
+ QPixmap textImage;
+ QPixmap styledImage;
+
+ if (richText) {
+ textImage = textDocumentImage(false);
+ if (style != QDeclarativeText::Normal)
+ styledImage = textDocumentImage(true); //### should use styleColor
+ } else {
+ textImage = textLayoutImage(false);
+ if (style != QDeclarativeText::Normal)
+ styledImage = textLayoutImage(true); //### should use styleColor
+ }
+
+ switch (style) {
+ case QDeclarativeText::Outline:
+ imageCache = drawOutline(textImage, styledImage);
+ break;
+ case QDeclarativeText::Sunken:
+ imageCache = drawOutline(textImage, styledImage, -1);
+ break;
+ case QDeclarativeText::Raised:
+ imageCache = drawOutline(textImage, styledImage, 1);
+ break;
+ default:
+ imageCache = textImage;
+ break;
+ }
+
+ }
+
+ imageCacheDirty = false;
+}
+
+/*!
+ Ensures the QDeclarativeTextPrivate::doc variable is set to a valid text document
+*/
+void QDeclarativeTextPrivate::ensureDoc()
+{
+ if (!doc) {
+ Q_Q(QDeclarativeText);
+ doc = new QTextDocumentWithImageResources(q);
+ doc->setDocumentMargin(0);
+ }
+}
+
+/*!
+ Draw \a styleSource as an outline around \a source and return the new image.
+*/
+QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource)
+{
+ QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ QPoint pos(0, 0);
+ pos += QPoint(-1, 0);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(2, 0);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(-1, -1);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(0, 2);
+ ppm.drawPixmap(pos, styleSource);
+
+ pos += QPoint(0, -1);
+ ppm.drawPixmap(pos, source);
+ ppm.end();
+
+ return img;
+}
+
+/*!
+ Draw \a styleSource below \a source at \a yOffset and return the new image.
+*/
+QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset)
+{
+ QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ ppm.drawPixmap(QPoint(0, yOffset), styleSource);
+ ppm.drawPixmap(0, 0, source);
+
+ ppm.end();
+
+ return img;
+}
+
/*!
\qmlclass Text QDeclarativeText
\ingroup qml-basic-visual-elements
@@ -199,10 +587,44 @@ QDeclarativeText::~QDeclarativeText()
{
}
+/*!
+ \qmlproperty bool Text::clip
+ This property holds whether the text is clipped.
+
+ Note that if the text does not fit in the bounding rectangle it will be abruptly chopped.
-QDeclarativeTextPrivate::~QDeclarativeTextPrivate()
-{
-}
+ If you want to display potentially long text in a limited space, you probably want to use \c elide instead.
+*/
+
+/*!
+ \qmlproperty bool Text::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlsignal Text::onLinkActivated(string link)
+
+ This handler is called when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+
+ \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
+
+ The example code will display the text
+ "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
+
+ Clicking on the highlighted link will output
+ \tt{http://qt.nokia.com link activated} to the console.
+*/
/*!
\qmlproperty string Text::font.family
@@ -308,7 +730,6 @@ QDeclarativeTextPrivate::~QDeclarativeTextPrivate()
Text { text: "Hello"; font.capitalization: Font.AllLowercase }
\endqml
*/
-
QFont QDeclarativeText::font() const
{
Q_D(const QDeclarativeText);
@@ -322,30 +743,9 @@ void QDeclarativeText::setFont(const QFont &font)
return;
d->font = font;
-
d->updateLayout();
- d->markImgDirty();
- emit fontChanged(d->font);
-}
-
-void QDeclarativeText::setText(const QString &n)
-{
- Q_D(QDeclarativeText);
- if (d->text == n)
- return;
- d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
- if (d->richText) {
- if (isComponentComplete()) {
- d->ensureDoc();
- d->doc->setText(n);
- }
- }
-
- d->text = n;
- d->updateLayout();
- d->markImgDirty();
- emit textChanged(d->text);
+ emit fontChanged(d->font);
}
/*!
@@ -362,17 +762,25 @@ QString QDeclarativeText::text() const
return d->text;
}
-void QDeclarativeText::setColor(const QColor &color)
+void QDeclarativeText::setText(const QString &n)
{
Q_D(QDeclarativeText);
- if (d->color == color)
+ if (d->text == n)
return;
- d->color = color;
- d->markImgDirty();
- emit colorChanged(d->color);
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
+ if (d->richText && isComponentComplete()) {
+ d->ensureDoc();
+ d->doc->setText(n);
+ }
+
+ d->text = n;
+ d->updateLayout();
+
+ emit textChanged(d->text);
}
+
/*!
\qmlproperty color Text::color
@@ -386,13 +794,23 @@ void QDeclarativeText::setColor(const QColor &color)
Text { color: "steelblue"; ... }
\endqml
*/
-
QColor QDeclarativeText::color() const
{
Q_D(const QDeclarativeText);
return d->color;
}
+void QDeclarativeText::setColor(const QColor &color)
+{
+ Q_D(QDeclarativeText);
+ if (d->color == color)
+ return;
+
+ d->color = color;
+ d->invalidateImageCache();
+ emit colorChanged(d->color);
+}
+
/*!
\qmlproperty enumeration Text::style
@@ -433,21 +851,10 @@ void QDeclarativeText::setStyle(QDeclarativeText::TextStyle style)
if (isComponentComplete() && (d->style == Normal || style == Normal))
prepareGeometryChange();
d->style = style;
- d->markImgDirty();
+ d->invalidateImageCache();
emit styleChanged(d->style);
}
-void QDeclarativeText::setStyleColor(const QColor &color)
-{
- Q_D(QDeclarativeText);
- if (d->styleColor == color)
- return;
-
- d->styleColor = color;
- d->markImgDirty();
- emit styleColorChanged(d->styleColor);
-}
-
/*!
\qmlproperty color Text::styleColor
@@ -469,6 +876,18 @@ QColor QDeclarativeText::styleColor() const
return d->styleColor;
}
+void QDeclarativeText::setStyleColor(const QColor &color)
+{
+ Q_D(QDeclarativeText);
+ if (d->styleColor == color)
+ return;
+
+ d->styleColor = color;
+ d->invalidateImageCache();
+ emit styleColorChanged(d->styleColor);
+}
+
+
/*!
\qmlproperty enumeration Text::horizontalAlignment
\qmlproperty enumeration Text::verticalAlignment
@@ -499,7 +918,10 @@ void QDeclarativeText::setHAlign(HAlignment align)
if (isComponentComplete())
prepareGeometryChange();
+
d->hAlign = align;
+ d->updateLayout();
+
emit horizontalAlignmentChanged(align);
}
@@ -547,9 +969,8 @@ void QDeclarativeText::setWrapMode(WrapMode mode)
return;
d->wrapMode = mode;
-
d->updateLayout();
- d->markImgDirty();
+
emit wrapModeChanged();
}
@@ -609,7 +1030,6 @@ Column {
\o \image declarative-textformat.png
\endtable
*/
-
QDeclarativeText::TextFormat QDeclarativeText::textFormat() const
{
Q_D(const QDeclarativeText);
@@ -625,19 +1045,13 @@ void QDeclarativeText::setTextFormat(TextFormat format)
bool wasRich = d->richText;
d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
- if (wasRich && !d->richText) {
- //### delete control? (and vice-versa below)
- d->updateLayout();
- d->markImgDirty();
- } else if (!wasRich && d->richText) {
- if (isComponentComplete()) {
- d->ensureDoc();
- d->doc->setText(d->text);
- }
- d->updateLayout();
- d->markImgDirty();
+ if (!wasRich && d->richText && isComponentComplete()) {
+ d->ensureDoc();
+ d->doc->setText(d->text);
}
+ d->updateLayout();
+
emit textFormatChanged(d->format);
}
@@ -676,12 +1090,12 @@ void QDeclarativeText::setElideMode(QDeclarativeText::TextElideMode mode)
return;
d->elideMode = mode;
-
d->updateLayout();
- d->markImgDirty();
+
emit elideModeChanged(d->elideMode);
}
+/*! \internal */
QRectF QDeclarativeText::boundingRect() const
{
Q_D(const QDeclarativeText);
@@ -692,7 +1106,7 @@ QRectF QDeclarativeText::boundingRect() const
int x = 0;
int y = 0;
- QSize size = d->cachedLayoutSize;
+ QSize size = d->layedOutTextSize;
if (d->style != Normal)
size += QSize(2,2);
@@ -725,117 +1139,23 @@ QRectF QDeclarativeText::boundingRect() const
return QRectF(x,y,size.width(),size.height());
}
-void QDeclarativeText::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
+/*! \internal */
+void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QDeclarativeText);
- if (!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width()) {
- if (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone) {
- //re-elide if needed
- if (d->singleline && d->elideMode != QDeclarativeText::ElideNone &&
- isComponentComplete() && widthValid()) {
-
- QFontMetrics fm(d->font);
- QString tmp = fm.elidedText(d->text,(Qt::TextElideMode)d->elideMode,width()); // XXX still worth layout...?
- d->layout.setText(tmp);
- }
+ if (!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width() &&
+ (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone)) {
- d->imgDirty = true;
+ if (d->singleline && d->elideMode != QDeclarativeText::ElideNone && widthValid()) {
+ // We need to re-elide
+ d->updateLayout();
+ } else {
+ // We just need to re-layout
d->updateSize();
}
}
- QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
-}
-void QDeclarativeTextPrivate::updateLayout()
-{
- Q_Q(QDeclarativeText);
- if (q->isComponentComplete()) {
- //setup instance of QTextLayout for all cases other than richtext
- if (!richText) {
- layout.clearLayout();
- layout.setFont(font);
- if (format != QDeclarativeText::StyledText) {
- QString tmp = text;
- tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
- singleline = !tmp.contains(QChar::LineSeparator);
- if (singleline && elideMode != QDeclarativeText::ElideNone && q->widthValid()) {
- QFontMetrics fm(font);
- tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...?
- }
- layout.setText(tmp);
- } else {
- singleline = false;
- QDeclarativeStyledText::parse(text, layout);
- }
- }
- updateSize();
- } else {
- dirty = true;
- }
-}
-
-
-void QDeclarativeTextPrivate::updateSize()
-{
- Q_Q(QDeclarativeText);
- if (q->isComponentComplete()) {
- QFontMetrics fm(font);
- if (text.isEmpty()) {
- q->setImplicitHeight(fm.height());
- emit q->paintedSizeChanged();
- return;
- }
-
- int dy = q->height();
- QSize size(0, 0);
-
- //setup instance of QTextLayout for all cases other than richtext
- if (!richText) {
- size = setupTextLayout(&layout);
- if (cachedLayoutSize != size) {
- q->prepareGeometryChange();
- cachedLayoutSize = size;
- }
- dy -= size.height();
- } else {
- singleline = false; // richtext can't elide or be optimized for single-line case
- ensureDoc();
- doc->setDefaultFont(font);
- QTextOption option((Qt::Alignment)int(hAlign | vAlign));
- option.setWrapMode(QTextOption::WrapMode(wrapMode));
- doc->setDefaultTextOption(option);
- if (wrapMode != QDeclarativeText::NoWrap && q->widthValid())
- doc->setTextWidth(q->width());
- else
- doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
- dy -= (int)doc->size().height();
- QSize dsize = doc->size().toSize();
- if (dsize != cachedLayoutSize) {
- q->prepareGeometryChange();
- cachedLayoutSize = dsize;
- }
- size = QSize(int(doc->idealWidth()),dsize.height());
- }
- int yoff = 0;
-
- if (q->heightValid()) {
- if (vAlign == QDeclarativeText::AlignBottom)
- yoff = dy;
- else if (vAlign == QDeclarativeText::AlignVCenter)
- yoff = dy/2;
- }
- q->setBaselineOffset(fm.ascent() + yoff);
-
- //### need to comfirm cost of always setting these for richText
- internalWidthUpdate = true;
- q->setImplicitWidth(size.width());
- internalWidthUpdate = false;
- q->setImplicitHeight(size.height());
- emit q->paintedSizeChanged();
- } else {
- dirty = true;
- }
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
}
/*!
@@ -860,228 +1180,6 @@ qreal QDeclarativeText::paintedHeight() const
return implicitHeight();
}
-
-
-// ### text layout handling should be profiled and optimized as needed
-// what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
-
-void QDeclarativeTextPrivate::drawOutline()
-{
- QPixmap img = QPixmap(imgStyleCache.width()+2,imgStyleCache.height()+2);
- img.fill(Qt::transparent);
-
- QPainter ppm(&img);
-
- QPoint pos(imgCache.rect().topLeft());
- pos += QPoint(-1, 0);
- ppm.drawPixmap(pos, imgStyleCache);
- pos += QPoint(2, 0);
- ppm.drawPixmap(pos, imgStyleCache);
- pos += QPoint(-1, -1);
- ppm.drawPixmap(pos, imgStyleCache);
- pos += QPoint(0, 2);
- ppm.drawPixmap(pos, imgStyleCache);
-
- pos += QPoint(0, -1);
- ppm.drawPixmap(pos, imgCache);
- ppm.end();
-
- imgCache = img;
-}
-
-void QDeclarativeTextPrivate::drawOutline(int yOffset)
-{
- QPixmap img = QPixmap(imgStyleCache.width()+2,imgStyleCache.height()+2);
- img.fill(Qt::transparent);
-
- QPainter ppm(&img);
-
- QPoint pos(imgCache.rect().topLeft());
- pos += QPoint(0, yOffset);
- ppm.drawPixmap(pos, imgStyleCache);
-
- pos += QPoint(0, -yOffset);
- ppm.drawPixmap(pos, imgCache);
- ppm.end();
-
- imgCache = img;
-}
-
-QSize QDeclarativeTextPrivate::setupTextLayout(QTextLayout *layout)
-{
- Q_Q(QDeclarativeText);
- layout->setCacheEnabled(true);
-
- int height = 0;
- qreal widthUsed = 0;
- qreal lineWidth = 0;
-
- //set manual width
- if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid())
- lineWidth = q->width();
-
- QTextOption textOption = layout->textOption();
- textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
- layout->setTextOption(textOption);
-
- layout->beginLayout();
-
- while (1) {
- QTextLine line = layout->createLine();
- if (!line.isValid())
- break;
-
- if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid())
- line.setLineWidth(lineWidth);
- }
- layout->endLayout();
-
- int x = 0;
- for (int i = 0; i < layout->lineCount(); ++i) {
- QTextLine line = layout->lineAt(i);
- widthUsed = qMax(widthUsed, line.naturalTextWidth());
- line.setPosition(QPointF(0, height));
- height += int(line.height());
-
- if (!cache) {
- if (hAlign == QDeclarativeText::AlignLeft) {
- x = 0;
- } else if (hAlign == QDeclarativeText::AlignRight) {
- x = q->width() - (int)line.naturalTextWidth();
- } else if (hAlign == QDeclarativeText::AlignHCenter) {
- x = (q->width() - (int)line.naturalTextWidth()) / 2;
- }
- line.setPosition(QPoint(x, (int)line.y()));
- }
- }
-
- return QSize(qCeil(widthUsed), height);
-}
-
-QPixmap QDeclarativeTextPrivate::wrappedTextImage(bool drawStyle)
-{
- //do layout
- QSize size = cachedLayoutSize;
-
- int x = 0;
- for (int i = 0; i < layout.lineCount(); ++i) {
- QTextLine line = layout.lineAt(i);
- if (hAlign == QDeclarativeText::AlignLeft) {
- x = 0;
- } else if (hAlign == QDeclarativeText::AlignRight) {
- x = size.width() - (int)line.naturalTextWidth();
- } else if (hAlign == QDeclarativeText::AlignHCenter) {
- x = (size.width() - (int)line.naturalTextWidth()) / 2;
- }
- line.setPosition(QPoint(x, (int)line.y()));
- }
-
- //paint text
- QPixmap img(size);
- if (!size.isEmpty()) {
- img.fill(Qt::transparent);
-#ifdef Q_WS_MAC
- bool oldSmooth = qt_applefontsmoothing_enabled;
- qt_applefontsmoothing_enabled = false;
-#endif
- QPainter p(&img);
-#ifdef Q_WS_MAC
- qt_applefontsmoothing_enabled = oldSmooth;
-#endif
- drawWrappedText(&p, QPointF(0,0), drawStyle);
- }
- return img;
-}
-
-void QDeclarativeTextPrivate::drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle)
-{
- if (drawStyle)
- p->setPen(styleColor);
- else
- p->setPen(color);
- p->setFont(font);
- layout.draw(p, pos);
-}
-
-QPixmap QDeclarativeTextPrivate::richTextImage(bool drawStyle)
-{
- QSize size = doc->size().toSize();
-
- //paint text
- QPixmap img(size);
- img.fill(Qt::transparent);
-#ifdef Q_WS_MAC
- bool oldSmooth = qt_applefontsmoothing_enabled;
- qt_applefontsmoothing_enabled = false;
-#endif
- QPainter p(&img);
-#ifdef Q_WS_MAC
- qt_applefontsmoothing_enabled = oldSmooth;
-#endif
-
- QAbstractTextDocumentLayout::PaintContext context;
-
- QTextOption oldOption(doc->defaultTextOption());
- if (drawStyle) {
- context.palette.setColor(QPalette::Text, styleColor);
- QTextOption colorOption(doc->defaultTextOption());
- colorOption.setFlags(QTextOption::SuppressColors);
- doc->setDefaultTextOption(colorOption);
- } else {
- context.palette.setColor(QPalette::Text, color);
- }
- doc->documentLayout()->draw(&p, context);
- if (drawStyle)
- doc->setDefaultTextOption(oldOption);
- return img;
-}
-
-void QDeclarativeTextPrivate::checkImgCache()
-{
- if (!imgDirty)
- return;
-
- bool empty = text.isEmpty();
- QPixmap newImgCache;
- if (empty) {
- imgStyleCache = QPixmap();
- } else if (richText) {
- newImgCache = richTextImage(false);
- if (style != QDeclarativeText::Normal)
- imgStyleCache = richTextImage(true); //### should use styleColor
- } else {
- newImgCache = wrappedTextImage(false);
- if (style != QDeclarativeText::Normal)
- imgStyleCache = wrappedTextImage(true); //### should use styleColor
- }
- imgCache = newImgCache;
- if (!empty)
- switch (style) {
- case QDeclarativeText::Outline:
- drawOutline();
- break;
- case QDeclarativeText::Sunken:
- drawOutline(-1);
- break;
- case QDeclarativeText::Raised:
- drawOutline(1);
- break;
- default:
- break;
- }
-
- imgDirty = false;
-}
-
-void QDeclarativeTextPrivate::ensureDoc()
-{
- if (!doc) {
- Q_Q(QDeclarativeText);
- doc = new QTextDocumentWithImageResources(q);
- doc->setDocumentMargin(0);
- }
-}
-
/*!
Returns the number of resources (images) that are being loaded asynchronously.
*/
@@ -1091,22 +1189,14 @@ int QDeclarativeText::resourcesLoading() const
return d->doc ? d->doc->resourcesLoading() : 0;
}
-/*!
- \qmlproperty bool Text::clip
- This property holds whether the text is clipped.
-
- Note that if the text does not fit in the bounding rectangle it will be abruptly chopped.
-
- If you want to display potentially long text in a limited space, you probably want to use \c elide instead.
-*/
-
+/*! \internal */
void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
Q_D(QDeclarativeText);
- if (d->cache || d->style != Normal) {
- d->checkImgCache();
- if (d->imgCache.isNull())
+ if (d->cacheAllTextAsImage || d->style != Normal) {
+ d->checkImageCache();
+ if (d->imageCache.isNull())
return;
bool oldAA = p->testRenderHint(QPainter::Antialiasing);
@@ -1116,23 +1206,23 @@ void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid
QRect br = boundingRect().toRect();
- bool needClip = clip() && (d->imgCache.width() > width() ||
- d->imgCache.height() > height());
+ bool needClip = clip() && (d->imageCache.width() > width() ||
+ d->imageCache.height() > height());
if (needClip)
- p->drawPixmap(0, 0, width(), height(), d->imgCache, -br.x(), -br.y(), width(), height());
+ p->drawPixmap(0, 0, width(), height(), d->imageCache, -br.x(), -br.y(), width(), height());
else
- p->drawPixmap(br.x(), br.y(), d->imgCache);
+ p->drawPixmap(br.x(), br.y(), d->imageCache);
if (d->smooth) {
p->setRenderHint(QPainter::Antialiasing, oldAA);
p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
}
} else {
- qreal y = boundingRect().y();
+ QRectF bounds = boundingRect();
- bool needClip = !clip() && (d->cachedLayoutSize.width() > width() ||
- d->cachedLayoutSize.height() > height());
+ bool needClip = clip() && (d->layedOutTextSize.width() > width() ||
+ d->layedOutTextSize.height() > height());
if (needClip) {
p->save();
@@ -1141,49 +1231,35 @@ void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid
if (d->richText) {
QAbstractTextDocumentLayout::PaintContext context;
context.palette.setColor(QPalette::Text, d->color);
- p->translate(0, y);
+ p->translate(bounds.x(), bounds.y());
d->doc->documentLayout()->draw(p, context);
- p->translate(0, -y);
+ p->translate(-bounds.x(), -bounds.y());
} else {
- d->drawWrappedText(p, QPointF(0,y), false);
+ d->drawTextLayout(p, QPointF(0, bounds.y()), false);
}
- if (needClip)
+
+ if (needClip) {
p->restore();
+ }
}
}
-/*!
- \qmlproperty bool Text::smooth
-
- This property holds whether the text is smoothly scaled or transformed.
-
- Smooth filtering gives better visual quality, but is slower. If
- the item is displayed at its natural size, this property has no visual or
- performance effect.
-
- \note Generally scaling artifacts are only visible if the item is stationary on
- the screen. A common pattern when animating an item is to disable smooth
- filtering at the beginning of the animation and reenable it at the conclusion.
-*/
-
+/*! \internal */
void QDeclarativeText::componentComplete()
{
Q_D(QDeclarativeText);
QDeclarativeItem::componentComplete();
- if (d->dirty) {
+ if (d->updateOnComponentComplete) {
+ d->updateOnComponentComplete = false;
if (d->richText) {
d->ensureDoc();
d->doc->setText(d->text);
}
d->updateLayout();
- d->dirty = false;
}
}
-/*!
- \overload
- Handles the given mouse \a event.
- */
+/*! \internal */
void QDeclarativeText::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QDeclarativeText);
@@ -1202,26 +1278,7 @@ void QDeclarativeText::mousePressEvent(QGraphicsSceneMouseEvent *event)
}
-/*!
- \qmlsignal Text::onLinkActivated(string link)
-
- This handler is called when the user clicks on a link embedded in the text.
- The link must be in rich text or HTML format and the
- \a link string provides access to the particular link.
-
- \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
-
- The example code will display the text
- "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
-
- Clicking on the highlighted link will output
- \tt{http://qt.nokia.com link activated} to the console.
-*/
-
-/*!
- \overload
- Handles the given mouse \a event.
- */
+/*! \internal */
void QDeclarativeText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QDeclarativeText);
diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h
index 48552a7..e37f477 100644
--- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h
@@ -55,6 +55,7 @@
#include "qdeclarativeitem.h"
#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativetextlayout_p.h"
#include <qdeclarative.h>
@@ -69,39 +70,12 @@ class QDeclarativeTextPrivate : public QDeclarativeItemPrivate
{
Q_DECLARE_PUBLIC(QDeclarativeText)
public:
- QDeclarativeTextPrivate()
- : color((QRgb)0), style(QDeclarativeText::Normal),
- hAlign(QDeclarativeText::AlignLeft), vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone),
- imgDirty(true), dirty(true), richText(false), singleline(false), cache(true), internalWidthUpdate(false), doc(0),
- format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap)
- {
-#if defined(QML_NO_TEXT_CACHE)
- cache = false;
-#endif
- QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton;
- QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
- }
+ QDeclarativeTextPrivate();
~QDeclarativeTextPrivate();
- void ensureDoc();
void updateSize();
void updateLayout();
- void markImgDirty() {
- Q_Q(QDeclarativeText);
- imgDirty = true;
- if (q->isComponentComplete())
- q->update();
- }
- void checkImgCache();
-
- void drawOutline();
- void drawOutline(int yOffset);
-
- QPixmap wrappedTextImage(bool drawStyle);
- void drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle);
- QPixmap richTextImage(bool drawStyle);
- QSize setupTextLayout(QTextLayout *layout);
QString text;
QFont font;
@@ -109,23 +83,37 @@ public:
QDeclarativeText::TextStyle style;
QColor styleColor;
QString activeLink;
- QPixmap imgCache;
- QPixmap imgStyleCache;
QDeclarativeText::HAlignment hAlign;
QDeclarativeText::VAlignment vAlign;
QDeclarativeText::TextElideMode elideMode;
- bool imgDirty:1;
- bool dirty:1;
+ QDeclarativeText::TextFormat format;
+ QDeclarativeText::WrapMode wrapMode;
+
+ void invalidateImageCache();
+ void checkImageCache();
+ QPixmap imageCache;
+
+ bool imageCacheDirty:1;
+ bool updateOnComponentComplete:1;
bool richText:1;
bool singleline:1;
- bool cache:1;
+ bool cacheAllTextAsImage:1;
bool internalWidthUpdate:1;
- QTextDocumentWithImageResources *doc;
- QTextLayout layout;
- QSize cachedLayoutSize;
- QDeclarativeText::TextFormat format;
- QDeclarativeText::WrapMode wrapMode;
+
+ QSize layedOutTextSize;
+ void ensureDoc();
+ QPixmap textDocumentImage(bool drawStyle);
+ QTextDocumentWithImageResources *doc;
+
+ QSize setupTextLayout();
+ QPixmap textLayoutImage(bool drawStyle);
+ void drawTextLayout(QPainter *p, const QPointF &pos, bool drawStyle);
+ QDeclarativeTextLayout layout;
+
+ static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource);
+ static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset);
+
static inline QDeclarativeTextPrivate *get(QDeclarativeText *t) {
return t->d_func();
}
diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
index 6f5608a..e05f4e4 100644
--- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
@@ -319,6 +319,7 @@ void QDeclarativeTextEdit::setTextFormat(TextFormat format)
updateSize();
}
d->format = format;
+ d->control->setAcceptRichText(d->format != PlainText);
emit textFormatChanged(d->format);
}
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
index 4817999..0903427 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
@@ -417,7 +417,11 @@ void QDeclarativeTextInput::setCursorVisible(bool on)
return;
d->cursorVisible = on;
d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
- //d->control should emit the cursor update regions
+ QRect r = d->control->cursorRect();
+ if (d->control->inputMask().isEmpty())
+ updateRect(r);
+ else
+ updateRect();
emit cursorVisibleChanged(d->cursorVisible);
}
@@ -1460,6 +1464,7 @@ void QDeclarativeTextInputPrivate::init()
void QDeclarativeTextInput::cursorPosChanged()
{
Q_D(QDeclarativeTextInput);
+ d->updateHorizontalScroll();
updateRect();//TODO: Only update rect between pos's
updateMicroFocus();
emit cursorPositionChanged();
diff --git a/src/declarative/graphicsitems/qdeclarativetextlayout.cpp b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp
new file mode 100644
index 0000000..e8b5fb2
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativetextlayout_p.h"
+#include <private/qstatictext_p.h>
+#include <private/qfontengine_p.h>
+#include <private/qtextengine_p.h>
+#include <private/qpainter_p.h>
+#include <private/qpaintengineex_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeTextLayoutPrivate
+{
+public:
+ QDeclarativeTextLayoutPrivate()
+ : cached(false) {}
+
+ QPointF position;
+
+ bool cached;
+ QVector<QStaticTextItem> items;
+ QVector<QFixedPoint> positions;
+ QVector<glyph_t> glyphs;
+ QVector<QChar> chars;
+};
+
+Q_GUI_EXPORT extern int qt_defaultDpiX();
+Q_GUI_EXPORT extern int qt_defaultDpiY();
+
+namespace {
+class DrawTextItemRecorder: public QPaintEngine
+{
+ public:
+ DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations)
+ : m_inertText(0), m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations),
+ m_untransformedCoordinates(untransformedCoordinates)
+ {
+ }
+
+ virtual void updateState(const QPaintEngineState &newState)
+ {
+ if (newState.state() & QPaintEngine::DirtyPen)
+ m_dirtyPen = true;
+ }
+
+ virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
+ {
+ int glyphOffset = m_inertText->glyphs.size(); // Store offset into glyph pool
+ int positionOffset = m_inertText->glyphs.size(); // Offset into position pool
+ int charOffset = m_inertText->chars.size();
+
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+
+ bool needFreshCurrentItem = true;
+ if (!m_inertText->items.isEmpty()) {
+ QStaticTextItem &last = m_inertText->items[m_inertText->items.count() - 1];
+
+ if (last.fontEngine == ti.fontEngine && last.font == ti.font() &&
+ (!m_dirtyPen || last.color == state->pen().color())) {
+ needFreshCurrentItem = false;
+
+ last.numChars += ti.num_chars;
+ last.numGlyphs += ti.glyphs.numGlyphs;
+
+ }
+ }
+
+ if (needFreshCurrentItem) {
+ QStaticTextItem currentItem;
+
+ currentItem.fontEngine = ti.fontEngine;
+ currentItem.font = ti.font();
+ currentItem.charOffset = charOffset;
+ currentItem.numChars = ti.num_chars;
+ currentItem.numGlyphs = ti.glyphs.numGlyphs;
+ currentItem.glyphOffset = glyphOffset;
+ currentItem.positionOffset = positionOffset;
+ currentItem.useBackendOptimizations = m_useBackendOptimizations;
+ if (m_dirtyPen)
+ currentItem.color = state->pen().color();
+
+ m_inertText->items.append(currentItem);
+ }
+
+ QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform();
+ matrix.translate(position.x(), position.y());
+
+ QVarLengthArray<glyph_t> glyphs;
+ QVarLengthArray<QFixedPoint> positions;
+ ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+
+ int size = glyphs.size();
+ Q_ASSERT(size == ti.glyphs.numGlyphs);
+ Q_ASSERT(size == positions.size());
+
+ m_inertText->glyphs.resize(m_inertText->glyphs.size() + size);
+ m_inertText->positions.resize(m_inertText->glyphs.size());
+ m_inertText->chars.resize(m_inertText->chars.size() + ti.num_chars);
+
+ glyph_t *glyphsDestination = m_inertText->glyphs.data() + glyphOffset;
+ qMemCopy(glyphsDestination, glyphs.constData(), sizeof(glyph_t) * ti.glyphs.numGlyphs);
+
+ QFixedPoint *positionsDestination = m_inertText->positions.data() + positionOffset;
+ qMemCopy(positionsDestination, positions.constData(), sizeof(QFixedPoint) * ti.glyphs.numGlyphs);
+
+ QChar *charsDestination = m_inertText->chars.data() + charOffset;
+ qMemCopy(charsDestination, ti.chars, sizeof(QChar) * ti.num_chars);
+
+ }
+
+ virtual void drawPolygon(const QPointF *, int , PolygonDrawMode )
+ {
+ /* intentionally empty */
+ }
+
+ virtual bool begin(QPaintDevice *) { return true; }
+ virtual bool end() { return true; }
+ virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
+ virtual Type type() const
+ {
+ return User;
+ }
+
+ void begin(QDeclarativeTextLayoutPrivate *t) {
+ m_inertText = t;
+ m_dirtyPen = false;
+ }
+
+ private:
+ QDeclarativeTextLayoutPrivate *m_inertText;
+
+ bool m_dirtyPen;
+ bool m_useBackendOptimizations;
+ bool m_untransformedCoordinates;
+};
+
+class DrawTextItemDevice: public QPaintDevice
+{
+ public:
+ DrawTextItemDevice(bool untransformedCoordinates, bool useBackendOptimizations)
+ {
+ m_paintEngine = new DrawTextItemRecorder(untransformedCoordinates,
+ useBackendOptimizations);
+ }
+
+ ~DrawTextItemDevice()
+ {
+ delete m_paintEngine;
+ }
+
+ void begin(QDeclarativeTextLayoutPrivate *t) {
+ m_paintEngine->begin(t);
+ }
+
+ int metric(PaintDeviceMetric m) const
+ {
+ int val;
+ switch (m) {
+ case PdmWidth:
+ case PdmHeight:
+ case PdmWidthMM:
+ case PdmHeightMM:
+ val = 0;
+ break;
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ val = qt_defaultDpiX();
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ val = qt_defaultDpiY();
+ break;
+ case PdmNumColors:
+ val = 16777216;
+ break;
+ case PdmDepth:
+ val = 24;
+ break;
+ default:
+ val = 0;
+ qWarning("DrawTextItemDevice::metric: Invalid metric command");
+ }
+ return val;
+ }
+
+ virtual QPaintEngine *paintEngine() const
+ {
+ return m_paintEngine;
+ }
+
+ private:
+ DrawTextItemRecorder *m_paintEngine;
+};
+
+struct InertTextPainter {
+ InertTextPainter()
+ : device(true, true), painter(&device) {}
+
+ DrawTextItemDevice device;
+ QPainter painter;
+};
+}
+
+Q_GLOBAL_STATIC(InertTextPainter, inertTextPainter);
+
+/*!
+\class QDeclarativeTextLayout
+\brief The QDeclarativeTextLayout class is a version of QStaticText that works with QTextLayouts.
+\internal
+
+This class is basically a copy of the QStaticText code, but it is adapted to source its text from
+QTextLayout.
+
+It is also considerably faster to create a QDeclarativeTextLayout than a QStaticText because it uses
+a single, shared QPainter instance. QStaticText by comparison creates a new QPainter per instance.
+As a consequence this means that QDeclarativeTextLayout is not re-enterant. Adding a lock around
+the shared painter solves this, and only introduces a minor performance penalty, but is unnecessary
+for QDeclarativeTextLayout's current use (QDeclarativeText is already tied to the GUI thread).
+*/
+
+QDeclarativeTextLayout::QDeclarativeTextLayout()
+: d(0)
+{
+}
+
+QDeclarativeTextLayout::QDeclarativeTextLayout(const QString &text)
+: QTextLayout(text), d(0)
+{
+}
+
+QDeclarativeTextLayout::~QDeclarativeTextLayout()
+{
+ if (d) delete d;
+}
+
+void QDeclarativeTextLayout::beginLayout()
+{
+ if (d && d->cached) {
+ d->cached = false;
+ d->items.clear();
+ d->positions.clear();
+ d->glyphs.clear();
+ d->chars.clear();
+ d->position = QPointF();
+ }
+ QTextLayout::beginLayout();
+}
+
+void QDeclarativeTextLayout::prepare()
+{
+ if (!d || !d->cached) {
+
+ if (!d)
+ d = new QDeclarativeTextLayoutPrivate;
+
+ InertTextPainter *itp = inertTextPainter();
+ itp->device.begin(d);
+ QTextLayout::draw(&itp->painter, QPointF(0, 0));
+
+ glyph_t *glyphPool = d->glyphs.data();
+ QFixedPoint *positionPool = d->positions.data();
+ QChar *charPool = d->chars.data();
+
+ int itemCount = d->items.count();
+ for (int ii = 0; ii < itemCount; ++ii) {
+ QStaticTextItem &item = d->items[ii];
+ item.glyphs = glyphPool + item.glyphOffset;
+ item.glyphPositions = positionPool + item.positionOffset;
+ item.chars = charPool + item.charOffset;
+ }
+
+ d->cached = true;
+ }
+}
+
+void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p)
+{
+ QPainterPrivate *priv = QPainterPrivate::get(painter);
+
+ bool paintEngineSupportsTransformations = priv->extended &&
+ (priv->extended->type() == QPaintEngine::OpenGL2 ||
+ priv->extended->type() == QPaintEngine::OpenVG ||
+ priv->extended->type() == QPaintEngine::OpenGL);
+
+ if (!paintEngineSupportsTransformations) {
+ QTextLayout::draw(painter, p);
+ return;
+ }
+
+ prepare();
+
+ int itemCount = d->items.count();
+
+ if (p != d->position) {
+ QFixed fx = QFixed::fromReal(p.x());
+ QFixed fy = QFixed::fromReal(p.y());
+ QFixed oldX = QFixed::fromReal(d->position.x());
+ QFixed oldY = QFixed::fromReal(d->position.y());
+ for (int item = 0; item < itemCount; ++item) {
+ QStaticTextItem &textItem = d->items[item];
+
+ for (int ii = 0; ii < textItem.numGlyphs; ++ii) {
+ textItem.glyphPositions[ii].x += fx - oldX;
+ textItem.glyphPositions[ii].y += fy - oldY;
+ }
+ textItem.userDataNeedsUpdate = true;
+ }
+
+ d->position = p;
+ }
+
+ for (int ii = 0; ii < itemCount; ++ii) {
+ QStaticTextItem &item = d->items[ii];
+ priv->extended->drawStaticTextItem(&item);
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/graphicsitems/qdeclarativetextlayout_p.h b/src/declarative/graphicsitems/qdeclarativetextlayout_p.h
new file mode 100644
index 0000000..90bf0e0
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativetextlayout_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXTLAYOUT_P_H
+#define QDECLARATIVETEXTLAYOUT_P_H
+
+#include <QtGui/qtextlayout.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeTextLayoutPrivate;
+class QDeclarativeTextLayout : public QTextLayout
+{
+public:
+ QDeclarativeTextLayout();
+ QDeclarativeTextLayout(const QString &);
+ ~QDeclarativeTextLayout();
+
+ void beginLayout();
+
+ void prepare();
+ void draw(QPainter *, const QPointF & = QPointF());
+
+private:
+ QDeclarativeTextLayoutPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVETEXTLAYOUT_P_H
diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h
index 1d15dba..5e187c2 100644
--- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h
+++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h
@@ -67,7 +67,6 @@ class Q_AUTOTEST_EXPORT QDeclarativeVisualModel : public QObject
Q_PROPERTY(int count READ count NOTIFY countChanged)
public:
- QDeclarativeVisualModel(QObject *parent=0) : QObject(parent) {}
virtual ~QDeclarativeVisualModel() {}
enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };