summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-04-04 23:01:17 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2019-04-04 23:01:17 +0000
commited485243b594a730cebee4d76847e0f556d369f4 (patch)
tree545dd98a3138782df786f742cac02bc63113eaf6 /src/gui
parent8d7c97d428cdf89c3419a4e13b62a9849feefce9 (diff)
parenteb606d85b3f1548445cfd1fee43f882da88fb6e7 (diff)
Merge "Merge remote-tracking branch 'origin/5.13' into dev" into refs/staging/dev
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/image/qiconloader.cpp5
-rw-r--r--src/gui/image/qimage.cpp47
-rw-r--r--src/gui/image/qimage.h4
-rw-r--r--src/gui/image/qimage_neon.cpp66
-rw-r--r--src/gui/image/qimage_p.h6
-rw-r--r--src/gui/image/qpixmap.cpp15
-rw-r--r--src/gui/image/qplatformpixmap.cpp1
-rw-r--r--src/gui/kernel/qplatformgraphicsbuffer.h2
-rw-r--r--src/gui/kernel/qplatformintegration.cpp81
-rw-r--r--src/gui/kernel/qplatformintegration.h6
-rw-r--r--src/gui/kernel/qplatformscreen.cpp3
-rw-r--r--src/gui/kernel/qplatformwindow.cpp7
-rw-r--r--src/gui/kernel/qscreen.cpp20
-rw-r--r--src/gui/kernel/qscreen.h1
-rw-r--r--src/gui/kernel/qwindow.cpp14
-rw-r--r--src/gui/kernel/qwindow_p.h10
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp61
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h4
-rw-r--r--src/gui/opengl/qopengltexture.cpp29
-rw-r--r--src/gui/painting/painting.pri6
-rw-r--r--src/gui/painting/qbrush.cpp12
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp13
-rw-r--r--src/gui/painting/qoutlinemapper.cpp5
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp5
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp7
-rw-r--r--src/gui/text/qtextcursor.cpp23
-rw-r--r--src/gui/text/qtextdocument_p.cpp18
-rw-r--r--src/gui/text/qtextdocument_p.h2
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp81
-rw-r--r--src/gui/text/qtextengine.cpp2
30 files changed, 328 insertions, 228 deletions
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index a9adde8c8d..1d0c93f26f 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -629,7 +629,10 @@ void QIconLoaderEngine::ensureLoaded()
void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect,
QIcon::Mode mode, QIcon::State state)
{
- QSize pixmapSize = rect.size();
+ const qreal dpr = !qApp->testAttribute(Qt::AA_UseHighDpiPixmaps) ?
+ qreal(1.0) : painter->device()->devicePixelRatioF();
+
+ QSize pixmapSize = rect.size() * dpr;
painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
}
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 18125460c7..8b2db6d346 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -127,7 +127,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
int height = size.height();
int depth = qt_depthForFormat(format);
auto params = calculateImageParameters(width, height, depth);
- if (params.bytesPerLine < 0)
+ if (!params.isValid())
return nullptr;
QScopedPointer<QImageData> d(new QImageData);
@@ -786,7 +786,7 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm
const int depth = qt_depthForFormat(format);
auto params = calculateImageParameters(width, height, depth);
- if (params.totalSize < 0)
+ if (!params.isValid())
return nullptr;
if (bpl > 0) {
@@ -1094,16 +1094,32 @@ void QImage::detach()
}
-static void copyMetadata(QImageData *dst, const QImageData *src)
+static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
{
- // Doesn't copy colortable and alpha_clut, or offset.
dst->dpmx = src->dpmx;
dst->dpmy = src->dpmy;
dst->devicePixelRatio = src->devicePixelRatio;
+}
+
+static void copyMetadata(QImageData *dst, const QImageData *src)
+{
+ // Doesn't copy colortable and alpha_clut, or offset.
+ copyPhysicalMetadata(dst, src);
dst->text = src->text;
dst->colorSpace = src->colorSpace;
}
+static void copyMetadata(QImage *dst, const QImage &src)
+{
+ dst->setDotsPerMeterX(src.dotsPerMeterX());
+ dst->setDotsPerMeterY(src.dotsPerMeterY());
+ dst->setDevicePixelRatio(src.devicePixelRatio());
+ const auto textKeys = src.textKeys();
+ for (const auto &key: textKeys)
+ dst->setText(key, src.text(key));
+
+}
+
/*!
\fn QImage QImage::copy(int x, int y, int width, int height) const
\overload
@@ -1492,10 +1508,17 @@ qsizetype QImage::sizeInBytes() const
\sa scanLine()
*/
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+qsizetype QImage::bytesPerLine() const
+{
+ return d ? d->bytes_per_line : 0;
+}
+#else
int QImage::bytesPerLine() const
{
return d ? d->bytes_per_line : 0;
}
+#endif
/*!
@@ -2948,8 +2971,10 @@ QImage QImage::createAlphaMask(Qt::ImageConversionFlags flags) const
}
QImage mask(d->width, d->height, Format_MonoLSB);
- if (!mask.isNull())
+ if (!mask.isNull()) {
dither_to_Mono(mask.d, d, flags, true);
+ copyPhysicalMetadata(mask.d, d);
+ }
return mask;
}
@@ -3067,6 +3092,7 @@ QImage QImage::createHeuristicMask(bool clipTight) const
#undef PIX
+ copyPhysicalMetadata(m.d, d);
return m;
}
#endif //QT_NO_IMAGE_HEURISTIC_MASK
@@ -3110,6 +3136,8 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
}
if (mode == Qt::MaskOutColor)
maskImage.invertPixels();
+
+ copyPhysicalMetadata(maskImage.d, d);
return maskImage;
}
@@ -4681,8 +4709,7 @@ QImage QImage::smoothScaled(int w, int h) const {
static QImage rotated90(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
- out.setDotsPerMeterX(image.dotsPerMeterY());
- out.setDotsPerMeterY(image.dotsPerMeterX());
+ copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
int w = image.width();
@@ -4710,8 +4737,7 @@ static QImage rotated180(const QImage &image)
return image.mirrored(true, true);
QImage out(image.width(), image.height(), image.format());
- out.setDotsPerMeterX(image.dotsPerMeterY());
- out.setDotsPerMeterY(image.dotsPerMeterX());
+ copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
int w = image.width();
@@ -4723,8 +4749,7 @@ static QImage rotated180(const QImage &image)
static QImage rotated270(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
- out.setDotsPerMeterX(image.dotsPerMeterY());
- out.setDotsPerMeterY(image.dotsPerMeterX());
+ copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
int w = image.width();
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index b09e69c839..af7e6988cb 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -228,7 +228,11 @@ public:
uchar *scanLine(int);
const uchar *scanLine(int) const;
const uchar *constScanLine(int) const;
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ qsizetype bytesPerLine() const;
+#else
int bytesPerLine() const;
+#endif
bool valid(int x, int y) const;
bool valid(const QPoint &pt) const;
diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp
index 57a24edeca..9dbcb11db5 100644
--- a/src/gui/image/qimage_neon.cpp
+++ b/src/gui/image/qimage_neon.cpp
@@ -52,65 +52,41 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons
const quint32 *const end = dst + len;
- // align dst on 64 bits
- const int offsetToAlignOn8Bytes = (reinterpret_cast<quintptr>(dst) >> 2) & 0x1;
- for (int i = 0; i < offsetToAlignOn8Bytes; ++i) {
+ // align dst on 128 bits
+ const int offsetToAlignOn16Bytes = (reinterpret_cast<quintptr>(dst) >> 2) & 0x3;
+ for (int i = 0; i < offsetToAlignOn16Bytes; ++i) {
*dst++ = qRgb(src[0], src[1], src[2]);
src += 3;
}
- if ((len - offsetToAlignOn8Bytes) >= 8) {
- const quint32 *const simdEnd = end - 7;
-#if !defined(Q_PROCESSOR_ARM_64)
- register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff);
- do {
+ if ((len - offsetToAlignOn16Bytes) >= 16) {
+ const quint32 *const simdEnd = end - 15;
+ uint8x16x4_t dstVector;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- asm volatile (
- "vld3.8 { d4, d5, d6 }, [%[SRC]] !\n\t"
- "vst4.8 { d3, d4, d5, d6 }, [%[DST],:64] !\n\t"
- : [DST]"+r" (dst), [SRC]"+r" (src)
- : "w"(fullVector)
- : "memory", "d4", "d5", "d6"
- );
+ dstVector.val[0] = vdupq_n_u8(0xff);
#else
- asm volatile (
- "vld3.8 { d0, d1, d2 }, [%[SRC]] !\n\t"
- "vswp d0, d2\n\t"
- "vst4.8 { d0, d1, d2, d3 }, [%[DST],:64] !\n\t"
- : [DST]"+r" (dst), [SRC]"+r" (src)
- : "w"(fullVector)
- : "memory", "d0", "d1", "d2"
- );
+ dstVector.val[3] = vdupq_n_u8(0xff);
#endif
- } while (dst < simdEnd);
-#else
- register uint8x8_t fullVector asm ("v3") = vdup_n_u8(0xff);
do {
+ uint8x16x3_t srcVector = vld3q_u8(src);
+ src += 3 * 16;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- asm volatile (
- "ld3 { v4.8b, v5.8b, v6.8b }, [%[SRC]], #24 \n\t"
- "st4 { v3.8b, v4.8b, v5.8b, v6.8b }, [%[DST]], #32 \n\t"
- : [DST]"+r" (dst), [SRC]"+r" (src)
- : "w"(fullVector)
- : "memory", "v4", "v5", "v6"
- );
+ dstVector.val[1] = srcVector.val[0];
+ dstVector.val[2] = srcVector.val[1];
+ dstVector.val[3] = srcVector.val[2];
#else
- asm volatile (
- "ld3 { v0.8b, v1.8b, v2.8b }, [%[SRC]], #24 \n\t"
- "mov v4.8b, v2.8b\n\t"
- "mov v2.8b, v0.8b\n\t"
- "mov v0.8b, v4.8b\n\t"
- "st4 { v0.8b, v1.8b, v2.8b, v3.8b }, [%[DST]], #32 \n\t"
- : [DST]"+r" (dst), [SRC]"+r" (src)
- : "w"(fullVector)
- : "memory", "v0", "v1", "v2", "v4"
- );
+ dstVector.val[0] = srcVector.val[2];
+ dstVector.val[1] = srcVector.val[1];
+ dstVector.val[2] = srcVector.val[0];
#endif
+ vst4q_u8(reinterpret_cast<uint8_t*>(dst), dstVector);
+ dst += 16;
} while (dst < simdEnd);
-#endif
}
- while (dst != end) {
+ int i = 0;
+ int length = end - dst;
+ SIMD_EPILOGUE(i, length, 15) {
*dst++ = qRgb(src[0], src[1], src[2]);
src += 3;
}
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 1e0578a0f4..9da6acd0a7 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -113,6 +113,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data
struct ImageSizeParameters {
qsizetype bytesPerLine;
qsizetype totalSize;
+ bool isValid() const { return bytesPerLine > 0 && totalSize > 0; }
};
static ImageSizeParameters calculateImageParameters(qsizetype width, qsizetype height, qsizetype depth);
};
@@ -139,6 +140,11 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp
qsizetype dummy;
if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy))
return invalid; // why is this here?
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ // Disallow images where width * depth calculations might overflow
+ if (width > (INT_MAX - 31) / depth)
+ return invalid;
+#endif
return { bytes_per_line, total_size };
}
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 2ef1d09422..5b4d218603 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1552,6 +1552,11 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
if (image.isNull())
return QPixmap();
+ if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
+ qWarning("QPixmap::fromImage: QPixmap cannot be created without a QGuiApplication");
+ return QPixmap();
+ }
+
QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImage(image, flags);
return QPixmap(data.take());
@@ -1574,6 +1579,11 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags)
if (image.isNull())
return QPixmap();
+ if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
+ qWarning("QPixmap::fromImageInPlace: QPixmap cannot be created without a QGuiApplication");
+ return QPixmap();
+ }
+
QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageInPlace(image, flags);
return QPixmap(data.take());
@@ -1593,6 +1603,11 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags)
*/
QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags)
{
+ if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
+ qWarning("QPixmap::fromImageReader: QPixmap cannot be created without a QGuiApplication");
+ return QPixmap();
+ }
+
QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageReader(imageReader, flags);
return QPixmap(data.take());
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index 2209c3de4d..a2e01147c4 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -178,6 +178,7 @@ QBitmap QPlatformPixmap::mask() const
if (mask.isNull()) // allocation failed
return QBitmap();
+ mask.setDevicePixelRatio(devicePixelRatio());
mask.setColorCount(2);
mask.setColor(0, QColor(Qt::color0).rgba());
mask.setColor(1, QColor(Qt::color1).rgba());
diff --git a/src/gui/kernel/qplatformgraphicsbuffer.h b/src/gui/kernel/qplatformgraphicsbuffer.h
index 65c24bebc9..9004116ea4 100644
--- a/src/gui/kernel/qplatformgraphicsbuffer.h
+++ b/src/gui/kernel/qplatformgraphicsbuffer.h
@@ -71,12 +71,14 @@ public:
TextureAccess = 0x04,
HWCompositor = 0x08
};
+ Q_ENUM(AccessType);
Q_DECLARE_FLAGS(AccessTypes, AccessType);
enum Origin {
OriginBottomLeft,
OriginTopLeft
};
+ Q_ENUM(Origin);
~QPlatformGraphicsBuffer();
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index 199ef0de07..490cfc6178 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -462,87 +462,6 @@ QList<int> QPlatformIntegration::possibleKeys(const QKeyEvent *) const
return QList<int>();
}
-/*!
- Should be called by the implementation whenever a new screen is added.
-
- The first screen added will be the primary screen, used for default-created
- windows, GL contexts, and other resources unless otherwise specified.
-
- This adds the screen to QGuiApplication::screens(), and emits the
- QGuiApplication::screenAdded() signal.
-
- The screen should be deleted by calling QPlatformIntegration::destroyScreen().
-*/
-void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
-{
- QScreen *screen = new QScreen(ps);
-
- if (isPrimary) {
- QGuiApplicationPrivate::screen_list.prepend(screen);
- } else {
- QGuiApplicationPrivate::screen_list.append(screen);
- }
-
- QGuiApplicationPrivate::resetCachedDevicePixelRatio();
-
- emit qGuiApp->screenAdded(screen);
-
- if (isPrimary)
- emit qGuiApp->primaryScreenChanged(screen);
-}
-
-/*!
- Just removes the screen, call destroyScreen instead.
-
- \sa destroyScreen()
-*/
-
-void QPlatformIntegration::removeScreen(QScreen *screen)
-{
- const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list.at(0) == screen);
- QGuiApplicationPrivate::screen_list.removeOne(screen);
-
- QGuiApplicationPrivate::resetCachedDevicePixelRatio();
-
- if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty())
- emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list.at(0));
-}
-
-/*!
- Should be called by the implementation whenever a screen is removed.
-
- This removes the screen from QGuiApplication::screens(), and deletes it.
-
- Failing to call this and manually deleting the QPlatformScreen instead may
- lead to a crash due to a pure virtual call.
-*/
-void QPlatformIntegration::destroyScreen(QPlatformScreen *screen)
-{
- QScreen *qScreen = screen->screen();
- removeScreen(qScreen);
- delete qScreen;
- delete screen;
-}
-
-/*!
- Should be called whenever the primary screen changes.
-
- When the screen specified as primary changes, this method will notify
- QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal.
- */
-
-void QPlatformIntegration::setPrimaryScreen(QPlatformScreen *newPrimary)
-{
- QScreen* newPrimaryScreen = newPrimary->screen();
- int idx = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
- Q_ASSERT(idx >= 0);
- if (idx == 0)
- return;
-
- QGuiApplicationPrivate::screen_list.swapItemsAt(0, idx);
- emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
-}
-
QStringList QPlatformIntegration::themeNames() const
{
return QStringList();
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 8ece390420..b764bd2617 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -192,8 +192,6 @@ public:
#endif
virtual void setApplicationIcon(const QIcon &icon) const;
- void removeScreen(QScreen *screen);
-
virtual void beep() const;
#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
@@ -202,10 +200,6 @@ public:
protected:
QPlatformIntegration() = default;
-
- void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
- void destroyScreen(QPlatformScreen *screen);
- void setPrimaryScreen(QPlatformScreen *newPrimary);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index b7b312e89e..9c5876550a 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -61,8 +61,7 @@ QPlatformScreen::~QPlatformScreen()
{
Q_D(QPlatformScreen);
if (d->screen) {
- qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead.");
- QGuiApplicationPrivate::platformIntegration()->removeScreen(d->screen);
+ qWarning("Manually deleting a QPlatformScreen. Call QWindowSystemInterface::handleScreenRemoved instead.");
delete d->screen;
}
}
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index d6f90c9254..562289a8c9 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -708,10 +708,11 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w,
const QScreen *screen = effectiveScreen(w);
if (!screen)
return initialGeometry;
+ const auto *wp = qt_window_private(const_cast<QWindow*>(w));
QRect rect(QHighDpi::fromNativePixels(initialGeometry, w));
- rect.setSize(fixInitialSize(rect.size(), w, defaultWidth, defaultHeight));
- if (qt_window_private(const_cast<QWindow*>(w))->positionAutomatic
- && w->type() != Qt::Popup) {
+ if (wp->resizeAutomatic)
+ rect.setSize(fixInitialSize(rect.size(), w, defaultWidth, defaultHeight));
+ if (wp->positionAutomatic && w->type() != Qt::Popup) {
const QRect availableGeometry = screen->availableGeometry();
// Center unless the geometry ( + unknown window frame) is too large for the screen).
if (rect.height() < (availableGeometry.height() * 8) / 9
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index f208eb02be..952023dd1b 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -106,9 +106,18 @@ void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen)
*/
QScreen::~QScreen()
{
- if (!qApp)
+ // Remove screen
+ const bool wasPrimary = QGuiApplication::primaryScreen() == this;
+ QGuiApplicationPrivate::screen_list.removeOne(this);
+ QGuiApplicationPrivate::resetCachedDevicePixelRatio();
+
+ if (!qGuiApp)
return;
+ QScreen *newPrimaryScreen = QGuiApplication::primaryScreen();
+ if (wasPrimary && newPrimaryScreen)
+ emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
+
// Allow clients to manage windows that are affected by the screen going
// away, before we fall back to moving them to the primary screen.
emit qApp->screenRemoved(this);
@@ -116,11 +125,8 @@ QScreen::~QScreen()
if (QGuiApplication::closingDown())
return;
- QScreen *primaryScreen = QGuiApplication::primaryScreen();
- if (this == primaryScreen)
- return;
-
- bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
+ bool movingFromVirtualSibling = newPrimaryScreen
+ && newPrimaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
const auto allWindows = QGuiApplication::allWindows();
@@ -129,7 +135,7 @@ QScreen::~QScreen()
continue;
const bool wasVisible = window->isVisible();
- window->setScreen(primaryScreen);
+ window->setScreen(newPrimaryScreen);
// Re-show window if moved from a virtual sibling screen. Otherwise
// leave it up to the application developer to show the window.
diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h
index 8c9b16e08e..14392d3036 100644
--- a/src/gui/kernel/qscreen.h
+++ b/src/gui/kernel/qscreen.h
@@ -169,6 +169,7 @@ private:
friend class QPlatformIntegration;
friend class QPlatformScreen;
friend class QHighDpiScaling;
+ friend class QWindowSystemInterface;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 6e0c2de240..19a5d39ad5 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1922,9 +1922,6 @@ void QWindowPrivate::destroy()
resizeEventPending = true;
receivedExpose = false;
exposed = false;
-
- if (wasVisible)
- maybeQuitOnLastWindowClosed();
}
/*!
@@ -2313,8 +2310,17 @@ bool QWindow::event(QEvent *ev)
#endif
case QEvent::Close:
- if (ev->isAccepted())
+ if (ev->isAccepted()) {
+ Q_D(QWindow);
+ bool wasVisible = isVisible();
destroy();
+ if (wasVisible) {
+ // FIXME: This check for visibility is a workaround for both QWidgetWindow
+ // and QWindow having logic to emit lastWindowClosed, and possibly quit the
+ // application. We should find a better way to handle this.
+ d->maybeQuitOnLastWindowClosed();
+ }
+ }
break;
case QEvent::Expose:
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 1098321135..cc1cc24525 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -90,6 +90,7 @@ public:
, receivedExpose(false)
, positionPolicy(WindowFrameExclusive)
, positionAutomatic(true)
+ , resizeAutomatic(true)
, contentOrientation(Qt::PrimaryOrientation)
, opacity(qreal(1.0))
, minimumSize(0, 0)
@@ -156,11 +157,15 @@ public:
virtual void processSafeAreaMarginsChanged() {};
bool isPopup() const { return (windowFlags & Qt::WindowType_Mask) == Qt::Popup; }
+ void setAutomaticPositionAndResizeEnabled(bool a)
+ { positionAutomatic = resizeAutomatic = a; }
static QWindowPrivate *get(QWindow *window) { return window->d_func(); }
static Qt::WindowState effectiveState(Qt::WindowStates);
+ virtual bool allowClickThrough(const QPoint &) const { return true; }
+
QWindow::SurfaceType surfaceType;
Qt::WindowFlags windowFlags;
QWindow *parentWindow;
@@ -179,6 +184,11 @@ public:
bool receivedExpose;
PositionPolicy positionPolicy;
bool positionAutomatic;
+ // resizeAutomatic suppresses resizing by QPlatformWindow::initialGeometry().
+ // It also indicates that width/height=0 is acceptable (for example, for
+ // the QRollEffect widget) and is thus not cleared in setGeometry().
+ // An alternative approach might be using -1,-1 as a default size.
+ bool resizeAutomatic;
Qt::ScreenOrientation contentOrientation;
qreal opacity;
QRegion mask;
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 8e6e3ce618..6f3edb10b4 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -780,6 +780,67 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *window, ulong
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
+/*!
+ Should be called by the implementation whenever a new screen is added.
+
+ The first screen added will be the primary screen, used for default-created
+ windows, GL contexts, and other resources unless otherwise specified.
+
+ This adds the screen to QGuiApplication::screens(), and emits the
+ QGuiApplication::screenAdded() signal.
+
+ The screen should be deleted by calling QWindowSystemInterface::handleScreenRemoved().
+*/
+void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrimary)
+{
+ QScreen *screen = new QScreen(ps);
+
+ if (isPrimary)
+ QGuiApplicationPrivate::screen_list.prepend(screen);
+ else
+ QGuiApplicationPrivate::screen_list.append(screen);
+
+ QGuiApplicationPrivate::resetCachedDevicePixelRatio();
+
+ emit qGuiApp->screenAdded(screen);
+
+ if (isPrimary)
+ emit qGuiApp->primaryScreenChanged(screen);
+}
+
+/*!
+ Should be called by the implementation whenever a screen is removed.
+
+ This removes the screen from QGuiApplication::screens(), and deletes it.
+
+ Failing to call this and manually deleting the QPlatformScreen instead may
+ lead to a crash due to a pure virtual call.
+*/
+void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen)
+{
+ // Important to keep this order since the QSceen doesn't own the platform screen
+ delete platformScreen->screen();
+ delete platformScreen;
+}
+
+/*!
+ Should be called whenever the primary screen changes.
+
+ When the screen specified as primary changes, this method will notify
+ QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal.
+ */
+void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrimary)
+{
+ QScreen *newPrimaryScreen = newPrimary->screen();
+ int indexOfScreen = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
+ Q_ASSERT(indexOfScreen >= 0);
+ if (indexOfScreen == 0)
+ return;
+
+ QGuiApplicationPrivate::screen_list.swapItemsAt(0, indexOfScreen);
+ emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
+}
+
void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation orientation)
{
QWindowSystemInterfacePrivate::ScreenOrientationEvent *e =
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index 03b3bd16f0..fd70eda9ff 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -237,6 +237,10 @@ public:
#endif
// Changes to the screen
+ static void handleScreenAdded(QPlatformScreen *screen, bool isPrimary = false);
+ static void handleScreenRemoved(QPlatformScreen *screen);
+ static void handlePrimaryScreenChanged(QPlatformScreen *newPrimary);
+
static void handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation newOrientation);
static void handleScreenGeometryChange(QScreen *screen, const QRect &newGeometry, const QRect &newAvailableGeometry);
static void handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal newDpiX, qreal newDpiY);
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 1e4d627e2a..61a6202017 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -3530,6 +3530,35 @@ void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
This overload is to be used to update a part of the texture. Parameters \a
xOffset, \a yOffset, \a zOffset specify the texel offsets within the
texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image. The mip map level the sub image we want to
+ update is specified with \a mipLevel.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, 0, 1,
+ QOpenGLTexture::CubeMapPositiveX, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
of the sub image. The mip map level and layerof the sub image we want to
update are specified with \a mipLevel and \a layer.
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 0e2dfed9ab..972cf387ff 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -143,9 +143,11 @@ ARCH_HASWELL_SOURCES += painting/qdrawhelper_avx2.cpp
NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h
-NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
!uikit:!win32:contains(QT_ARCH, "arm"): CONFIG += no_clang_integrated_as
-!uikit:!win32:!contains(QT_ARCH, "arm64"): DEFINES += ENABLE_PIXMAN_DRAWHELPERS
+!uikit:!win32:!integrity:!contains(QT_ARCH, "arm64") {
+ NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
+ DEFINES += ENABLE_PIXMAN_DRAWHELPERS
+}
MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp
MIPS_DSP_HEADERS += painting/qdrawhelper_mips_dsp_p.h painting/qt_mips_asm_dsp_p.h
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index abfa8d41bb..ed575abf54 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -545,9 +545,11 @@ QBrush::QBrush(const QBrush &other)
*/
QBrush::QBrush(const QGradient &gradient)
{
- Q_ASSERT_X(gradient.type() != QGradient::NoGradient, "QBrush::QBrush",
- "QGradient should not be used directly, use the linear, radial\n"
- "or conical gradients instead");
+ if (Q_UNLIKELY(gradient.type() == QGradient::NoGradient)) {
+ d.reset(nullBrushInstance());
+ d->ref.ref();
+ return;
+ }
const Qt::BrushStyle enum_table[] = {
Qt::LinearGradientPattern,
@@ -1376,8 +1378,10 @@ QGradient::QGradient(Preset preset)
}();
const QJsonValue presetData = jsonPresets[preset - 1];
- if (!presetData.isObject())
+ if (!presetData.isObject()) {
+ qWarning("QGradient: Undefined preset %i", preset);
return;
+ }
m_type = LinearGradient;
setCoordinateMode(ObjectMode);
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 3fcbcfd053..8196a87b24 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -50,7 +50,18 @@ QT_BEGIN_NAMESPACE
void qt_memfill32(quint32 *dest, quint32 value, qsizetype count)
{
const int epilogueSize = count % 16;
-#if !defined(Q_PROCESSOR_ARM_64)
+#if defined(Q_CC_GHS) || defined(Q_CC_MSVC)
+ // inline assembler free version:
+ if (count >= 16) {
+ quint32 *const neonEnd = dest + count - epilogueSize;
+ const uint32x4_t valueVector1 = vdupq_n_u32(value);
+ const uint32x4x4_t valueVector4 = { valueVector1, valueVector1, valueVector1, valueVector1 };
+ do {
+ vst4q_u32(dest, valueVector4);
+ dest += 16;
+ } while (dest != neonEnd);
+ }
+#elif !defined(Q_PROCESSOR_ARM_64)
if (count >= 16) {
quint32 *const neonEnd = dest + count - epilogueSize;
register uint32x4_t valueVector1 asm ("q0") = vdupq_n_u32(value);
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index b2d02182c3..2074f98069 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -42,6 +42,7 @@
#include "qbezier_p.h"
#include "qmath.h"
#include "qpainterpath_p.h"
+#include "qscopedvaluerollback.h"
#include <stdlib.h>
@@ -354,7 +355,7 @@ void QOutlineMapper::clipElements(const QPointF *elements,
// instead of going through convenience functionallity, but since
// this part of code hardly every used, it shouldn't matter.
- m_in_clip_elements = true;
+ QScopedValueRollback<bool> in_clip_elements(m_in_clip_elements, true);
QPainterPath path;
@@ -397,8 +398,6 @@ void QOutlineMapper::clipElements(const QPointF *elements,
convertPath(clippedPath);
m_transform = oldTransform;
}
-
- m_in_clip_elements = false;
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index afb4613ba5..c71d82546a 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -446,6 +446,11 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
d_ptr->blitter->setRedBlueSwizzle(false);
}
+ // There is no way to tell if the OpenGL-rendered content is premultiplied or not.
+ // For compatibility, assume that it is not, and use normal alpha blend always.
+ if (d_ptr->premultiplied)
+ funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
+
// Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 102a776ed3..cf584f6980 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -45,6 +45,7 @@
#include <private/qtextdocument_p.h>
#include <qtextlayout.h>
#include <qpointer.h>
+#include <qscopedvaluerollback.h>
#include <qtextobject.h>
#include <qtextcursor.h>
#include <qdebug.h>
@@ -68,14 +69,14 @@ public:
void reformatBlocks(int from, int charsRemoved, int charsAdded);
void reformatBlock(const QTextBlock &block);
- inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
- inReformatBlocks = true;
+ inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation)
+ {
+ QScopedValueRollback<bool> bg(inReformatBlocks, true);
cursor.beginEditBlock();
int from = cursor.position();
cursor.movePosition(operation);
reformatBlocks(from, 0, cursor.position() - from);
cursor.endEditBlock();
- inReformatBlocks = false;
}
inline void _q_delayedRehighlight() {
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index 7719a2e6da..c88497840f 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -1145,6 +1145,15 @@ bool QTextCursor::isNull() const
\a pos using a \c MoveMode specified by \a m. The cursor is positioned
between characters.
+ \note The "characters" in this case refer to the string of QChar
+ objects, i.e. 16-bit Unicode characters, and \a pos is considered
+ an index into this string. This does not necessarily correspond to
+ individual graphemes in the writing system, as a single grapheme may
+ be represented by multiple Unicode characters, such as in the case
+ of surrogate pairs, linguistic ligatures or diacritics. For a more
+ generic approach to navigating the document, use movePosition(),
+ which will respect the actual grapheme boundaries in the text.
+
\sa position(), movePosition(), anchor()
*/
void QTextCursor::setPosition(int pos, MoveMode m)
@@ -1176,6 +1185,13 @@ void QTextCursor::setPosition(int pos, MoveMode m)
Returns the absolute position of the cursor within the document.
The cursor is positioned between characters.
+ \note The "characters" in this case refer to the string of QChar
+ objects, i.e. 16-bit Unicode characters, and the position is considered
+ an index into this string. This does not necessarily correspond to
+ individual graphemes in the writing system, as a single grapheme may
+ be represented by multiple Unicode characters, such as in the case
+ of surrogate pairs, linguistic ligatures or diacritics.
+
\sa setPosition(), movePosition(), anchor(), positionInBlock()
*/
int QTextCursor::position() const
@@ -1192,6 +1208,13 @@ int QTextCursor::position() const
This is equivalent to \c{ position() - block().position()}.
+ \note The "characters" in this case refer to the string of QChar
+ objects, i.e. 16-bit Unicode characters, and the position is considered
+ an index into this string. This does not necessarily correspond to
+ individual graphemes in the writing system, as a single grapheme may
+ be represented by multiple Unicode characters, such as in the case
+ of surrogate pairs, linguistic ligatures or diacritics.
+
\sa position()
*/
int QTextCursor::positionInBlock() const
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index c0a0c1a177..0e3c8d0e83 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -40,6 +40,7 @@
#include <private/qtools_p.h>
#include <qdebug.h>
+#include <qscopedvaluerollback.h>
#include "qtextdocument_p.h"
#include "qtextdocument.h"
#include <qtextformat.h>
@@ -274,9 +275,10 @@ void QTextDocumentPrivate::clear()
rtFrame = 0;
init();
cursors = oldCursors;
- inContentsChange = true;
- emit q->contentsChange(0, len, 0);
- inContentsChange = false;
+ {
+ QScopedValueRollback<bool> bg(inContentsChange, true);
+ emit q->contentsChange(0, len, 0);
+ }
if (lout)
lout->documentChanged(0, len, 0);
} QT_CATCH(...) {
@@ -309,9 +311,10 @@ void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
it->free();
emit q->documentLayoutChanged();
- inContentsChange = true;
- emit q->contentsChange(0, 0, length());
- inContentsChange = false;
+ {
+ QScopedValueRollback<bool> bg(inContentsChange, true);
+ emit q->contentsChange(0, 0, length());
+ }
if (lout)
lout->documentChanged(0, 0, length());
}
@@ -1213,9 +1216,8 @@ void QTextDocumentPrivate::finishEdit()
if (lout && docChangeFrom >= 0) {
if (!inContentsChange) {
- inContentsChange = true;
+ QScopedValueRollback<bool> bg(inContentsChange, true);
emit q->contentsChange(docChangeFrom, docChangeOldLength, docChangeLength);
- inContentsChange = false;
}
lout->documentChanged(docChangeFrom, docChangeOldLength, docChangeLength);
}
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index d95f5bef6a..a8e17bfc08 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -339,6 +339,7 @@ private:
int lastBlockCount;
public:
+ bool inContentsChange;
QTextOption defaultTextOption;
Qt::CursorMoveStyle defaultCursorMoveStyle;
#ifndef QT_NO_CSSPARSER
@@ -346,7 +347,6 @@ public:
#endif
int maximumBlockCount;
uint needsEnsureMaximumBlockCount : 1;
- uint inContentsChange : 1;
uint blockCursorAdjustment : 1;
QSizeF pageSize;
QString title;
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 323253c70d..2e1a2b5bff 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -58,23 +58,17 @@
#include <limits.h>
#include <qbasictimer.h>
#include "private/qfunctions_p.h"
+#include <qloggingcategory.h>
#include <algorithm>
-// #define LAYOUT_DEBUG
-
-#ifdef LAYOUT_DEBUG
-#define LDEBUG qDebug()
-#define INC_INDENT debug_indent += " "
-#define DEC_INDENT debug_indent = debug_indent.left(debug_indent.length()-2)
-#else
-#define LDEBUG if(0) qDebug()
-#define INC_INDENT do {} while(0)
-#define DEC_INDENT do {} while(0)
-#endif
-
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcDraw, "qt.text.drawing")
+Q_LOGGING_CATEGORY(lcHit, "qt.text.hittest")
+Q_LOGGING_CATEGORY(lcLayout, "qt.text.layout")
+Q_LOGGING_CATEGORY(lcTable, "qt.text.layout.table")
+
// ################ should probably add frameFormatChange notification!
struct QTextLayoutStruct;
@@ -583,16 +577,16 @@ QTextDocumentLayoutPrivate::hitTest(QTextFrame *frame, const QFixedPoint &point,
QTextFrame *rootFrame = docPrivate->rootFrame();
-// LDEBUG << "checking frame" << frame->firstPosition() << "point=" << point
-// << "position" << fd->position << "size" << fd->size;
+ qCDebug(lcHit) << "checking frame" << frame->firstPosition() << "point=" << point.toPointF()
+ << "position" << fd->position.toPointF() << "size" << fd->size.toSizeF();
if (frame != rootFrame) {
if (relativePoint.y < 0 || relativePoint.x < 0) {
*position = frame->firstPosition() - 1;
-// LDEBUG << "before pos=" << *position;
+ qCDebug(lcHit) << "before pos=" << *position;
return PointBefore;
} else if (relativePoint.y > fd->size.height || relativePoint.x > fd->size.width) {
*position = frame->lastPosition() + 1;
-// LDEBUG << "after pos=" << *position;
+ qCDebug(lcHit) << "after pos=" << *position;
return PointAfter;
}
}
@@ -666,8 +660,6 @@ QTextDocumentLayoutPrivate::HitPoint
QTextDocumentLayoutPrivate::hitTest(QTextFrame::Iterator it, HitPoint hit, const QFixedPoint &p,
int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const
{
- INC_INDENT;
-
for (; !it.atEnd(); ++it) {
QTextFrame *c = it.currentFrame();
HitPoint hp;
@@ -693,8 +685,7 @@ QTextDocumentLayoutPrivate::hitTest(QTextFrame::Iterator it, HitPoint hit, const
}
}
- DEC_INDENT;
-// LDEBUG << "inside=" << hit << " pos=" << *position;
+ qCDebug(lcHit) << "inside=" << hit << " pos=" << *position;
return hit;
}
@@ -741,15 +732,14 @@ QTextDocumentLayoutPrivate::hitTest(const QTextBlock &bl, const QFixedPoint &poi
QTextLayout *tl = bl.layout();
QRectF textrect = tl->boundingRect();
textrect.translate(tl->position());
-// LDEBUG << " checking block" << bl.position() << "point=" << point
-// << " tlrect" << textrect;
+ qCDebug(lcHit) << " checking block" << bl.position() << "point=" << point.toPointF() << " tlrect" << textrect;
*position = bl.position();
if (point.y.toReal() < textrect.top()) {
-// LDEBUG << " before pos=" << *position;
+ qCDebug(lcHit) << " before pos=" << *position;
return PointBefore;
} else if (point.y.toReal() > textrect.bottom()) {
*position += bl.length();
-// LDEBUG << " after pos=" << *position;
+ qCDebug(lcHit) << " after pos=" << *position;
return PointAfter;
}
@@ -781,7 +771,7 @@ QTextDocumentLayoutPrivate::hitTest(const QTextBlock &bl, const QFixedPoint &poi
}
*position += off;
-// LDEBUG << " inside=" << hit << " pos=" << *position;
+ qCDebug(lcHit) << " inside=" << hit << " pos=" << *position;
return hit;
}
@@ -944,8 +934,7 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
|| off.x() > context.clip.right() || off.x() + fd->size.width.toReal() < context.clip.left()))
return;
-// LDEBUG << debug_indent << "drawFrame" << frame->firstPosition() << "--" << frame->lastPosition() << "at" << offset;
-// INC_INDENT;
+ qCDebug(lcDraw) << "drawFrame" << frame->firstPosition() << "--" << frame->lastPosition() << "at" << offset;
// if the cursor is /on/ a table border we may need to repaint it
// afterwards, as we usually draw the decoration first
@@ -1076,8 +1065,6 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
painter->setPen(oldPen);
}
-// DEC_INDENT;
-
return;
}
@@ -1280,7 +1267,7 @@ void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *pain
r.translate(offset + tl->position());
if (!bl.isVisible() || (context.clip.isValid() && (r.bottom() < context.clip.y() || r.top() > context.clip.bottom())))
return;
-// LDEBUG << debug_indent << "drawBlock" << bl.position() << "at" << offset << "br" << tl->boundingRect();
+ qCDebug(lcDraw) << "drawBlock" << bl.position() << "at" << offset << "br" << tl->boundingRect();
QTextBlockFormat blockFormat = bl.blockFormat();
@@ -1512,7 +1499,7 @@ QTextLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QT
int layoutFrom, int layoutTo, QTextTableData *td,
QFixed absoluteTableY, bool withPageBreaks)
{
- LDEBUG << "layoutCell";
+ qCDebug(lcTable) << "layoutCell";
QTextLayoutStruct layoutStruct;
layoutStruct.frame = t;
layoutStruct.minimumWidth = 0;
@@ -1587,7 +1574,7 @@ QTextLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QT
QRectF QTextDocumentLayoutPrivate::layoutTable(QTextTable *table, int layoutFrom, int layoutTo, QFixed parentY)
{
- LDEBUG << "layoutTable";
+ qCDebug(lcTable) << "layoutTable from" << layoutFrom << "to" << layoutTo << "parentY" << parentY;
QTextTableData *td = static_cast<QTextTableData *>(data(table));
Q_ASSERT(td->sizeDirty);
const int rows = table->rows();
@@ -1709,6 +1696,7 @@ recalc_minmax_widths:
if (length.type() == QTextLength::FixedLength) {
td->minWidths[i] = td->widths[i] = qMax(scaleToDevice(QFixed::fromReal(length.rawValue())), td->minWidths.at(i));
remainingWidth -= td->widths.at(i);
+ qCDebug(lcTable) << "column" << i << "has width constraint" << td->minWidths.at(i) << "px, remaining width now" << remainingWidth;
} else if (length.type() == QTextLength::PercentageLength) {
totalPercentage += QFixed::fromReal(length.rawValue());
} else if (length.type() == QTextLength::VariableLength) {
@@ -1716,6 +1704,7 @@ recalc_minmax_widths:
td->widths[i] = td->minWidths.at(i);
remainingWidth -= td->minWidths.at(i);
+ qCDebug(lcTable) << "column" << i << "has variable width, min" << td->minWidths.at(i) << "remaining width now" << remainingWidth;
}
totalMinWidth += td->minWidths.at(i);
}
@@ -1735,6 +1724,8 @@ recalc_minmax_widths:
} else {
td->widths[i] = td->minWidths.at(i);
}
+ qCDebug(lcTable) << "column" << i << "has width constraint" << columnWidthConstraints.at(i).rawValue()
+ << "%, allocated width" << td->widths[i] << "remaining width now" << remainingWidth;
remainingWidth -= td->widths.at(i);
}
}
@@ -1978,9 +1969,12 @@ relayout:
td->minimumWidth += rightMargin - td->border;
td->maximumWidth = td->columnPositions.at(0);
- for (int i = 0; i < columns; ++i)
+ for (int i = 0; i < columns; ++i) {
if (td->maxWidths.at(i) != QFIXED_MAX)
td->maximumWidth += td->maxWidths.at(i) + 2 * td->border + cellSpacing;
+ qCDebug(lcTable) << "column" << i << "has final width" << td->widths.at(i).toReal()
+ << "min" << td->minWidths.at(i).toReal() << "max" << td->maxWidths.at(i).toReal();
+ }
td->maximumWidth += rightMargin - td->border;
td->updateTableSize();
@@ -2052,9 +2046,8 @@ void QTextDocumentLayoutPrivate::positionFloat(QTextFrame *frame, QTextLine *cur
QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, QFixed parentY)
{
- LDEBUG << "layoutFrame (pre)";
+ qCDebug(lcLayout, "layoutFrame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
Q_ASSERT(data(f)->sizeDirty);
-// qDebug("layouting frame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
QTextFrameFormat fformat = f->frameFormat();
@@ -2076,9 +2069,8 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, QFixed frameWidth, QFixed frameHeight, QFixed parentY)
{
- LDEBUG << "layoutFrame from=" << layoutFrom << "to=" << layoutTo;
+ qCDebug(lcLayout, "layoutFrame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
Q_ASSERT(data(f)->sizeDirty);
-// qDebug("layouting frame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
QTextFrameData *fd = data(f);
QFixed newContentsWidth;
@@ -2165,8 +2157,8 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
layoutStruct.maximumWidth = QFIXED_MAX;
layoutStruct.fullLayout = fullLayout || (fd->oldContentsWidth != newContentsWidth);
layoutStruct.updateRect = QRectF(QPointF(0, 0), QSizeF(qreal(INT_MAX), qreal(INT_MAX)));
- LDEBUG << "layoutStruct: x_left" << layoutStruct.x_left << "x_right" << layoutStruct.x_right
- << "fullLayout" << layoutStruct.fullLayout;
+ qCDebug(lcLayout) << "layoutStruct: x_left" << layoutStruct.x_left << "x_right" << layoutStruct.x_right
+ << "fullLayout" << layoutStruct.fullLayout;
fd->oldContentsWidth = newContentsWidth;
layoutStruct.pageHeight = QFixed::fromReal(document->pageSize().height());
@@ -2220,7 +2212,7 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayoutStruct *layoutStruct,
int layoutFrom, int layoutTo, QFixed width)
{
- LDEBUG << "layoutFlow from=" << layoutFrom << "to=" << layoutTo;
+ qCDebug(lcLayout) << "layoutFlow from=" << layoutFrom << "to=" << layoutTo;
QTextFrameData *fd = data(layoutStruct->frame);
fd->currentLayoutStruct = layoutStruct;
@@ -2578,9 +2570,8 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
QTextLayout *tl = bl.layout();
const int blockLength = bl.length();
- LDEBUG << "layoutBlock from=" << layoutFrom << "to=" << layoutTo;
-
-// qDebug() << "layoutBlock; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ')';
+ qCDebug(lcLayout) << "layoutBlock from=" << layoutFrom << "to=" << layoutTo
+ << "; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ')';
if (previousBlockFormat) {
qreal margin = qMax(blockFormat.topMargin(), previousBlockFormat->bottomMargin());
@@ -2612,7 +2603,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
// force relayout if we cross a page boundary
|| (layoutStruct->pageHeight != QFIXED_MAX && layoutStruct->absoluteY() + QFixed::fromReal(tl->boundingRect().height()) > layoutStruct->pageBottom)) {
- LDEBUG << " do layout";
+ qCDebug(lcLayout) << "do layout";
QTextOption option = docPrivate->defaultTextOption;
option.setTextDirection(dir);
option.setTabs( blockFormat.tabPositions() );
@@ -2741,7 +2732,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
const int cnt = tl->lineCount();
QFixed bottom;
for (int i = 0; i < cnt; ++i) {
- LDEBUG << "going to move text line" << i;
+ qCDebug(lcLayout) << "going to move text line" << i;
QTextLine line = tl->lineAt(i);
layoutStruct->contentsWidth
= qMax(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + tl->lineAt(i).naturalTextWidth()) + totalRightMargin);
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 130d506975..2616a42022 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1754,7 +1754,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
#ifdef Q_OS_DARWIN
if (actualFontEngine->type() == QFontEngine::Mac) {
- if (actualFontEngine->fontDef.stretch != 100) {
+ if (actualFontEngine->fontDef.stretch != 100 && actualFontEngine->fontDef.stretch != QFont::AnyStretch) {
QFixed stretch = QFixed(int(actualFontEngine->fontDef.stretch)) / QFixed(100);
for (uint i = 0; i < num_glyphs; ++i)
g.advances[i] *= stretch;