summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/doc/src/richtext.qdoc1
-rw-r--r--src/gui/image/qicon.cpp2
-rw-r--r--src/gui/image/qimage_conversions.cpp2
-rw-r--r--src/gui/image/qimage_neon.cpp4
-rw-r--r--src/gui/image/qjpeghandler.cpp155
-rw-r--r--src/gui/kernel/qguiapplication.cpp25
-rw-r--r--src/gui/kernel/qguiapplication_p.h1
-rw-r--r--src/gui/kernel/qopenglcontext_p.h3
-rw-r--r--src/gui/kernel/qshapedpixmapdndwindow.cpp6
-rw-r--r--src/gui/kernel/qshapedpixmapdndwindow_p.h1
-rw-r--r--src/gui/kernel/qwindow.cpp12
-rw-r--r--src/gui/kernel/qwindow.h13
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp36
-rw-r--r--src/gui/opengl/qopenglpaintdevice.cpp4
-rw-r--r--src/gui/opengl/qopenglpaintdevice.h2
-rw-r--r--src/gui/opengl/qopengltextureglyphcache.cpp2
-rw-r--r--src/gui/painting/qbrush.cpp3
-rw-r--r--src/gui/painting/qdrawhelper.cpp2
-rw-r--r--src/gui/painting/qpdf.cpp7
-rw-r--r--src/gui/text/qfontdatabase.cpp10
-rw-r--r--src/gui/text/qfontdatabase.h2
-rw-r--r--src/gui/text/qfontengine.cpp8
-rw-r--r--src/gui/text/qfontengine_ft.cpp75
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
-rw-r--r--src/gui/text/qfontengine_p.h2
-rw-r--r--src/gui/text/qharfbuzzng.cpp6
-rw-r--r--src/gui/text/qtextengine.cpp2
-rw-r--r--src/gui/text/qtextimagehandler.cpp67
-rw-r--r--src/gui/text/qtextlayout.cpp10
-rw-r--r--src/gui/util/qvalidator.cpp26
30 files changed, 378 insertions, 114 deletions
diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc
index 90248298d6..460018a52e 100644
--- a/src/gui/doc/src/richtext.qdoc
+++ b/src/gui/doc/src/richtext.qdoc
@@ -27,6 +27,7 @@
/*!
\group richtext-processing
+ \brief How to use Rich Text Processing APIs.
\title Rich Text Processing APIs
*/
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index f1a384af3a..d885729cbd 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1173,8 +1173,8 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
QIconEngine * const engine = platformTheme ? platformTheme->createIconEngine(name)
: new QIconLoaderEngine(name);
QIcon *cachedIcon = new QIcon(engine);
- qtIconCache()->insert(name, cachedIcon);
icon = *cachedIcon;
+ qtIconCache()->insert(name, cachedIcon);
}
// Note the qapp check is to allow lazy loading of static icons
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 6009918521..2e8fc1963d 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -2945,7 +2945,7 @@ void qInitImageConversions()
}
#endif
-#ifdef __ARM_NEON__
+#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon;
diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp
index e3930bbb4d..88d1c87ee7 100644
--- a/src/gui/image/qimage_neon.cpp
+++ b/src/gui/image/qimage_neon.cpp
@@ -35,7 +35,7 @@
#include <private/qimage_p.h>
#include <private/qsimd_p.h>
-#ifdef __ARM_NEON__
+#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
QT_BEGIN_NAMESPACE
@@ -103,4 +103,4 @@ void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::I
QT_END_NAMESPACE
-#endif // __ARM_NEON__
+#endif // defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index fbcc0608e2..ae30de634a 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -729,7 +729,7 @@ public:
};
QJpegHandlerPrivate(QJpegHandler *qq)
- : quality(75), iod_src(0), state(Ready), q(qq)
+ : quality(75), exifOrientation(1), iod_src(0), state(Ready), q(qq)
{}
~QJpegHandlerPrivate()
@@ -744,8 +744,10 @@ public:
bool readJpegHeader(QIODevice*);
bool read(QImage *image);
+ void applyExifOrientation(QImage *image);
int quality;
+ int exifOrientation;
QVariant size;
QImage::Format format;
QSize scaledSize;
@@ -763,6 +765,97 @@ public:
QJpegHandler *q;
};
+static bool readExifHeader(QDataStream &stream)
+{
+ char prefix[6];
+ if (stream.readRawData(prefix, sizeof(prefix)) != sizeof(prefix))
+ return false;
+ if (prefix[0] != 'E' || prefix[1] != 'x' || prefix[2] != 'i' || prefix[3] != 'f' || prefix[4] != 0 || prefix[5] != 0)
+ return false;
+ return true;
+}
+
+/*
+ * Returns -1 on error
+ * Returns 0 if no Exif orientation was found
+ * Returns 1 orientation is horizontal (normal)
+ * Returns 2 mirror horizontal
+ * Returns 3 rotate 180
+ * Returns 4 mirror vertical
+ * Returns 5 mirror horizontal and rotate 270 CCW
+ * Returns 6 rotate 90 CW
+ * Returns 7 mirror horizontal and rotate 90 CW
+ * Returns 8 rotate 270 CW
+ */
+static int getExifOrientation(QByteArray &exifData)
+{
+ QDataStream stream(&exifData, QIODevice::ReadOnly);
+
+ if (!readExifHeader(stream))
+ return -1;
+
+ quint16 val;
+ quint32 offset;
+
+ // read byte order marker
+ stream >> val;
+ if (val == 0x4949) // 'II' == Intel
+ stream.setByteOrder(QDataStream::LittleEndian);
+ else if (val == 0x4d4d) // 'MM' == Motorola
+ stream.setByteOrder(QDataStream::BigEndian);
+ else
+ return -1; // unknown byte order
+
+ // read size
+ stream >> val;
+ if (val != 0x2a)
+ return -1;
+
+ stream >> offset;
+ // we have already used 8 bytes of TIFF header
+ offset -= 8;
+
+ // read IFD
+ while (!stream.atEnd()) {
+ quint16 numEntries;
+
+ // skip offset bytes to get the next IFD
+ if (stream.skipRawData(offset) != (qint32)offset)
+ return -1;
+
+ stream >> numEntries;
+
+ for (;numEntries > 0; --numEntries) {
+ quint16 tag;
+ quint16 type;
+ quint32 components;
+ quint32 value;
+
+ stream >> tag >> type >> components >> value;
+
+ if (tag == 0x0112) { // Tag Exif.Image.Orientation
+ if (components !=1)
+ return -1;
+ if (type != 3) // we are expecting it to be an unsigned short
+ return -1;
+ if (value < 1 || value > 8) // check for valid range
+ return -1;
+
+ // It is possible to include the orientation multiple times.
+ // Right now the first value is returned.
+ return value;
+ }
+ }
+
+ // read offset to next IFD
+ stream >> offset;
+ if (offset == 0) // this is the last IFD
+ break;
+ }
+
+ // No Exif orientation was found
+ return 0;
+}
/*!
\internal
*/
@@ -782,6 +875,7 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
if (!setjmp(err.setjmp_buffer)) {
jpeg_save_markers(&info, JPEG_COM, 0xFFFF);
+ jpeg_save_markers(&info, JPEG_APP0+1, 0xFFFF); // Exif uses APP1 marker
(void) jpeg_read_header(&info, TRUE);
@@ -793,6 +887,8 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
format = QImage::Format_Invalid;
read_jpeg_format(format, &info);
+ QByteArray exifData;
+
for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) {
if (marker->marker == JPEG_COM) {
QString key, value;
@@ -810,9 +906,18 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
description += key + QLatin1String(": ") + value.simplified();
readTexts.append(key);
readTexts.append(value);
+ } else if (marker->marker == JPEG_APP0+1) {
+ exifData.append((const char*)marker->data, marker->data_length);
}
}
+ if (exifData.size()) {
+ // Exif data present
+ int orientation = getExifOrientation(exifData);
+ if (orientation > 0)
+ exifOrientation = orientation;
+ }
+
state = ReadHeader;
return true;
}
@@ -826,6 +931,48 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
return true;
}
+void QJpegHandlerPrivate::applyExifOrientation(QImage *image)
+{
+ // This is not an optimized implementation, but easiest to maintain
+ QTransform transform;
+
+ switch (exifOrientation) {
+ case 1: // normal
+ break;
+ case 2: // mirror horizontal
+ *image = image->mirrored(true, false);
+ break;
+ case 3: // rotate 180
+ transform.rotate(180);
+ *image = image->transformed(transform);
+ break;
+ case 4: // mirror vertical
+ *image = image->mirrored(false, true);
+ break;
+ case 5: // mirror horizontal and rotate 270 CCW
+ *image = image->mirrored(true, false);
+ transform.rotate(270);
+ *image = image->transformed(transform);
+ break;
+ case 6: // rotate 90 CW
+ transform.rotate(90);
+ *image = image->transformed(transform);
+ break;
+ case 7: // mirror horizontal and rotate 90 CW
+ *image = image->mirrored(true, false);
+ transform.rotate(90);
+ *image = image->transformed(transform);
+ break;
+ case 8: // rotate 270 CW
+ transform.rotate(-90);
+ *image = image->transformed(transform);
+ break;
+ default:
+ qWarning("This should never happen");
+ }
+ exifOrientation = 1;
+}
+
bool QJpegHandlerPrivate::read(QImage *image)
{
if(state == Ready)
@@ -837,6 +984,7 @@ bool QJpegHandlerPrivate::read(QImage *image)
if (success) {
for (int i = 0; i < readTexts.size()-1; i+=2)
image->setText(readTexts.at(i), readTexts.at(i+1));
+ applyExifOrientation(image);
state = Ready;
return true;
@@ -856,12 +1004,13 @@ extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uc
QJpegHandler::QJpegHandler()
: d(new QJpegHandlerPrivate(this))
{
-#if defined(__ARM_NEON__)
+#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
// from qimage_neon.cpp
if (qCpuHasFeature(NEON))
rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon;
-#endif // __ARM_NEON__
+#endif
+
#if defined(QT_COMPILER_SUPPORTS_SSSE3)
// from qimage_ssse3.cpp
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index c5e7fb523d..e421f79e91 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -163,7 +163,6 @@ QWindow *QGuiApplicationPrivate::focus_window = 0;
static QBasicMutex applicationFontMutex;
QFont *QGuiApplicationPrivate::app_font = 0;
bool QGuiApplicationPrivate::obey_desktop_settings = true;
-bool QGuiApplicationPrivate::noGrab = false;
static qreal fontSmoothingGamma = 1.7;
@@ -1191,20 +1190,10 @@ void QGuiApplicationPrivate::eventDispatcherReady()
platform_integration->initialize();
}
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
-// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc.
-static bool runningUnderDebugger()
-{
- const QFileInfo parentProcExe(QStringLiteral("/proc/") + QString::number(getppid()) + QStringLiteral("/exe"));
- return parentProcExe.isSymLink() && parentProcExe.symLinkTarget().endsWith(QLatin1String("/gdb"));
-}
-#endif
-
void QGuiApplicationPrivate::init()
{
QCoreApplicationPrivate::is_app_running = false; // Starting up.
- bool doGrabUnderDebugger = false;
bool loadTestability = false;
QList<QByteArray> pluginList;
// Get command line params
@@ -1239,10 +1228,6 @@ void QGuiApplicationPrivate::init()
QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2));
}
#endif
- } else if (arg == "-nograb") {
- QGuiApplicationPrivate::noGrab = true;
- } else if (arg == "-dograb") {
- doGrabUnderDebugger = true;
#ifndef QT_NO_SESSIONMANAGER
} else if (arg == "-session" && i < argc-1) {
++i;
@@ -1268,16 +1253,6 @@ void QGuiApplicationPrivate::init()
argc = j;
}
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
- if (!doGrabUnderDebugger && !QGuiApplicationPrivate::noGrab && runningUnderDebugger()) {
- QGuiApplicationPrivate::noGrab = true;
- qDebug("Qt: gdb: -nograb added to command-line options.\n"
- "\t Use the -dograb option to enforce grabbing.");
- }
-#else
- Q_UNUSED(doGrabUnderDebugger)
-#endif
-
// Load environment exported generic plugins
foreach (const QByteArray &plugin, qgetenv("QT_QPA_GENERIC_PLUGINS").split(','))
pluginList << plugin;
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 8988bd461d..eed3d5c10e 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -221,7 +221,6 @@ public:
QStyleHints *styleHints;
static bool obey_desktop_settings;
- static bool noGrab;
QInputMethod *inputMethod;
QString firstWindowTitle;
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index d5a3126176..975553e7cd 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -203,6 +203,7 @@ public:
, workaround_brokenTexSubImage(false)
, workaround_missingPrecisionQualifiers(false)
, active_engine(0)
+ , qgl_current_fbo_invalid(false)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
@@ -237,6 +238,8 @@ public:
QPaintEngineEx *active_engine;
+ bool qgl_current_fbo_invalid;
+
QVariant nativeHandle;
static QOpenGLContext *setCurrentContext(QOpenGLContext *context);
diff --git a/src/gui/kernel/qshapedpixmapdndwindow.cpp b/src/gui/kernel/qshapedpixmapdndwindow.cpp
index 55a8aae33c..af60b36647 100644
--- a/src/gui/kernel/qshapedpixmapdndwindow.cpp
+++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp
@@ -52,6 +52,12 @@ QShapedPixmapWindow::QShapedPixmapWindow()
m_backingStore = new QBackingStore(this);
}
+QShapedPixmapWindow::~QShapedPixmapWindow()
+{
+ delete m_backingStore;
+ m_backingStore = 0;
+}
+
void QShapedPixmapWindow::render()
{
QRect rect(QPoint(), geometry().size());
diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h
index b59305f055..04198c83cb 100644
--- a/src/gui/kernel/qshapedpixmapdndwindow_p.h
+++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h
@@ -56,6 +56,7 @@ class QShapedPixmapWindow : public QWindow
Q_OBJECT
public:
QShapedPixmapWindow();
+ ~QShapedPixmapWindow();
void render();
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index a3b7f38c80..fa99390af0 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1127,6 +1127,10 @@ Qt::WindowState QWindow::windowState() const
This is a hint to the window manager that this window is a dialog or pop-up
on behalf of the given window.
+ In order to cause the window to be centered above its transient parent by
+ default, depending on the window manager, it may also be necessary to call
+ setFlags() with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
+
\sa transientParent(), parent()
*/
void QWindow::setTransientParent(QWindow *parent)
@@ -1644,8 +1648,6 @@ QPlatformSurface *QWindow::surfaceHandle() const
bool QWindow::setKeyboardGrabEnabled(bool grab)
{
Q_D(QWindow);
- if (grab && QGuiApplicationPrivate::noGrab)
- return false;
if (d->platformWindow)
return d->platformWindow->setKeyboardGrabEnabled(grab);
return false;
@@ -1663,8 +1665,6 @@ bool QWindow::setKeyboardGrabEnabled(bool grab)
bool QWindow::setMouseGrabEnabled(bool grab)
{
Q_D(QWindow);
- if (grab && QGuiApplicationPrivate::noGrab)
- return false;
if (d->platformWindow)
return d->platformWindow->setMouseGrabEnabled(grab);
return false;
@@ -2352,7 +2352,7 @@ QWindow *QWindow::fromWinId(WId id)
/*!
Causes an alert to be shown for \a msec miliseconds. If \a msec is \c 0 (the
default), then the alert is shown indefinitely until the window becomes
- active again.
+ active again. This function has no effect on an active window.
In alert state, the window indicates that it demands attention, for example by
flashing or bouncing the taskbar entry.
@@ -2363,7 +2363,7 @@ QWindow *QWindow::fromWinId(WId id)
void QWindow::alert(int msec)
{
Q_D(QWindow);
- if (!d->platformWindow || d->platformWindow->isAlertState())
+ if (!d->platformWindow || d->platformWindow->isAlertState() || isActive())
return;
d->platformWindow->setAlertState(true);
if (d->platformWindow->isAlertState() && msec)
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 6d9793ae3f..2230ed8801 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -358,6 +358,19 @@ private:
friend Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window);
};
+#ifndef Q_QDOC
+template <> inline QWindow *qobject_cast<QWindow*>(QObject *o)
+{
+ if (!o || !o->isWindowType()) return 0;
+ return static_cast<QWindow*>(o);
+}
+template <> inline const QWindow *qobject_cast<const QWindow*>(const QObject *o)
+{
+ if (!o || !o->isWindowType()) return 0;
+ return static_cast<const QWindow*>(o);
+}
+#endif // !Q_QDOC
+
QT_END_NAMESPACE
#endif // QWINDOW_H
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index b185e332e6..124d9d53f6 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -469,6 +469,8 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
funcs.glGenFramebuffers(1, &fbo);
funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
+
GLuint color_buffer = 0;
QT_CHECK_GLERROR();
@@ -997,7 +999,11 @@ bool QOpenGLFramebufferObject::bind()
if (current->shareGroup() != d->fbo_guard->group())
qWarning("QOpenGLFramebufferObject::bind() called from incompatible context");
#endif
+
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
+
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
+
if (d->texture_guard || d->format.samples() != 0)
d->valid = d->checkFramebufferStatus(current);
else
@@ -1029,9 +1035,12 @@ bool QOpenGLFramebufferObject::release()
qWarning("QOpenGLFramebufferObject::release() called from incompatible context");
#endif
- if (current)
+ if (current) {
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject());
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
+ }
+
return true;
}
@@ -1194,9 +1203,23 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value
of QOpenGLPaintDevice::paintFlipped().
- Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to
- a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported. Since 5.4 an
- A2BGR30 image is returned if the internal format is RGB10_A2.
+ The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used
+ only when internalTextureFormat() is set to \c GL_RGB.
+
+ If the rendering in the framebuffer was not done with premultiplied alpha in mind,
+ create a wrapper QImage with a non-premultiplied format. This is necessary before
+ performing operations like QImage::save() because otherwise the image data would get
+ unpremultiplied, even though it was not premultiplied in the first place. To create
+ such a wrapper without performing a copy of the pixel data, do the following:
+
+ \code
+ QImage fboImage(fbo.toImage());
+ QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
+ \endcode
+
+ Since Qt 5.2 the function will fall back to premultiplied RGBA8888 or RGBx8888 when
+ reading to (A)RGB32 is not supported. Since 5.4 an A2BGR30 image is returned if the
+ internal format is RGB10_A2.
For multisampled framebuffer objects the samples are resolved using the
\c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents
@@ -1272,8 +1295,10 @@ bool QOpenGLFramebufferObject::bindDefault()
{
QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
- if (ctx)
+ if (ctx) {
ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
+ }
#ifdef QT_DEBUG
else
qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
@@ -1342,6 +1367,7 @@ void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachmen
qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context");
#endif
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
d->initAttachments(current, attachment);
}
diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp
index e908fd8e91..a08d26f708 100644
--- a/src/gui/opengl/qopenglpaintdevice.cpp
+++ b/src/gui/opengl/qopenglpaintdevice.cpp
@@ -138,8 +138,8 @@ QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height)
/*!
\internal
*/
-QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd)
- : d_ptr(dd)
+QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd)
+ : d_ptr(&dd)
{
}
diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h
index dda3bfe43f..10cee842ab 100644
--- a/src/gui/opengl/qopenglpaintdevice.h
+++ b/src/gui/opengl/qopenglpaintdevice.h
@@ -53,7 +53,6 @@ public:
QOpenGLPaintDevice();
explicit QOpenGLPaintDevice(const QSize &size);
QOpenGLPaintDevice(int width, int height);
- QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd);
virtual ~QOpenGLPaintDevice();
int devType() const { return QInternal::OpenGL; }
@@ -76,6 +75,7 @@ public:
virtual void ensureActiveTarget();
protected:
+ QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd);
int metric(QPaintDevice::PaintDeviceMetric metric) const;
Q_DISABLE_COPY(QOpenGLPaintDevice)
diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp
index 0f70a01014..cd268cd685 100644
--- a/src/gui/opengl/qopengltextureglyphcache.cpp
+++ b/src/gui/opengl/qopengltextureglyphcache.cpp
@@ -82,10 +82,12 @@ QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache()
clear();
}
+#if !defined(QT_OPENGL_ES_2)
static inline bool isCoreProfile()
{
return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile;
}
+#endif
void QOpenGLTextureGlyphCache::createTextureData(int width, int height)
{
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index d120175108..d136f3a903 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -708,6 +708,9 @@ void QBrush::setStyle(Qt::BrushStyle style)
void QBrush::setColor(const QColor &c)
{
+ if (d->color == c)
+ return;
+
detach(d->style);
d->color = c;
}
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 4c6dc958b2..a991b89f48 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6928,7 +6928,7 @@ void qInitDrawhelperAsm()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
#endif
-#ifdef Q_PROCESSOR_MIPS_32
+#if defined(Q_PROCESSOR_MIPS_32) && defined(QT_COMPILER_SUPPORTS_MIPS_DSP)
qt_memfill32 = qt_memfill32_asm_mips_dsp;
#endif // Q_PROCESSOR_MIPS_32
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 30421ea2fa..8cf45863b8 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -2506,7 +2506,8 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
QFontEngine::FaceId face_id = fe->faceId();
bool noEmbed = false;
- if (face_id.filename.isEmpty()
+ if (!embedFonts
+ || face_id.filename.isEmpty()
|| fe->fsType & 0x200 /* bitmap embedding only */
|| fe->fsType == 2 /* no embedding allowed */) {
*currentPage << "Q\n";
@@ -2529,10 +2530,6 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
qreal size = ti.fontEngine->fontDef.pixelSize;
-#if defined(Q_OS_WIN)
- size = (ti.fontEngine->ascent() + ti.fontEngine->descent()).toReal();
-#endif
-
QVarLengthArray<glyph_t> glyphs;
QVarLengthArray<QFixedPoint> positions;
QTransform m = QTransform::fromTranslate(p.x(), p.y());
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index decf2fe121..8fe6aff79f 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -620,7 +620,7 @@ struct QtFontDesc
static int match(int script, const QFontDef &request,
const QString &family_name, const QString &foundry_name, int force_encoding_id,
- QtFontDesc *desc, const QList<int> &blacklisted, bool fallback);
+ QtFontDesc *desc, const QList<int> &blacklisted);
static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef, bool multi)
{
@@ -1110,7 +1110,7 @@ static bool matchFamilyName(const QString &familyName, QtFontFamily *f)
*/
static int match(int script, const QFontDef &request,
const QString &family_name, const QString &foundry_name, int force_encoding_id,
- QtFontDesc *desc, const QList<int> &blacklistedFamilies, bool fallback = false)
+ QtFontDesc *desc, const QList<int> &blacklistedFamilies)
{
Q_UNUSED(force_encoding_id);
int result = -1;
@@ -1163,7 +1163,7 @@ static int match(int script, const QFontDef &request,
load(test.family->name, script);
// Check if family is supported in the script we want
- if (!fallback && script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported))
+ if (script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported))
continue;
// as we know the script is supported, we can be sure
@@ -2490,7 +2490,7 @@ bool QFontDatabase::supportsThreadedFontRendering()
*/
QFontEngine *
QFontDatabase::findFont(int script, const QFontPrivate *fp,
- const QFontDef &request, bool multi, bool fallback)
+ const QFontDef &request, bool multi)
{
QMutexLocker locker(fontDatabaseMutex());
@@ -2518,7 +2518,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
QtFontDesc desc;
QList<int> blackListed;
- int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed, fallback);
+ int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed);
if (index >= 0) {
engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
if (!engine)
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index f1c479d0bb..d7d8745f12 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -152,7 +152,7 @@ private:
static void createDatabase();
static void parseFontName(const QString &name, QString &foundry, QString &family);
static QString resolveFontFamilyAlias(const QString &family);
- static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false, bool fallback = false);
+ static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false);
static void load(const QFontPrivate *d, int script);
friend struct QFontDef;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index fe0f9fa943..4c6fc7c1a6 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -373,8 +373,6 @@ bool QFontEngine::supportsScript(QChar::Script script) const
if (!ret && script_tag_2 != HB_OT_TAG_DEFAULT_SCRIPT)
ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, HB_OT_TAG_DEFAULT_SCRIPT, &script_index);
}
-
- hb_face_destroy(face);
}
return ret;
}
@@ -2028,7 +2026,7 @@ void QFontEngineMultiBasicImpl::loadEngine(int at)
request.family = fallbackFamilies.at(at-1);
engines[at] = QFontDatabase::findFont(script,
/*fontprivate = */0,
- request, /*multi = */false, true);
+ request, /*multi = */false);
Q_ASSERT(engines[at]);
engines[at]->ref.ref();
engines[at]->fontDef = request;
@@ -2098,4 +2096,8 @@ QFontEngine* QFontEngineMultiBasicImpl::createMultiFontEngine(QFontEngine *fe, i
return engine;
}
+QTestFontEngine::QTestFontEngine(int size)
+ : QFontEngineBox(TestFontEngine, size)
+{}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index b44eb43be5..4c5bab77d6 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1459,10 +1459,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
bool QFontEngineFT::supportsTransformation(const QTransform &transform) const
{
- // The freetype engine falls back to QFontEngine for tranformed glyphs,
- // which uses fast-tranform and produces very ugly results, so we claim
- // to support just translations.
- return transform.type() <= QTransform::TxTranslate;
+ return transform.type() <= QTransform::TxRotate;
}
void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
@@ -1943,17 +1940,75 @@ void QFontEngineFT::unlockAlphaMapForGlyph()
currentlyLockedAlphaMap = QImage();
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format)
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
+ QFixed subPixelPosition,
+ GlyphFormat format,
+ const QTransform &t)
{
- return defaultGlyphSet.outline_drawing ? 0 :
- loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, g, subPixelPosition, format);
+ FT_Face face = 0;
+ QGlyphSet *glyphSet = 0;
+ FT_Matrix ftMatrix = QTransformToFTMatrix(t);
+ if (cacheEnabled) {
+ if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
+ for (int i = 0; i < transformedGlyphSets.count(); ++i) {
+ const QGlyphSet &g = transformedGlyphSets.at(i);
+ if (g.transformationMatrix.xx == ftMatrix.xx
+ && g.transformationMatrix.xy == ftMatrix.xy
+ && g.transformationMatrix.yx == ftMatrix.yx
+ && g.transformationMatrix.yy == ftMatrix.yy) {
+
+ // found a match, move it to the front
+ transformedGlyphSets.move(i, 0);
+ glyphSet = &transformedGlyphSets[0];
+ break;
+ }
+ }
+
+ if (!glyphSet) {
+ // don't cache more than 10 transformations
+ if (transformedGlyphSets.count() >= 10) {
+ transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
+ } else {
+ transformedGlyphSets.prepend(QGlyphSet());
+ }
+ glyphSet = &transformedGlyphSets[0];
+ glyphSet->clear();
+ glyphSet->transformationMatrix = ftMatrix;
+ }
+ } else {
+ glyphSet = &defaultGlyphSet;
+ }
+ Q_ASSERT(glyphSet != 0);
+ }
+
+ if (glyphSet != 0 && glyphSet->outline_drawing)
+ return 0;
+
+ Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
+ if (!glyph || glyph->format != format) {
+ face = lockFace();
+ FT_Matrix m = this->matrix;
+ FT_Matrix_Multiply(&ftMatrix, &m);
+ freetype->matrix = m;
+ glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false);
+ }
+
+ if (face)
+ unlockFace();
+
+ return glyph;
}
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
{
+ return alphaMapForGlyph(g, subPixelPosition, QTransform());
+}
+
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
+{
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@@ -1982,12 +2037,12 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
- if (t.type() > QTransform::TxTranslate)
+ if (t.type() > QTransform::TxRotate)
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index a73c281f1d..1894d25d70 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -233,6 +233,7 @@ private:
virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const;
virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
virtual QImage alphaMapForGlyph(glyph_t, QFixed);
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
QFixed subPixelPosition,
@@ -265,7 +266,7 @@ private:
inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
{ return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); }
Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
- Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format);
+ Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t);
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 50b1bb9e9d..9364b82bed 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -463,7 +463,7 @@ private:
class QTestFontEngine : public QFontEngineBox
{
public:
- inline QTestFontEngine(int size) : QFontEngineBox(TestFontEngine, size) {}
+ QTestFontEngine(int size);
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index eb7bca1974..16c45e642b 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -632,7 +632,7 @@ hb_face_t *hb_qt_face_get_for_engine(QFontEngine *fe)
fe->face_destroy_func = _hb_qt_face_release;
}
- return hb_face_reference((hb_face_t *)fe->face_);
+ return (hb_face_t *)fe->face_;
}
@@ -645,8 +645,6 @@ _hb_qt_font_create(QFontEngine *fe)
hb_font_t *font = hb_font_create(face);
- hb_face_destroy(face); // ref-ed in hb_qt_face_get_for_engine()
-
if (Q_UNLIKELY(hb_font_is_immutable(font))) {
hb_font_destroy(font);
return NULL;
@@ -684,7 +682,7 @@ hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe)
fe->font_destroy_func = _hb_qt_font_release;
}
- return hb_font_reference((hb_font_t *)fe->font_);
+ return (hb_font_t *)fe->font_;
}
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 9fe1fd26e9..d156124b98 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1168,8 +1168,6 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
};
const int num_features = 1;
shapedOk = hb_shape_full(hb_font, buffer, features, num_features, 0);
-
- hb_font_destroy(hb_font);
}
if (!shapedOk) {
hb_buffer_destroy(buffer);
diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp
index f6525448de..37c18e3624 100644
--- a/src/gui/text/qtextimagehandler.cpp
+++ b/src/gui/text/qtextimagehandler.cpp
@@ -44,31 +44,49 @@
QT_BEGIN_NAMESPACE
-static QString resolve2xFile(const QString &fileName, qreal targetDevicePixelRatio)
+static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePixelRatio)
{
+ // We might use the fileName for loading if url loading fails
+ // try to make sure it is a valid file path.
+ // Also, QFile{Info}::exists works only on filepaths (not urls)
+
+ if (url->isValid()) {
+ if (url->scheme() == QLatin1Literal("qrc")) {
+ fileName = fileName.right(fileName.length() - 3);
+ }
+ else if (url->scheme() == QLatin1Literal("file")) {
+ fileName = url->toLocalFile();
+ }
+ }
+
if (targetDevicePixelRatio <= 1.0)
return fileName;
- int dotIndex = fileName.lastIndexOf(QLatin1Char('.'));
+ // try to find a 2x version
+
+ const int dotIndex = fileName.lastIndexOf(QLatin1Char('.'));
if (dotIndex != -1) {
QString at2xfileName = fileName;
at2xfileName.insert(dotIndex, QStringLiteral("@2x"));
- if (QFile::exists(at2xfileName))
- return at2xfileName;
+ if (QFile::exists(at2xfileName)) {
+ fileName = at2xfileName;
+ *url = QUrl(fileName);
+ }
}
+
return fileName;
}
-static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format)
+
+static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
{
QPixmap pm;
QString name = format.name();
- if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
+ if (name.startsWith(QLatin1String(":/"))) // auto-detect resources and convert them to url
name.prepend(QLatin1String("qrc"));
- QPaintDevice *pdev = doc->documentLayout()->paintDevice();
- name = resolve2xFile(name, pdev ? pdev->devicePixelRatio() : qApp->devicePixelRatio());
QUrl url = QUrl(name);
+ name = resolveFileName(name, &url, devicePixelRatio);
const QVariant data = doc->resource(QTextDocument::ImageResource, url);
if (data.type() == QVariant::Pixmap || data.type() == QVariant::Image) {
pm = qvariant_cast<QPixmap>(data);
@@ -77,19 +95,18 @@ static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format)
}
if (pm.isNull()) {
- QString context;
#if 0
+ QString context;
// ### Qt5
QTextBrowser *browser = qobject_cast<QTextBrowser *>(doc->parent());
if (browser)
context = browser->source().toString();
#endif
+ // try direct loading
QImage img;
- if (img.isNull()) { // try direct loading
- name = format.name(); // remove qrc:/ prefix again
- if (name.isEmpty() || !img.load(name))
- return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
- }
+ if (name.isEmpty() || !img.load(name))
+ return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
+
pm = QPixmap::fromImage(img);
doc->addResource(QTextDocument::ImageResource, url, pm);
}
@@ -142,16 +159,15 @@ static QSize getPixmapSize(QTextDocument *doc, const QTextImageFormat &format)
return size;
}
-static QImage getImage(QTextDocument *doc, const QTextImageFormat &format)
+static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
{
QImage image;
QString name = format.name();
if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
name.prepend(QLatin1String("qrc"));
- QPaintDevice *pdev = doc->documentLayout()->paintDevice();
- name = resolve2xFile(name, pdev ? pdev->devicePixelRatio() : qApp->devicePixelRatio());
QUrl url = QUrl(name);
+ name = resolveFileName(name, &url, devicePixelRatio);
const QVariant data = doc->resource(QTextDocument::ImageResource, url);
if (data.type() == QVariant::Image) {
image = qvariant_cast<QImage>(data);
@@ -160,19 +176,18 @@ static QImage getImage(QTextDocument *doc, const QTextImageFormat &format)
}
if (image.isNull()) {
- QString context;
-
#if 0
+ QString context;
// ### Qt5
QTextBrowser *browser = qobject_cast<QTextBrowser *>(doc->parent());
if (browser)
context = browser->source().toString();
#endif
- if (image.isNull()) { // try direct loading
- name = format.name(); // remove qrc:/ prefix again
- if (name.isEmpty() || !image.load(name))
- return QImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
- }
+ // try direct loading
+
+ if (name.isEmpty() || !image.load(name))
+ return QImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
+
doc->addResource(QTextDocument::ImageResource, url, image);
}
@@ -241,10 +256,10 @@ void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocumen
const QTextImageFormat imageFormat = format.toImageFormat();
if (QCoreApplication::instance()->thread() != QThread::currentThread()) {
- const QImage image = getImage(doc, imageFormat);
+ const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatio());
p->drawImage(rect, image, image.rect());
} else {
- const QPixmap pixmap = getPixmap(doc, imageFormat);
+ const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatio());
p->drawPixmap(rect, pixmap, pixmap.rect());
}
}
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index adc5663299..1ac50d3e5c 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -2256,8 +2256,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
logClusters,
iterator.itemStart,
iterator.itemLength));
- for (int i = 0; i < subLayout.numGlyphs; ++i)
- pos.rx() += subLayout.advances[i].toReal();
+ for (int i = 0; i < subLayout.numGlyphs; ++i) {
+ QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6);
+ pos.rx() += (subLayout.advances[i] + justification).toReal();
+ }
if (rtl)
end = start;
@@ -2559,6 +2561,10 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
}
else
itm = eng->findItem(pos);
+ if (itm < 0) {
+ *cursorPos = 0;
+ return x.toReal();
+ }
eng->shapeLine(line);
const QScriptItem *si = &eng->layoutData->items[itm];
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index 1b5a10f733..f879847935 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -316,7 +316,12 @@ void QValidator::fixup(QString &) const
QIntValidator uses its locale() to interpret the number. For example,
in Arabic locales, QIntValidator will accept Arabic digits.
- \sa QDoubleValidator, QRegExpValidator, {Line Edits Example}
+ \note The QLocale::NumberOptions set on the locale() also affect the
+ way the number is interpreted. For example, since QLocale::RejectGroupSeparator
+ is not set by default, the validator will accept group separators. It is thus
+ recommended to use QLocale::toInt() to obtain the numeric value.
+
+ \sa QDoubleValidator, QRegExpValidator, QLocale::toInt(), {Line Edits Example}
*/
/*!
@@ -393,7 +398,8 @@ static qlonglong pow10(int exp)
QValidator::State QIntValidator::validate(QString & input, int&) const
{
QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) {
+ if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff,
+ -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) {
return Invalid;
}
@@ -432,7 +438,8 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
void QIntValidator::fixup(QString &input) const
{
QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) {
+ if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff,
+ -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) {
return;
}
bool ok, overflow;
@@ -548,7 +555,12 @@ public:
in the German locale, "1,234" will be accepted as the fractional number
1.234. In Arabic locales, QDoubleValidator will accept Arabic digits.
- \sa QIntValidator, QRegExpValidator, {Line Edits Example}
+ \note The QLocale::NumberOptions set on the locale() also affect the
+ way the number is interpreted. For example, since QLocale::RejectGroupSeparator
+ is not set by default, the validator will accept group separators. It is thus
+ recommended to use QLocale::toDouble() to obtain the numeric value.
+
+ \sa QIntValidator, QRegExpValidator, QLocale::toDouble(), {Line Edits Example}
*/
/*!
@@ -648,8 +660,10 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
{
Q_Q(const QDoubleValidator);
QByteArray buff;
- if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec))
+ if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec,
+ locale.numberOptions() & QLocale::RejectGroupSeparator)) {
return QValidator::Invalid;
+ }
if (buff.isEmpty())
return QValidator::Intermediate;
@@ -1003,7 +1017,7 @@ QValidator::State QRegularExpressionValidator::validate(QString &input, int &pos
const QRegularExpressionMatch m = d->usedRe.match(input, 0, QRegularExpression::PartialPreferCompleteMatch);
if (m.hasMatch()) {
return Acceptable;
- } else if (m.hasPartialMatch()) {
+ } else if (input.isEmpty() || m.hasPartialMatch()) {
return Intermediate;
} else {
pos = input.size();