From f02ce5b8e9f306d066b3a8edb240199444adaa43 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 27 Jun 2011 17:05:54 +1000 Subject: Add TextLayout element --- src/declarative/items/qsgtext.cpp | 30 +++- src/declarative/items/qsgtext_p.h | 9 + src/declarative/items/qsgtext_p_p.h | 2 + src/declarative/util/qdeclarativetextdocument.cpp | 197 ++++++++++++++++++++++ src/declarative/util/qdeclarativetextdocument_p.h | 119 +++++++++++++ src/declarative/util/qdeclarativeutilmodule.cpp | 2 + src/declarative/util/util.pri | 6 +- 7 files changed, 360 insertions(+), 5 deletions(-) create mode 100644 src/declarative/util/qdeclarativetextdocument.cpp create mode 100644 src/declarative/util/qdeclarativetextdocument_p.h diff --git a/src/declarative/items/qsgtext.cpp b/src/declarative/items/qsgtext.cpp index 3398824f69..cc8c6c5ba0 100644 --- a/src/declarative/items/qsgtext.cpp +++ b/src/declarative/items/qsgtext.cpp @@ -60,6 +60,7 @@ #include #include +#include #include #include @@ -106,7 +107,7 @@ QSGTextPrivate::QSGTextPrivate() richText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false), layoutTextElided(false), richTextAsImage(false), textureImageCacheDirty(false), naturalWidth(0), - doc(0), layoutThread(0), nodeType(NodeIsNull) + doc(0), layoutThread(0), textLayout(0), nodeType(NodeIsNull) { cacheAllTextAsImage = enableImageCache(); } @@ -1071,7 +1072,7 @@ QSGNode *QSGText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) Q_UNUSED(data); Q_D(QSGText); - if (d->text.isEmpty()) { + if (d->text.isEmpty() && !d->textLayout) { delete oldNode; return 0; } @@ -1138,7 +1139,10 @@ QSGNode *QSGText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) node->addTextDocument(bounds.topLeft(), d->doc, QColor(), d->style, d->styleColor); } else { - node->addTextLayout(QPoint(0, bounds.y()), &d->layout, d->color, d->style, d->styleColor); + if (d->textLayout) + node->addTextLayout(QPoint(0, bounds.y()), d->textLayout->layout(), d->color, d->style, d->styleColor); + else + node->addTextLayout(QPoint(0, bounds.y()), &d->layout, d->color, d->style, d->styleColor); } return node; @@ -1267,6 +1271,26 @@ void QSGText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QSGItem::mouseReleaseEvent(event); } +QDeclarativeTextDocument *QSGText::layout() const +{ + Q_D(const QSGText); + return d->textLayout; +} + +void QSGText::setLayout(QDeclarativeTextDocument* l) +{ + Q_D(QSGText); + d->textLayout = l; + QObject::connect(d->textLayout, SIGNAL(textLayoutChanged()), this, SLOT(textLayoutHasChanged())); +} + +void QSGText::textLayoutHasChanged() +{ + Q_D(QSGText); + d->updateLayout(); + update(); +} + QT_END_NAMESPACE #include "qsgtext.moc" diff --git a/src/declarative/items/qsgtext_p.h b/src/declarative/items/qsgtext_p.h index a5b61bcb2e..840ebcee49 100644 --- a/src/declarative/items/qsgtext_p.h +++ b/src/declarative/items/qsgtext_p.h @@ -46,6 +46,7 @@ #include "qsgimplicitsizeitem_p.h" #include +#include #include @@ -85,6 +86,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QSGText : public QSGImplicitSizeItem Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) Q_PROPERTY(qreal lineHeight READ lineHeight WRITE setLineHeight NOTIFY lineHeightChanged) Q_PROPERTY(LineHeightMode lineHeightMode READ lineHeightMode WRITE setLineHeightMode NOTIFY lineHeightModeChanged) + Q_PROPERTY(QDeclarativeTextDocument *layout READ layout WRITE setLayout NOTIFY layoutChanged) public: QSGText(QSGItem *parent=0); @@ -173,6 +175,9 @@ public: QRectF boundingRect() const; + QDeclarativeTextDocument *layout() const; + void setLayout(QDeclarativeTextDocument*); + Q_SIGNALS: void textChanged(const QString &text); void linkActivated(const QString &link); @@ -192,6 +197,10 @@ Q_SIGNALS: void lineHeightChanged(qreal lineHeight); void lineHeightModeChanged(LineHeightMode mode); void effectiveHorizontalAlignmentChanged(); + void layoutChanged(); + +private Q_SLOTS: + void textLayoutHasChanged(); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/src/declarative/items/qsgtext_p_p.h b/src/declarative/items/qsgtext_p_p.h index 6e98d30594..21b9d594af 100644 --- a/src/declarative/items/qsgtext_p_p.h +++ b/src/declarative/items/qsgtext_p_p.h @@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; +class QDeclarativeTextDocument; class QSGTextDocumentWithImageResources; class QSGPlainTexture; @@ -137,6 +138,7 @@ public: void drawTextLayout(QPainter *p, const QPointF &pos, bool drawStyle); QTextLayout layout; QThread *layoutThread; + QDeclarativeTextDocument *textLayout; static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource); static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset); diff --git a/src/declarative/util/qdeclarativetextdocument.cpp b/src/declarative/util/qdeclarativetextdocument.cpp new file mode 100644 index 0000000000..53d6111b9b --- /dev/null +++ b/src/declarative/util/qdeclarativetextdocument.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDeclarativeTextLine::QDeclarativeTextLine(QDeclarativeTextDocument* doc) + : QObject(0) +{ + _doc = doc; + _x = 0; + _y = 0; +} + +qreal QDeclarativeTextLine::x() const +{ + return _x; +} + +void QDeclarativeTextLine::setX(qreal x) +{ + _x = x; + _doc->doLayout(); +} + +qreal QDeclarativeTextLine::y() const +{ + return _y; +} + +void QDeclarativeTextLine::setY(qreal y) +{ + _y = y; + _doc->doLayout(); +} + +class QDeclarativeTextDocumentPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeTextDocument) + +public: + QString text; + qreal width; + QTextLayout layout; + QList lines; +}; + +QDeclarativeTextDocument::QDeclarativeTextDocument(QObject *parent) + : QObject(*(new QDeclarativeTextDocumentPrivate), parent) +{ + Q_D(QDeclarativeTextDocument); + d->text = QString(); + d->width = 0.0; +} + +QDeclarativeTextDocument::~QDeclarativeTextDocument() +{ +} + +qreal QDeclarativeTextDocument::width() const +{ + Q_D(const QDeclarativeTextDocument); + return d->width; +} + +void QDeclarativeTextDocument::setWidth(qreal w) +{ + Q_D(QDeclarativeTextDocument); + + if (w != d->width) { + d->width = w; + emit widthChanged(); + } +} + +QString QDeclarativeTextDocument::text() const +{ + Q_D(const QDeclarativeTextDocument); + return d->text; +} + +void QDeclarativeTextDocument::setText(const QString& text) +{ + Q_D(QDeclarativeTextDocument); + + if (text != d->text) { + d->text = text; +// d->layout.setText(text); + QDeclarativeStyledText::parse(text, d->layout); + emit textChanged(); + doLayout(); + } +} + +QObject *QDeclarativeTextDocument::lineAt(int i) const +{ + Q_D(const QDeclarativeTextDocument); + return d->lines.at(i); +} + +void QDeclarativeTextDocument::doLayout() +{ + Q_D(QDeclarativeTextDocument); + QTextOption textOption = d->layout.textOption(); + textOption.setAlignment(Qt::AlignJustify); + d->layout.setTextOption(textOption); + + qreal height = 0; + d->layout.clearLayout(); + d->layout.beginLayout(); + + int i = 0; + int l = 0; + + bool firstPass = d->lines.isEmpty(); + + forever { + QTextLine line = d->layout.createLine(); + + if (!line.isValid()) + break; + if (d->width) + line.setLineWidth(d->width); + + if (!firstPass) { + QDeclarativeTextLine *tl = d->lines.at(l); + line.setPosition(QPointF(line.position().x() + tl->x(), height * tl->y() / 100)); + } else { + line.setPosition(QPointF(line.position().x(), height)); + QDeclarativeTextLine *tline = new QDeclarativeTextLine(this); + d->lines << tline; + } + height += line.height(); + i += line.textLength(); + ++l; + } + d->layout.endLayout(); + emit textLayoutChanged(); +} + +int QDeclarativeTextDocument::lineCount() const +{ + Q_D(const QDeclarativeTextDocument); + return d->lines.count(); +} + +QTextLayout *QDeclarativeTextDocument::layout() +{ + Q_D(QDeclarativeTextDocument); + return &d->layout; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativetextdocument_p.h b/src/declarative/util/qdeclarativetextdocument_p.h new file mode 100644 index 0000000000..33d5f67583 --- /dev/null +++ b/src/declarative/util/qdeclarativetextdocument_p.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVETEXTDOCUMENT_H +#define QDECLARATIVETEXTDOCUMENT_H + +#include + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeTextDocumentPrivate; +class QTextLayout; +class QDeclarativeTextDocument; + +class Q_AUTOTEST_EXPORT QDeclarativeTextLine : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal x READ x WRITE setX) + Q_PROPERTY(qreal y READ y WRITE setY) + +public: + QDeclarativeTextLine(QDeclarativeTextDocument* doc); + qreal x() const; + void setX(qreal x); + qreal y() const; + void setY(qreal y); + +private: + QDeclarativeTextDocument* _doc; + qreal _x; + qreal _y; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeTextDocument : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeTextDocument) + + Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged) + +public: + QDeclarativeTextDocument(QObject *parent = 0); + ~QDeclarativeTextDocument(); + + qreal width() const; + void setWidth(qreal); + + QString text() const; + void setText(const QString&); + + QTextLayout *layout(); + + int lineCount() const; + + Q_INVOKABLE QObject *lineAt(int i) const; + + void doLayout(); + +Q_SIGNALS: + void textLayoutChanged(); + void widthChanged(); + void textChanged(); + void lineCountChanged(); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeTextDocument) + +QT_END_HEADER + +#endif // QDECLARATIVETEXTDOCUMENT_H diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 4bea2e651a..6786b1cb9f 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -63,6 +63,7 @@ #include "private/qdeclarativestyledtext_p.h" #include "private/qdeclarativesystempalette_p.h" #include "private/qdeclarativetimeline_p_p.h" +#include "private/qdeclarativetextdocument_p.h" #include "private/qdeclarativetimer_p.h" #include "private/qdeclarativetransitionmanager_p_p.h" #include "private/qdeclarativetransition_p.h" @@ -78,6 +79,7 @@ void QDeclarativeUtilModule::defineModule() { qmlRegisterUncreatableType("QtQuick",1,1,"Application", QDeclarativeApplication::tr("Application is an abstract class")); + qmlRegisterType("QtQuick",2,0,"TextLayout"); qmlRegisterType("QtQuick",1,0,"AnchorAnimation"); qmlRegisterType("QtQuick",1,0,"AnchorChanges"); qmlRegisterType("QtQuick",1,0,"Behavior"); diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index 4bd1f1bb1b..61bee8e760 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -29,7 +29,8 @@ SOURCES += \ $$PWD/qdeclarativestyledtext.cpp \ $$PWD/qdeclarativelistmodelworkeragent.cpp \ $$PWD/qdeclarativechangeset.cpp \ - $$PWD/qlistmodelinterface.cpp + $$PWD/qlistmodelinterface.cpp \ + $$PWD/qdeclarativetextdocument.cpp HEADERS += \ $$PWD/qdeclarativeapplication_p.h \ @@ -65,7 +66,8 @@ HEADERS += \ $$PWD/qdeclarativestyledtext_p.h \ $$PWD/qdeclarativelistmodelworkeragent_p.h \ $$PWD/qdeclarativechangeset_p.h \ - $$PWD/qlistmodelinterface_p.h + $$PWD/qlistmodelinterface_p.h \ + $$PWD/qdeclarativetextdocument_p.h contains(QT_CONFIG, xmlpatterns) { QT+=xmlpatterns -- cgit v1.2.3