aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/util
diff options
context:
space:
mode:
authorYann Bodson <yann.bodson@nokia.com>2011-11-28 11:26:40 +1000
committerQt by Nokia <qt-info@nokia.com>2012-02-02 11:11:53 +0100
commit8872c0716fb33e33311a78e693b61d3dd6b656c1 (patch)
tree01b970d0cc196cb99b971f9905d3a002a1a97190 /src/quick/util
parent76ed62fb836ea3e3e5236f8ed567f7ac64dd63fc (diff)
Support inline images with <img> tag in StyledText
Task-number: QTBUG-21793 Change-Id: Ie7b9f293c6c9a949c1899152c38b61251b0069d3 Reviewed-by: Yann Bodson <yann.bodson@nokia.com>
Diffstat (limited to 'src/quick/util')
-rw-r--r--src/quick/util/qdeclarativestyledtext.cpp98
-rw-r--r--src/quick/util/qdeclarativestyledtext_p.h46
2 files changed, 130 insertions, 14 deletions
diff --git a/src/quick/util/qdeclarativestyledtext.cpp b/src/quick/util/qdeclarativestyledtext.cpp
index d34601d09f..39ea6b1a22 100644
--- a/src/quick/util/qdeclarativestyledtext.cpp
+++ b/src/quick/util/qdeclarativestyledtext.cpp
@@ -46,6 +46,7 @@
#include <QDebug>
#include <qmath.h>
#include "qdeclarativestyledtext_p.h"
+#include <QDeclarativeContext>
/*
QDeclarativeStyledText supports few tags:
@@ -61,6 +62,7 @@
<a href=""> - anchor
<ol type="">, <ul type=""> and <li> - ordered and unordered lists
<pre></pre> - preformated
+ <img src=""> - images
The opening and closing tags must be correctly nested.
*/
@@ -79,9 +81,12 @@ public:
ListFormat format;
};
- QDeclarativeStyledTextPrivate(const QString &t, QTextLayout &l)
- : text(t), layout(l), baseFont(layout.font()), hasNewLine(false)
- , preFormat(false), prependSpace(false), hasSpace(true)
+ QDeclarativeStyledTextPrivate(const QString &t, QTextLayout &l,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags,
+ QDeclarativeContext *context,
+ bool preloadImages)
+ : text(t), layout(l), imgTags(&imgTags), baseFont(layout.font()), hasNewLine(false), nbImages(0), updateImagePositions(false)
+ , preFormat(false), prependSpace(false), hasSpace(true), preloadImages(preloadImages), context(context)
{
}
@@ -94,6 +99,7 @@ public:
bool parseOrderedListAttributes(const QChar *&ch, const QString &textIn);
bool parseUnorderedListAttributes(const QChar *&ch, const QString &textIn);
bool parseAnchorAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
+ void parseImageAttributes(const QChar *&ch, const QString &textIn, QString &textOut);
QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn);
QStringRef parseValue(const QChar *&ch, const QString &textIn);
@@ -108,12 +114,17 @@ public:
QString text;
QTextLayout &layout;
+ QList<QDeclarativeStyledTextImgTag*> *imgTags;
QFont baseFont;
QStack<List> listStack;
bool hasNewLine;
+ int nbImages;
+ bool updateImagePositions;
bool preFormat;
bool prependSpace;
bool hasSpace;
+ bool preloadImages;
+ QDeclarativeContext *context;
static const QChar lessThan;
static const QChar greaterThan;
@@ -143,8 +154,10 @@ const QChar QDeclarativeStyledTextPrivate::square(0x25a1);
const QChar QDeclarativeStyledTextPrivate::lineFeed(QLatin1Char('\n'));
const QChar QDeclarativeStyledTextPrivate::space(QLatin1Char(' '));
-QDeclarativeStyledText::QDeclarativeStyledText(const QString &string, QTextLayout &layout)
-: d(new QDeclarativeStyledTextPrivate(string, layout))
+QDeclarativeStyledText::QDeclarativeStyledText(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags, QDeclarativeContext *context,
+ bool preloadImages)
+ : d(new QDeclarativeStyledTextPrivate(string, layout, imgTags, context, preloadImages))
{
}
@@ -153,11 +166,13 @@ QDeclarativeStyledText::~QDeclarativeStyledText()
delete d;
}
-void QDeclarativeStyledText::parse(const QString &string, QTextLayout &layout)
+void QDeclarativeStyledText::parse(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags, QDeclarativeContext *context,
+ bool preloadImages)
{
if (string.isEmpty())
return;
- QDeclarativeStyledText styledText(string, layout);
+ QDeclarativeStyledText styledText(string, layout, imgTags, context, preloadImages);
styledText.d->parse();
}
@@ -169,6 +184,8 @@ void QDeclarativeStyledTextPrivate::parse()
QString drawText;
drawText.reserve(text.count());
+ updateImagePositions = !imgTags->isEmpty();
+
int textStart = 0;
int textLength = 0;
int rangeStart = 0;
@@ -401,6 +418,10 @@ bool QDeclarativeStyledTextPrivate::parseTag(const QChar *&ch, const QString &te
if (tag == QLatin1String("a")) {
return parseAnchorAttributes(ch, textIn, format);
}
+ if (tag == QLatin1String("img")) {
+ parseImageAttributes(ch, textIn, textOut);
+ return false;
+ }
if (*ch == greaterThan || ch->isNull())
continue;
} else if (*ch != slash) {
@@ -606,6 +627,69 @@ bool QDeclarativeStyledTextPrivate::parseAnchorAttributes(const QChar *&ch, cons
return valid;
}
+void QDeclarativeStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QString &textIn, QString &textOut)
+{
+ qreal imgWidth = 0.0;
+
+ if (!updateImagePositions) {
+ QDeclarativeStyledTextImgTag *image = new QDeclarativeStyledTextImgTag;
+ image->position = textOut.length() + 1;
+
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ if (attr.first == QLatin1String("src")) {
+ image->url = QUrl(attr.second.toString());
+ } else if (attr.first == QLatin1String("width")) {
+ image->size.setWidth(attr.second.toString().toInt());
+ } else if (attr.first == QLatin1String("height")) {
+ image->size.setHeight(attr.second.toString().toInt());
+ } else if (attr.first == QLatin1String("align")) {
+ if (attr.second.toString() == QLatin1String("top")) {
+ image->align = QDeclarativeStyledTextImgTag::Top;
+ } else if (attr.second.toString() == QLatin1String("middle")) {
+ image->align = QDeclarativeStyledTextImgTag::Middle;
+ }
+ }
+ } while (!ch->isNull() && !attr.first.isEmpty());
+
+ if (preloadImages && !image->size.isValid()) {
+ // if we don't know its size but the image is a local image,
+ // we load it in the pixmap cache and save its implicit size
+ // to avoid a relayout later on.
+ QUrl url = context->resolvedUrl(image->url);
+ if (url.isLocalFile()) {
+ QDeclarativePixmap *pix = new QDeclarativePixmap(context->engine(), url, image->size);
+ if (pix && pix->isReady()) {
+ image->size = pix->implicitSize();
+ image->pix = pix;
+ }
+ }
+ }
+
+ imgWidth = image->size.width();
+ imgTags->append(image);
+
+ } else {
+ // if we already have a list of img tags for this text
+ // we only want to update the positions of these tags.
+ QDeclarativeStyledTextImgTag *image = imgTags->value(nbImages);
+ image->position = textOut.length() + 1;
+ imgWidth = image->size.width();
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ } while (!ch->isNull() && !attr.first.isEmpty());
+ nbImages++;
+ }
+
+ QFontMetricsF fm(layout.font());
+ QString padding(qFloor(imgWidth / fm.width(QChar::Nbsp)), QChar::Nbsp);
+ textOut += QChar(' ');
+ textOut += padding;
+ textOut += QChar(' ');
+}
+
QPair<QStringRef,QStringRef> QDeclarativeStyledTextPrivate::parseAttribute(const QChar *&ch, const QString &textIn)
{
skipSpace(ch);
diff --git a/src/quick/util/qdeclarativestyledtext_p.h b/src/quick/util/qdeclarativestyledtext_p.h
index f3e9fef457..1c9086e7d1 100644
--- a/src/quick/util/qdeclarativestyledtext_p.h
+++ b/src/quick/util/qdeclarativestyledtext_p.h
@@ -42,23 +42,55 @@
#ifndef QDECLARATIVESTYLEDTEXT_H
#define QDECLARATIVESTYLEDTEXT_H
-#include <QSizeF>
+#include <QSize>
+#include <QPointF>
+#include <QList>
+#include <QUrl>
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
QT_BEGIN_NAMESPACE
-class QPainter;
-class QPointF;
-class QString;
+class QDeclarativeStyledTextImgTag;
class QDeclarativeStyledTextPrivate;
-class QTextLayout;
+class QString;
+class QDeclarativeContext;
+
+class Q_AUTOTEST_EXPORT QDeclarativeStyledTextImgTag
+{
+public:
+ QDeclarativeStyledTextImgTag()
+ : position(0), align(QDeclarativeStyledTextImgTag::Bottom), pix(0)
+ { }
+
+ ~QDeclarativeStyledTextImgTag() { delete pix; }
+
+ enum Align {
+ Bottom,
+ Middle,
+ Top
+ };
+
+ QUrl url;
+ QPointF pos;
+ QSize size;
+ int position;
+ Align align;
+ QDeclarativePixmap *pix;
+};
class Q_AUTOTEST_EXPORT QDeclarativeStyledText
{
public:
- static void parse(const QString &string, QTextLayout &layout);
+ static void parse(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags,
+ QDeclarativeContext *context,
+ bool preloadImages);
private:
- QDeclarativeStyledText(const QString &string, QTextLayout &layout);
+ QDeclarativeStyledText(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags,
+ QDeclarativeContext *context,
+ bool preloadImages);
~QDeclarativeStyledText();
QDeclarativeStyledTextPrivate *d;