Get started with patching up the Qt GUI docs
[profile/ivi/qtbase.git] / src / gui / text / qtextimagehandler.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include "qtextimagehandler_p.h"
44
45 #include <qcoreapplication.h>
46 #include <qtextformat.h>
47 #include <qpainter.h>
48 #include <qdebug.h>
49 #include <private/qtextengine_p.h>
50 #include <qpalette.h>
51 #include <qthread.h>
52
53 QT_BEGIN_NAMESPACE
54
55 static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format)
56 {
57     QPixmap pm;
58
59     QString name = format.name();
60     if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
61         name.prepend(QLatin1String("qrc"));
62     QUrl url = QUrl(name);
63     const QVariant data = doc->resource(QTextDocument::ImageResource, url);
64     if (data.type() == QVariant::Pixmap || data.type() == QVariant::Image) {
65         pm = qvariant_cast<QPixmap>(data);
66     } else if (data.type() == QVariant::ByteArray) {
67         pm.loadFromData(data.toByteArray());
68     }
69
70     if (pm.isNull()) {
71         QString context;
72 #if 0
73         // ### Qt5
74         QTextBrowser *browser = qobject_cast<QTextBrowser *>(doc->parent());
75         if (browser)
76             context = browser->source().toString();
77 #endif
78         QImage img;
79         if (img.isNull()) { // try direct loading
80             name = format.name(); // remove qrc:/ prefix again
81             if (name.isEmpty() || !img.load(name))
82                 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
83         }
84         pm = QPixmap::fromImage(img);
85         doc->addResource(QTextDocument::ImageResource, url, pm);
86     }
87
88     return pm;
89 }
90
91 static QSize getPixmapSize(QTextDocument *doc, const QTextImageFormat &format)
92 {
93     QPixmap pm;
94
95     const bool hasWidth = format.hasProperty(QTextFormat::ImageWidth);
96     const int width = qRound(format.width());
97     const bool hasHeight = format.hasProperty(QTextFormat::ImageHeight);
98     const int height = qRound(format.height());
99
100     QSize size(width, height);
101     if (!hasWidth || !hasHeight) {
102         pm = getPixmap(doc, format);
103         if (!hasWidth) {
104             if (!hasHeight)
105                 size.setWidth(pm.width());
106             else
107                 size.setWidth(qRound(height * (pm.width() / (qreal) pm.height())));
108         }
109         if (!hasHeight) {
110             if (!hasWidth)
111                 size.setHeight(pm.height());
112             else
113                 size.setHeight(qRound(width * (pm.height() / (qreal) pm.width())));
114         }
115     }
116
117     qreal scale = 1.0;
118     QPaintDevice *pdev = doc->documentLayout()->paintDevice();
119     if (pdev) {
120         if (pm.isNull())
121             pm = getPixmap(doc, format);
122         if (!pm.isNull())
123             scale = qreal(pdev->logicalDpiY()) / qreal(qt_defaultDpi());
124     }
125     size *= scale;
126
127     return size;
128 }
129
130 static QImage getImage(QTextDocument *doc, const QTextImageFormat &format)
131 {
132     QImage image;
133
134     QString name = format.name();
135     if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
136         name.prepend(QLatin1String("qrc"));
137     QUrl url = QUrl(name);
138     const QVariant data = doc->resource(QTextDocument::ImageResource, url);
139     if (data.type() == QVariant::Image) {
140         image = qvariant_cast<QImage>(data);
141     } else if (data.type() == QVariant::ByteArray) {
142         image.loadFromData(data.toByteArray());
143     }
144
145     if (image.isNull()) {
146         QString context;
147
148 #if 0
149         // ### Qt5
150         QTextBrowser *browser = qobject_cast<QTextBrowser *>(doc->parent());
151         if (browser)
152             context = browser->source().toString();
153 #endif
154         if (image.isNull()) { // try direct loading
155             name = format.name(); // remove qrc:/ prefix again
156             if (name.isEmpty() || !image.load(name))
157                 return QImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
158         }
159         doc->addResource(QTextDocument::ImageResource, url, image);
160     }
161
162     return image;
163 }
164
165 static QSize getImageSize(QTextDocument *doc, const QTextImageFormat &format)
166 {
167     QImage image;
168
169     const bool hasWidth = format.hasProperty(QTextFormat::ImageWidth);
170     const int width = qRound(format.width());
171     const bool hasHeight = format.hasProperty(QTextFormat::ImageHeight);
172     const int height = qRound(format.height());
173
174     QSize size(width, height);
175     if (!hasWidth || !hasHeight) {
176         image = getImage(doc, format);
177         if (!hasWidth)
178             size.setWidth(image.width());
179         if (!hasHeight)
180             size.setHeight(image.height());
181     }
182
183     qreal scale = 1.0;
184     QPaintDevice *pdev = doc->documentLayout()->paintDevice();
185     if (pdev) {
186         if (image.isNull())
187             image = getImage(doc, format);
188         if (!image.isNull())
189             scale = qreal(pdev->logicalDpiY()) / qreal(qt_defaultDpi());
190     }
191     size *= scale;
192
193     return size;
194 }
195
196 QTextImageHandler::QTextImageHandler(QObject *parent)
197     : QObject(parent)
198 {
199 }
200
201 QSizeF QTextImageHandler::intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format)
202 {
203     Q_UNUSED(posInDocument)
204     const QTextImageFormat imageFormat = format.toImageFormat();
205
206     if (QCoreApplication::instance()->thread() != QThread::currentThread())
207         return getImageSize(doc, imageFormat);
208     return getPixmapSize(doc, imageFormat);
209 }
210
211 QImage QTextImageHandler::image(QTextDocument *doc, const QTextImageFormat &imageFormat)
212 {
213     Q_ASSERT(doc != 0);
214
215     return getImage(doc, imageFormat);
216 }
217
218 void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format)
219 {
220     Q_UNUSED(posInDocument)
221         const QTextImageFormat imageFormat = format.toImageFormat();
222
223     if (QCoreApplication::instance()->thread() != QThread::currentThread()) {
224         const QImage image = getImage(doc, imageFormat);
225         p->drawImage(rect, image, image.rect());
226     } else {
227         const QPixmap pixmap = getPixmap(doc, imageFormat);
228         p->drawPixmap(rect, pixmap, pixmap.rect());
229     }
230 }
231
232 QT_END_NAMESPACE