diff options
author | Yann Bodson <yann.bodson@nokia.com> | 2011-11-28 11:26:40 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-02 11:11:53 +0100 |
commit | 8872c0716fb33e33311a78e693b61d3dd6b656c1 (patch) | |
tree | 01b970d0cc196cb99b971f9905d3a002a1a97190 /src/quick/util | |
parent | 76ed62fb836ea3e3e5236f8ed567f7ac64dd63fc (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.cpp | 98 | ||||
-rw-r--r-- | src/quick/util/qdeclarativestyledtext_p.h | 46 |
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; |