summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/qaccessible.cpp12
-rw-r--r--src/gui/configure.json4
-rw-r--r--src/gui/image/qimage_conversions.cpp18
-rw-r--r--src/gui/image/qimage_darwin.mm4
-rw-r--r--src/gui/image/qpixmap_raster.cpp2
-rw-r--r--src/gui/image/qpnghandler.cpp6
-rw-r--r--src/gui/kernel/qdrag.cpp2
-rw-r--r--src/gui/kernel/qplatformdrag.cpp2
-rw-r--r--src/gui/kernel/qplatformwindow.cpp2
-rw-r--r--src/gui/kernel/qplatformwindow.h1
-rw-r--r--src/gui/kernel/qwindow.cpp67
-rw-r--r--src/gui/kernel/qwindow_p.h1
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp4
-rw-r--r--src/gui/painting/qdrawhelper.cpp459
-rw-r--r--src/gui/painting/qdrawhelper_mips_dsp.cpp15
-rw-r--r--src/gui/painting/qdrawhelper_mips_dsp_p.h12
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp13
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp2
-rw-r--r--src/gui/painting/qpainter.cpp1
-rw-r--r--src/gui/text/qfontmetrics.cpp6
-rw-r--r--src/gui/text/qharfbuzzng.cpp117
-rw-r--r--src/gui/text/qtextengine.cpp28
22 files changed, 547 insertions, 231 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 874b99be4f..2db4d46874 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -52,12 +52,15 @@
#include <qpa/qplatformintegration.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qloggingcategory.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qhash.h>
#include <private/qfactoryloader_p.h>
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
+
/*!
\class QAccessible
\brief The QAccessible class provides enums and static functions
@@ -1370,8 +1373,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(m_object);
if (!iface)
return 0;
- if (m_child != -1)
+ if (m_child != -1) {
iface = iface->child(m_child);
+ if (Q_UNLIKELY(!iface)) {
+ qCWarning(lcAccessibilityCore) << "Invalid child in QAccessibleEvent:" << m_object << "child:" << m_child;
+ return 0;
+ }
+ }
return QAccessible::uniqueId(iface);
}
@@ -1769,7 +1777,7 @@ QAccessibleInterface *QAccessibleEvent::accessibleInterface() const
if (child) {
iface = child;
} else {
- qWarning() << "Cannot creat accessible child interface for object: " << m_object << " index: " << m_child;
+ qCWarning(lcAccessibilityCore) << "Cannot create accessible child interface for object: " << m_object << " index: " << m_child;
}
}
return iface;
diff --git a/src/gui/configure.json b/src/gui/configure.json
index 02032dee8f..6d0848c9f0 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -182,7 +182,7 @@
"label": "Desktop OpenGL",
"test": "unix/opengldesktop",
"sources": [
- { "type": "pkgConfig", "args": "gl" },
+ { "type": "pkgConfig", "args": "gl", "condition": "!config.darwin" },
{ "type": "makeSpec", "spec": "OPENGL" }
]
},
@@ -190,7 +190,7 @@
"label": "OpenGL ES 2.0",
"test": "unix/opengles2",
"sources": [
- { "type": "pkgConfig", "args": "glesv2" },
+ { "type": "pkgConfig", "args": "glesv2", "condition": "!config.darwin" },
{ "type": "makeSpec", "spec": "OPENGL_ES2" }
]
},
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index d685d50d49..2a0bdeb7c1 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -2979,16 +2979,14 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_neon;
#endif
-#ifdef QT_COMPILER_SUPPORTS_MIPS_DSPR2
- if (qCpuHasFeature(DSPR2)) {
- extern bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConversionFlags);
- qimage_inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_mips_dspr2;
-
- extern void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
- qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_mips_dspr2;
- qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_mips_dspr2;
- qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_mips_dspr2;
- }
+#if defined(__MIPS_DSPR2__)
+ extern bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConversionFlags);
+ qimage_inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_mips_dspr2;
+
+ extern void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_mips_dspr2;
#endif
}
diff --git a/src/gui/image/qimage_darwin.mm b/src/gui/image/qimage_darwin.mm
index d72733abd3..2d38468cc5 100644
--- a/src/gui/image/qimage_darwin.mm
+++ b/src/gui/image/qimage_darwin.mm
@@ -41,7 +41,7 @@
QT_BEGIN_NAMESPACE
/*!
- Creates a \c CGImage equivalent to the QImage \a image. Returns a
+ Creates a \c CGImage equivalent to this QImage. Returns a
\c CGImageRef handle.
The returned CGImageRef partakes in the QImage implicit sharing,
@@ -85,7 +85,7 @@ QT_BEGIN_NAMESPACE
The CGImageRef color space is set to the sRGB color space.
- \sa toNSImage()
+ \sa QtMac::toNSImage()
*/
CGImageRef QImage::toCGImage() const
{
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 54a5b94840..7eb61adb2d 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -349,8 +349,6 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage sourceImage, Qt::ImageCo
}
is_null = (w <= 0 || h <= 0);
- if (image.d)
- image.d->devicePixelRatio = sourceImage.devicePixelRatio();
//ensure the pixmap and the image resulting from toImage() have the same cacheKey();
setSerialNumber(image.cacheKey() >> 32);
if (image.d)
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index fdf77e162c..d55a26b2a4 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -521,6 +521,12 @@ bool QPngHandlerPrivate::readPngHeader()
png_set_error_fn(png_ptr, 0, 0, qt_png_warning);
+#if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW)
+ // Trade off a little bit of memory for better compatibility with existing images
+ // Ref. "invalid distance too far back" explanation in libpng-manual.txt
+ png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
+#endif
+
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, 0, 0);
diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp
index 5b36f496f1..0aadac2c62 100644
--- a/src/gui/kernel/qdrag.cpp
+++ b/src/gui/kernel/qdrag.cpp
@@ -393,7 +393,7 @@ Qt::DropAction QDrag::defaultAction() const
\note This is currently implemented on Windows and X11.
- \since 5.6
+ \since 5.7
\sa exec()
*/
void QDrag::cancel()
diff --git a/src/gui/kernel/qplatformdrag.cpp b/src/gui/kernel/qplatformdrag.cpp
index 903f6686a8..3c23406a6b 100644
--- a/src/gui/kernel/qplatformdrag.cpp
+++ b/src/gui/kernel/qplatformdrag.cpp
@@ -166,7 +166,7 @@ Qt::DropAction QPlatformDrag::defaultAction(Qt::DropActions possibleActions,
The default implementation does nothing.
- \since 5.6
+ \since 5.7
*/
void QPlatformDrag::cancelDrag()
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 6fd2afb1aa..bfb2deff50 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -508,7 +508,7 @@ QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) co
// QRect::center can return a value outside the rectangle if it's empty.
// Apply mapToGlobal() in case it is a foreign/embedded window.
QPoint center = newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center();
- if (window()->type() == Qt::ForeignWindow)
+ if (isForeignWindow())
center = mapToGlobal(center - newGeometry.topLeft());
if (!parent() && currentScreen && !currentScreen->geometry().contains(center)) {
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index d7fdbb156e..8af8791bb4 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -104,6 +104,7 @@ public:
virtual bool isActive() const;
virtual bool isAncestorOf(const QPlatformWindow *child) const;
virtual bool isEmbedded() const;
+ virtual bool isForeignWindow() const { return window()->type() == Qt::ForeignWindow; };
virtual QPoint mapToGlobal(const QPoint &pos) const;
virtual QPoint mapFromGlobal(const QPoint &pos) const;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 5a27b19101..47277abea3 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -208,7 +208,8 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
*/
QWindow::~QWindow()
{
- destroy();
+ Q_D(QWindow);
+ d->destroy();
QGuiApplicationPrivate::window_list.removeAll(this);
if (!QGuiApplicationPrivate::is_app_closing)
QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this);
@@ -1762,42 +1763,54 @@ void QWindow::destroy()
if (!d->platformWindow)
return;
- QObjectList childrenWindows = children();
+ if (d->platformWindow->isForeignWindow())
+ return;
+
+ d->destroy();
+}
+
+void QWindowPrivate::destroy()
+{
+ if (!platformWindow)
+ return;
+
+ Q_Q(QWindow);
+ QObjectList childrenWindows = q->children();
for (int i = 0; i < childrenWindows.size(); i++) {
QObject *object = childrenWindows.at(i);
if (object->isWindowType()) {
QWindow *w = static_cast<QWindow*>(object);
- w->destroy();
+ qt_window_private(w)->destroy();
}
}
- if (QGuiApplicationPrivate::focus_window == this)
- QGuiApplicationPrivate::focus_window = parent();
- if (QGuiApplicationPrivate::currentMouseWindow == this)
- QGuiApplicationPrivate::currentMouseWindow = parent();
- if (QGuiApplicationPrivate::currentMousePressWindow == this)
- QGuiApplicationPrivate::currentMousePressWindow = parent();
+ if (QGuiApplicationPrivate::focus_window == q)
+ QGuiApplicationPrivate::focus_window = q->parent();
+ if (QGuiApplicationPrivate::currentMouseWindow == q)
+ QGuiApplicationPrivate::currentMouseWindow = q->parent();
+ if (QGuiApplicationPrivate::currentMousePressWindow == q)
+ QGuiApplicationPrivate::currentMousePressWindow = q->parent();
for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i)
- if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == this)
- QGuiApplicationPrivate::tabletDevicePoints[i].target = parent();
+ if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == q)
+ QGuiApplicationPrivate::tabletDevicePoints[i].target = q->parent();
- bool wasVisible = isVisible();
- d->visibilityOnDestroy = wasVisible && d->platformWindow;
+ bool wasVisible = q->isVisible();
+ visibilityOnDestroy = wasVisible && platformWindow;
- setVisible(false);
+ q->setVisible(false);
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
- QGuiApplication::sendEvent(this, &e);
+ QGuiApplication::sendEvent(q, &e);
- delete d->platformWindow;
- d->resizeEventPending = true;
- d->receivedExpose = false;
- d->exposed = false;
- d->platformWindow = 0;
+ delete platformWindow;
+ resizeEventPending = true;
+ receivedExpose = false;
+ exposed = false;
+ platformWindow = 0;
if (wasVisible)
- d->maybeQuitOnLastWindowClosed();
+ maybeQuitOnLastWindowClosed();
}
/*!
@@ -2440,7 +2453,7 @@ QPoint QWindow::mapToGlobal(const QPoint &pos) const
Q_D(const QWindow);
// QTBUG-43252, prefer platform implementation for foreign windows.
if (d->platformWindow
- && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded())) {
+ && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
return pos + d->globalPosition();
@@ -2460,7 +2473,7 @@ QPoint QWindow::mapFromGlobal(const QPoint &pos) const
Q_D(const QWindow);
// QTBUG-43252, prefer platform implementation for foreign windows.
if (d->platformWindow
- && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded())) {
+ && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
return pos - d->globalPosition();
@@ -2471,11 +2484,13 @@ QPoint QWindowPrivate::globalPosition() const
Q_Q(const QWindow);
QPoint offset = q->position();
for (const QWindow *p = q->parent(); p; p = p->parent()) {
- if (p->type() != Qt::ForeignWindow) {
- offset += p->position();
- } else { // Use mapToGlobal() for foreign windows
+ QPlatformWindow *pw = p->handle();
+ if (pw && pw->isForeignWindow()) {
+ // Use mapToGlobal() for foreign windows
offset += p->mapToGlobal(QPoint(0, 0));
break;
+ } else {
+ offset += p->position();
}
}
return offset;
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 95c6abf428..d1727a1c57 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -137,6 +137,7 @@ public:
bool windowRecreationRequired(QScreen *newScreen) const;
void create(bool recursive);
+ void destroy();
void setTopLevelScreen(QScreen *newScreen, bool recreate);
void connectToScreen(QScreen *topLevelScreen);
void disconnectFromScreen();
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index ad8b19a2bc..e724efab37 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -45,7 +45,6 @@
#include <QtGui/private/qopengl_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
-#include <QtCore/qloggingcategory.h>
#ifdef Q_OS_INTEGRITY
#include <EGL/egl.h>
@@ -57,9 +56,6 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcGLES3, "qt.opengl.es3")
-
-
#define QT_OPENGL_COUNT_FUNCTIONS(ret, name, args) +1
#define QT_OPENGL_FUNCTION_NAMES(ret, name, args) \
"gl"#name"\0"
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 4ea3b37d5f..4671c5cecf 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1540,12 +1540,8 @@ static const uint *QT_FASTCALL fetchUntransformedRGB16(uint *buffer, const Opera
int length)
{
const quint16 *scanLine = (const quint16 *)data->texture.scanLine(y) + x;
-#ifdef QT_COMPILER_SUPPORTS_MIPS_DSPR2
- qConvertRgb16To32_asm_mips_dspr2(buffer, scanLine, length);
-#else
for (int i = 0; i < length; ++i)
buffer[i] = qConvertRgb16To32(scanLine[i]);
-#endif
return buffer;
}
@@ -5543,32 +5539,160 @@ inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer,
map, mapWidth, mapHeight, mapStride);
}
-static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
+static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorProfile *colorProfile)
+{
+ if (coverage == 0) {
+ // nothing
+ } else if (coverage == 255) {
+ dest[x] = src;
+ } else {
+ QRgba64 dstColor = dest[x];
+ if (colorProfile) {
+ if (dstColor.isOpaque())
+ dstColor = colorProfile->toLinear(dstColor);
+ else if (!dstColor.isTransparent())
+ dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied();
+ }
+
+ dstColor = interpolate255(srcLinear, coverage, dstColor, 255 - coverage);
+ if (colorProfile) {
+ if (dstColor.isOpaque())
+ dstColor = colorProfile->fromLinear(dstColor);
+ else if (!dstColor.isTransparent())
+ dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied();
+ }
+ dest[x] = dstColor;
+ }
+}
+
+static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *, bool /*useGammaCorrection*/)
+ const QClipData *clip, bool useGammaCorrection)
{
- const quint16 c = color.toRgb16();
- quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
- const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
+ if (color.isTransparent())
+ return;
- while (mapHeight--) {
- for (int i = 0; i < mapWidth; ++i) {
- const int coverage = map[i];
+ const QColorProfile *colorProfile = nullptr;
- if (coverage == 0) {
- // nothing
- } else if (coverage == 255) {
- dest[i] = c;
- } else {
- int ialpha = 255 - coverage;
- dest[i] = BYTE_MUL_RGB16(c, coverage)
- + BYTE_MUL_RGB16(dest[i], ialpha);
+ if (useGammaCorrection)
+ colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
+
+ QRgba64 srcColor = color;
+ if (colorProfile) {
+ if (color.isOpaque())
+ srcColor = colorProfile->toLinear(srcColor);
+ else
+ srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
+ }
+
+ QRgba64 buffer[buffer_size];
+ const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format];
+ const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format];
+
+ if (!clip) {
+ for (int ly = 0; ly < mapHeight; ++ly) {
+ int i = x;
+ int length = mapWidth;
+ while (length > 0) {
+ int l = qMin(buffer_size, length);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, i, y + ly, l);
+ for (int j=0; j < l; ++j) {
+ const int coverage = map[j + (i - x)];
+ alphamapblend_generic(coverage, dest, j, srcColor, color, colorProfile);
+ }
+ destStore64(rasterBuffer, i, y + ly, buffer, l);
+ length -= l;
+ i += l;
}
+ map += mapStride;
}
- dest += destStride;
- map += mapStride;
+ } else {
+ int bottom = qMin(y + mapHeight, rasterBuffer->height());
+
+ int top = qMax(y, 0);
+ map += (top - y) * mapStride;
+
+ const_cast<QClipData *>(clip)->initialize();
+ for (int yp = top; yp<bottom; ++yp) {
+ const QClipData::ClipLine &line = clip->m_clipLines[yp];
+
+ for (int i=0; i<line.count; ++i) {
+ const QSpan &clip = line.spans[i];
+
+ int start = qMax<int>(x, clip.x);
+ int end = qMin<int>(x + mapWidth, clip.x + clip.len);
+ Q_ASSERT(clip.len <= buffer_size);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, start, clip.y, clip.len);
+
+ for (int xp=start; xp<end; ++xp) {
+ const int coverage = map[xp - x];
+ alphamapblend_generic(coverage, dest, xp - start, srcColor, color, colorProfile);
+ }
+ destStore64(rasterBuffer, start, clip.y, dest, clip.len);
+ } // for (i -> line.count)
+ map += mapStride;
+ } // for (yp -> bottom)
+ }
+}
+
+static inline void alphamapblend_quint16(int coverage, quint16 *dest, int x, const quint16 srcColor)
+{
+ if (coverage == 0) {
+ // nothing
+ } else if (coverage == 255) {
+ dest[x] = srcColor;
+ } else {
+ dest[x] = BYTE_MUL_RGB16(srcColor, coverage)
+ + BYTE_MUL_RGB16(dest[x], 255 - coverage);
+ }
+}
+
+void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uchar *map,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *clip, bool useGammaCorrection)
+{
+ if (useGammaCorrection) {
+ qt_alphamapblit_generic(rasterBuffer, x, y, color, map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection);
+ return;
+ }
+
+ const quint16 c = color.toRgb16();
+
+ if (!clip) {
+ quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
+ const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
+ while (mapHeight--) {
+ for (int i = 0; i < mapWidth; ++i)
+ alphamapblend_quint16(map[i], dest, i, c);
+ dest += destStride;
+ map += mapStride;
+ }
+ } else {
+ int top = qMax(y, 0);
+ int bottom = qMin(y + mapHeight, rasterBuffer->height());
+ map += (top - y) * mapStride;
+
+ const_cast<QClipData *>(clip)->initialize();
+ for (int yp = top; yp<bottom; ++yp) {
+ const QClipData::ClipLine &line = clip->m_clipLines[yp];
+
+ quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(yp));
+
+ for (int i=0; i<line.count; ++i) {
+ const QSpan &clip = line.spans[i];
+
+ int start = qMax<int>(x, clip.x);
+ int end = qMin<int>(x + mapWidth, clip.x + clip.len);
+
+ for (int xp=start; xp<end; ++xp)
+ alphamapblend_quint16(map[xp - x], dest, xp, c);
+ } // for (i -> line.count)
+ map += mapStride;
+ } // for (yp -> bottom)
}
}
@@ -5694,19 +5818,119 @@ static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
}
#endif
-inline static int qRgbAvg(QRgb rgb)
+static inline int qRgbAvg(QRgb rgb)
{
return (qRed(rgb) * 5 + qGreen(rgb) * 6 + qBlue(rgb) * 5) / 16;
}
+static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorProfile *colorProfile)
+{
+ if (coverage == 0xff000000) {
+ // nothing
+ } else if (coverage == 0xffffffff) {
+ dest[x] = src;
+ } else {
+ QRgba64 dstColor = dest[x];
+ if (dstColor.isOpaque()) {
+ if (colorProfile)
+ dstColor = colorProfile->toLinear(dstColor);
+ dstColor = rgbBlend(dstColor, srcLinear, coverage);
+ if (colorProfile)
+ dstColor = colorProfile->fromLinear(dstColor);
+ dest[x] = dstColor;
+ } else {
+ // Give up and do a gray alphablend.
+ if (colorProfile && !dstColor.isTransparent())
+ dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied();
+ const int a = qRgbAvg(coverage);
+ dstColor = interpolate255(srcLinear, coverage, dstColor, 255 - a);
+ if (colorProfile && !dstColor.isTransparent())
+ dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied();
+ dest[x] = dstColor;
+ }
+ }
+}
+
+static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uint *src, int mapWidth, int mapHeight, int srcStride,
+ const QClipData *clip, bool useGammaCorrection)
+{
+ if (color.isTransparent())
+ return;
+
+ const QColorProfile *colorProfile = nullptr;
+
+ if (useGammaCorrection)
+ colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
+
+ QRgba64 srcColor = color;
+ if (colorProfile) {
+ if (color.isOpaque())
+ srcColor = colorProfile->toLinear(srcColor);
+ else
+ srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
+ }
+
+ QRgba64 buffer[buffer_size];
+ const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format];
+ const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format];
+
+ if (!clip) {
+ for (int ly = 0; ly < mapHeight; ++ly) {
+ int i = x;
+ int length = mapWidth;
+ while (length > 0) {
+ int l = qMin(buffer_size, length);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, i, y + ly, l);
+ for (int j=0; j < l; ++j) {
+ const uint coverage = src[j + (i - x)];
+ alphargbblend_generic(coverage, dest, j, srcColor, color, colorProfile);
+ }
+ destStore64(rasterBuffer, i, y + ly, buffer, l);
+ length -= l;
+ i += l;
+ }
+ src += srcStride;
+ }
+ } else {
+ int bottom = qMin(y + mapHeight, rasterBuffer->height());
+
+ int top = qMax(y, 0);
+ src += (top - y) * srcStride;
+
+ const_cast<QClipData *>(clip)->initialize();
+ for (int yp = top; yp<bottom; ++yp) {
+ const QClipData::ClipLine &line = clip->m_clipLines[yp];
+
+ for (int i=0; i<line.count; ++i) {
+ const QSpan &clip = line.spans[i];
+
+ int start = qMax<int>(x, clip.x);
+ int end = qMin<int>(x + mapWidth, clip.x + clip.len);
+ Q_ASSERT(clip.len <= buffer_size);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, start, clip.y, clip.len);
+
+ for (int xp=start; xp<end; ++xp) {
+ const uint coverage = src[xp - x];
+ alphargbblend_generic(coverage, dest, xp - start, srcColor, color, colorProfile);
+ }
+ destStore64(rasterBuffer, start, clip.y, dest, clip.len);
+ } // for (i -> line.count)
+ src += srcStride;
+ } // for (yp -> bottom)
+ }
+}
+
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *src, int mapWidth, int mapHeight, int srcStride,
const QClipData *clip, bool useGammaCorrection)
{
- const quint32 c = color.toArgb32();
+ if (color.isTransparent())
+ return;
- int sa = qAlpha(c);
+ const quint32 c = color.toArgb32();
const QColorProfile *colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
if (!colorProfile)
@@ -5714,9 +5938,6 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
const QRgba64 slinear = useGammaCorrection ? colorProfile->toLinear64(c) : color;
- if (sa == 0)
- return;
-
if (!clip) {
quint32 *dst = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
@@ -5729,9 +5950,12 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (dst[i] >= 0xff000000) {
rgbBlendPixel(dst+i, coverage, slinear, colorProfile, useGammaCorrection);
} else {
- // Give up and do a naive blend.
+ // Give up and do a gray blend.
const int a = qRgbAvg(coverage);
- dst[i] = INTERPOLATE_PIXEL_255(c, a, dst[i], 255 - a);
+ if (useGammaCorrection)
+ grayBlendPixel(dst+i, a, slinear, colorProfile);
+ else
+ dst[i] = INTERPOLATE_PIXEL_255(c, a, dst[i], 255 - a);
}
}
}
@@ -5765,9 +5989,12 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (dst[xp] >= 0xff000000) {
rgbBlendPixel(dst+xp, coverage, slinear, colorProfile, useGammaCorrection);
} else {
- // Give up and do a naive blend.
+ // Give up and do a gray blend.
const int a = qRgbAvg(coverage);
- dst[xp] = INTERPOLATE_PIXEL_255(c, a, dst[xp], 255 - coverage);
+ if (useGammaCorrection)
+ grayBlendPixel(dst+xp, a, slinear, colorProfile);
+ else
+ dst[xp] = INTERPOLATE_PIXEL_255(c, a, dst[xp], 255 - coverage);
}
}
}
@@ -5901,56 +6128,80 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
qt_gradient_quint16,
qt_bitmapblit_quint16,
qt_alphamapblit_quint16,
- 0,
+ qt_alphargbblit_generic,
qt_rectfill_quint16
},
// Format_ARGB8565_Premultiplied
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_RGB666
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_ARGB6666_Premultiplied
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_RGB555
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_ARGB8555_Premultiplied
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_RGB888
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_RGB444
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_ARGB4444_Premultiplied
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0, 0
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ 0
},
// Format_RGBX8888
{
@@ -5960,9 +6211,9 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
qt_alphamapblit_rgba8888,
#else
- 0,
+ qt_alphamapblit_generic,
#endif
- 0,
+ qt_alphargbblit_generic,
qt_rectfill_rgba
},
// Format_RGBA8888
@@ -5973,9 +6224,9 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
qt_alphamapblit_rgba8888,
#else
- 0,
+ qt_alphamapblit_generic,
#endif
- 0,
+ qt_alphargbblit_generic,
qt_rectfill_nonpremul_rgba
},
// Format_RGB8888_Premultiplied
@@ -5986,9 +6237,9 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
qt_alphamapblit_rgba8888,
#else
- 0,
+ qt_alphamapblit_generic,
#endif
- 0,
+ qt_alphargbblit_generic,
qt_rectfill_rgba
},
// Format_BGR30
@@ -5996,8 +6247,8 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
blend_color_generic_rgb64,
blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderBGR>,
- 0,
- 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
qt_rectfill_rgb30<PixelOrderBGR>
},
// Format_A2BGR30_Premultiplied
@@ -6005,8 +6256,8 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
blend_color_generic_rgb64,
blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderBGR>,
- 0,
- 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
qt_rectfill_rgb30<PixelOrderBGR>
},
// Format_RGB30
@@ -6014,8 +6265,8 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
blend_color_generic_rgb64,
blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderRGB>,
- 0,
- 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
qt_rectfill_rgb30<PixelOrderRGB>
},
// Format_A2RGB30_Premultiplied
@@ -6023,22 +6274,26 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
blend_color_generic_rgb64,
blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderRGB>,
- 0,
- 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
qt_rectfill_rgb30<PixelOrderRGB>
},
// Format_Alpha8
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0,
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
qt_rectfill_alpha
},
// Format_Grayscale8
{
blend_color_generic,
blend_src_generic,
- 0, 0, 0,
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
qt_rectfill_gray
},
};
@@ -6105,7 +6360,7 @@ void qt_memfill16(quint16 *dest, quint16 color, int count)
qt_memfill_template<quint16>(dest, color, count);
}
#endif
-#if !defined(__SSE2__) && !defined(__ARM_NEON__) && !defined(__mips_dsp)
+#if !defined(__SSE2__) && !defined(__ARM_NEON__) && !defined(__MIPS_DSP__)
void qt_memfill32(quint32 *dest, quint32 color, int count)
{
qt_memfill_template<quint32>(dest, color, count);
@@ -6296,52 +6551,50 @@ static void qInitDrawhelperFunctions()
qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon;
qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon;
#endif
-
-#endif
-
-#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP) || defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
- if (qCpuHasFeature(DSP) && qCpuHasFeature(DSPR2)) {
- // Composition functions are all DSP r1
- qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_DestinationOver] = comp_func_DestinationOver_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_SourceIn] = comp_func_SourceIn_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_DestinationIn] = comp_func_DestinationIn_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_DestinationOut] = comp_func_DestinationOut_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_SourceAtop] = comp_func_SourceAtop_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_DestinationAtop] = comp_func_DestinationAtop_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_Xor] = comp_func_XOR_mips_dsp;
- qt_functionForMode_C[QPainter::CompositionMode_SourceOut] = comp_func_SourceOut_mips_dsp;
-
- qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_mips_dsp;
- qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationOver] = comp_func_solid_DestinationOver_mips_dsp;
- qt_functionForModeSolid_C[QPainter::CompositionMode_SourceIn] = comp_func_solid_SourceIn_mips_dsp;
- qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationIn] = comp_func_solid_DestinationIn_mips_dsp;
- qt_functionForModeSolid_C[QPainter::CompositionMode_SourceAtop] = comp_func_solid_SourceAtop_mips_dsp;
- qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationAtop] = comp_func_solid_DestinationAtop_mips_dsp;
- qt_functionForModeSolid_C[QPainter::CompositionMode_Xor] = comp_func_solid_XOR_mips_dsp;
- qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOut] = comp_func_solid_SourceOut_mips_dsp;
-
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mips_dsp;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mips_dsp;
-
- destFetchProc[QImage::Format_ARGB32] = qt_destFetchARGB32_mips_dsp;
-
- destStoreProc[QImage::Format_ARGB32] = qt_destStoreARGB32_mips_dsp;
-
- sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_mips_dsp;
- sourceFetchUntransformed[QImage::Format_RGB444] = qt_fetchUntransformed_444_mips_dsp;
- sourceFetchUntransformed[QImage::Format_ARGB8565_Premultiplied] = qt_fetchUntransformed_argb8565_premultiplied_mips_dsp;
-
-#if defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
- qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_mips_dspr2;
+#endif // defined(__ARM_NEON__)
+
+#if defined(__MIPS_DSP__)
+ // Composition functions are all DSP r1
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationOver] = comp_func_DestinationOver_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceIn] = comp_func_SourceIn_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationIn] = comp_func_DestinationIn_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationOut] = comp_func_DestinationOut_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceAtop] = comp_func_SourceAtop_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationAtop] = comp_func_DestinationAtop_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_Xor] = comp_func_XOR_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOut] = comp_func_SourceOut_mips_dsp;
+
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationOver] = comp_func_solid_DestinationOver_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceIn] = comp_func_solid_SourceIn_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationIn] = comp_func_solid_DestinationIn_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceAtop] = comp_func_solid_SourceAtop_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationAtop] = comp_func_solid_DestinationAtop_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_Xor] = comp_func_solid_XOR_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOut] = comp_func_solid_SourceOut_mips_dsp;
+
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mips_dsp;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mips_dsp;
+
+ destFetchProc[QImage::Format_ARGB32] = qt_destFetchARGB32_mips_dsp;
+
+ destStoreProc[QImage::Format_ARGB32] = qt_destStoreARGB32_mips_dsp;
+
+ sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_mips_dsp;
+ sourceFetchUntransformed[QImage::Format_RGB444] = qt_fetchUntransformed_444_mips_dsp;
+ sourceFetchUntransformed[QImage::Format_ARGB8565_Premultiplied] = qt_fetchUntransformed_argb8565_premultiplied_mips_dsp;
+
+#if defined(__MIPS_DSPR2__)
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_mips_dspr2;
+ sourceFetchUntransformed[QImage::Format_RGB16] = qt_fetchUntransformedRGB16_mips_dspr2;
#else
- qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_mips_dsp;
-#endif // QT_COMPILER_SUPPORTS_MIPS_DSPR2
- }
-#endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_mips_dsp;
+#endif // defined(__MIPS_DSPR2__)
+#endif // defined(__MIPS_DSP__)
}
// Ensure initialization if this object file is linked.
diff --git a/src/gui/painting/qdrawhelper_mips_dsp.cpp b/src/gui/painting/qdrawhelper_mips_dsp.cpp
index 783e481296..e92a6606de 100644
--- a/src/gui/painting/qdrawhelper_mips_dsp.cpp
+++ b/src/gui/painting/qdrawhelper_mips_dsp.cpp
@@ -113,7 +113,7 @@ void qt_blend_rgb32_on_rgb32_mips_dsp(uchar *destPixels, int dbpl,
}
}
-#if defined QT_COMPILER_SUPPORTS_MIPS_DSPR2
+#if defined(__MIPS_DSPR2__)
void qt_blend_rgb16_on_rgb16_mips_dspr2(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
@@ -521,4 +521,17 @@ const uint * QT_FASTCALL qt_fetchUntransformed_argb8565_premultiplied_mips_dsp (
return buffer;
}
+#if defined(__MIPS_DSPR2__)
+extern "C" void qConvertRgb16To32_asm_mips_dspr2(quint32 *dest, const quint16 *src, int length);
+
+const uint *QT_FASTCALL qt_fetchUntransformedRGB16_mips_dspr2(uint *buffer, const Operator *,
+ const QSpanData *data, int y, int x,
+ int length)
+{
+ const quint16 *scanLine = (const quint16 *)data->texture.scanLine(y) + x;
+ qConvertRgb16To32_asm_mips_dspr2(buffer, scanLine, length);
+ return buffer;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_mips_dsp_p.h b/src/gui/painting/qdrawhelper_mips_dsp_p.h
index 86773ad25f..36c4af2732 100644
--- a/src/gui/painting/qdrawhelper_mips_dsp_p.h
+++ b/src/gui/painting/qdrawhelper_mips_dsp_p.h
@@ -192,12 +192,9 @@ const uint * QT_FASTCALL qt_fetchUntransformed_argb8565_premultiplied_mips_dsp (
const QSpanData *data,
int y, int x, int length);
-#endif // QT_COMPILER_SUPPORTS_MIPS_DSP
-
-#ifdef QT_COMPILER_SUPPORTS_MIPS_DSPR2
-extern "C" void qConvertRgb16To32_asm_mips_dspr2(quint32 *dest, const quint16 *src, int length);
+#if defined(__MIPS_DSPR2__)
extern "C" void qt_blend_rgb16_on_rgb16_mips_dspr2_asm(quint16 *dest, const quint16 *src, int length, uint const_alpha);
@@ -206,7 +203,12 @@ void qt_blend_rgb16_on_rgb16_mips_dspr2(uchar *destPixels, int dbpl,
int w, int h,
int const_alpha);
-#endif // QT_COMPILER_SUPPORTS_MIPS_DSPR2
+const uint *QT_FASTCALL qt_fetchUntransformedRGB16_mips_dspr2(uint *buffer, const Operator *,
+ const QSpanData *data, int y, int x,
+ int length);
+#endif // defined(__MIPS_DSPR2__)
+
+#endif // QT_COMPILER_SUPPORTS_MIPS_DSP
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 643c570f65..4cbac009d8 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -535,12 +535,23 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
}
#if defined(ENABLE_PIXMAN_DRAWHELPERS)
+extern void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uchar *map,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *clip, bool useGammaCorrection);
+
void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *bitmap,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *, bool /*useGammaCorrection*/)
+ const QClipData *clip, bool useGammaCorrection)
{
+ if (clip || useGammaCorrection) {
+ qt_alphamapblit_quint16(rasterBuffer, x, y, color, bitmap, mapWidth, mapHeight, mapStride, clip, useGammaCorrection);
+ return;
+ }
+
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index fc4f2a9944..eb43453ddb 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -2621,7 +2621,7 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
return;
}
}
- } else if (d->deviceDepth == 32 && ((depth == 8 && s->penData.alphamapBlit) || (depth == 32 && s->penData.alphaRGBBlit))) {
+ } else if ((depth == 8 && s->penData.alphamapBlit) || (depth == 32 && s->penData.alphaRGBBlit)) {
// (A)RGB Alpha mask where the alpha component is not used.
if (!clip) {
int nx = qMax(0, rx);
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 74b961f042..083e68fcdb 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7570,7 +7570,6 @@ start_lengthVariant:
lineWidth = qMax<qreal>(0, r.width());
if(!wordwrap)
tf |= Qt::TextIncludeTrailingSpaces;
- textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
textLayout.beginLayout();
qreal leading = fm.leading();
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index aca59d0288..8067969f56 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -556,7 +556,6 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
}
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -692,7 +691,6 @@ QRect QFontMetrics::boundingRect(const QString &text) const
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
@@ -861,7 +859,6 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
@@ -1413,7 +1410,6 @@ qreal QFontMetricsF::width(const QString &text) const
int len = (pos != -1) ? pos : text.length();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
return layout.width(0, len).toReal();
}
@@ -1496,7 +1492,6 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
return QRectF();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, len);
return QRectF(gm.x.toReal(), gm.y.toReal(),
@@ -1668,7 +1663,6 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 55ef9f0d15..6aca660205 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -422,19 +422,53 @@ hb_unicode_funcs_t *hb_qt_get_unicode_funcs()
// Font routines
+#if HB_VERSION_ATLEAST(1, 1, 3)
static hb_bool_t
-_hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
- hb_codepoint_t unicode, hb_codepoint_t /*variation_selector*/,
- hb_codepoint_t *glyph,
- void * /*user_data*/)
+_hb_qt_get_font_h_extents(hb_font_t * /*font*/, void *font_data,
+ hb_font_extents_t *metrics,
+ void * /*user_data*/)
{
QFontEngine *fe = static_cast<QFontEngine *>(font_data);
Q_ASSERT(fe);
- *glyph = fe->glyphIndex(unicode);
+ metrics->ascender = fe->ascent().value();
+ metrics->descender = fe->descent().value();
+ metrics->line_gap = fe->leading().value();
return true;
}
+#endif
+
+#if HB_VERSION_ATLEAST(1, 2, 3)
+static hb_bool_t
+_hb_qt_font_get_nominal_glyph(hb_font_t * /*font*/, void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = static_cast<QFontEngine *>(font_data);
+ Q_ASSERT(fe);
+
+ *glyph = fe->glyphIndex(unicode);
+
+ return *glyph != 0;
+}
+#endif
+
+static hb_bool_t
+_hb_qt_font_get_variation_glyph(hb_font_t * /*font*/, void *font_data,
+ hb_codepoint_t unicode, hb_codepoint_t /*variation_selector*/,
+ hb_codepoint_t *glyph,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = static_cast<QFontEngine *>(font_data);
+ Q_ASSERT(fe);
+
+ // ### TODO add support for variation selectors
+ *glyph = fe->glyphIndex(unicode);
+
+ return *glyph != 0;
+}
static hb_position_t
_hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
@@ -456,15 +490,7 @@ _hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
return advance.value();
}
-static hb_position_t
-_hb_qt_font_get_glyph_v_advance(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*glyph*/,
- void * /*user_data*/)
-{
- qCritical("hb_qt_font_get_glyph_v_advance: vertical writing isn't supported!");
- return 0;
-}
-
+#if !HB_VERSION_ATLEAST(1, 1, 2)
static hb_bool_t
_hb_qt_font_get_glyph_h_origin(hb_font_t * /*font*/, void * /*font_data*/,
hb_codepoint_t /*glyph*/,
@@ -473,16 +499,7 @@ _hb_qt_font_get_glyph_h_origin(hb_font_t * /*font*/, void * /*font_data*/,
{
return true; // we always work in the horizontal coordinates
}
-
-static hb_bool_t
-_hb_qt_font_get_glyph_v_origin(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*glyph*/,
- hb_position_t * /*x*/, hb_position_t * /*y*/,
- void * /*user_data*/)
-{
- qCritical("hb_qt_get_glyph_v_origin: vertical writing isn't supported!");
- return false;
-}
+#endif
static hb_position_t
_hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
@@ -505,15 +522,6 @@ _hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
return advance.value();
}
-static hb_position_t
-_hb_qt_font_get_glyph_v_kerning(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*first_glyph*/, hb_codepoint_t /*second_glyph*/,
- void * /*user_data*/)
-{
- qCritical("hb_qt_get_glyph_v_kerning: vertical writing isn't supported!");
- return 0;
-}
-
static hb_bool_t
_hb_qt_font_get_glyph_extents(hb_font_t * /*font*/, void *font_data,
hb_codepoint_t glyph,
@@ -554,29 +562,6 @@ _hb_qt_font_get_glyph_contour_point(hb_font_t * /*font*/, void *font_data,
return false;
}
-static hb_bool_t
-_hb_qt_font_get_glyph_name(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*glyph*/,
- char *name, unsigned int size,
- void * /*user_data*/)
-{
- qCritical("hb_qt_font_get_glyph_name: not implemented!");
- if (size)
- *name = '\0';
- return false;
-}
-
-static hb_bool_t
-_hb_qt_font_get_glyph_from_name(hb_font_t * /*font*/, void * /*font_data*/,
- const char * /*name*/, int /*len*/,
- hb_codepoint_t *glyph,
- void * /*user_data*/)
-{
- qCritical("hb_qt_font_get_glyph_from_name: not implemented!");
- *glyph = 0;
- return false;
-}
-
static hb_user_data_key_t _useDesignMetricsKey;
@@ -595,17 +580,25 @@ struct _hb_qt_font_funcs_t {
_hb_qt_font_funcs_t()
{
funcs = hb_font_funcs_create();
- hb_font_funcs_set_glyph_func(funcs, _hb_qt_font_get_glyph, NULL, NULL);
+
+#if HB_VERSION_ATLEAST(1, 1, 3)
+ hb_font_funcs_set_font_h_extents_func(funcs, _hb_qt_get_font_h_extents, NULL, NULL);
+#endif
+#if HB_VERSION_ATLEAST(1, 2, 3)
+ hb_font_funcs_set_nominal_glyph_func(funcs, _hb_qt_font_get_nominal_glyph, NULL, NULL);
+ hb_font_funcs_set_variation_glyph_func(funcs, _hb_qt_font_get_variation_glyph, NULL, NULL);
+#else
+ hb_font_funcs_set_glyph_func(funcs, _hb_qt_font_get_variation_glyph, NULL, NULL);
+#endif
hb_font_funcs_set_glyph_h_advance_func(funcs, _hb_qt_font_get_glyph_h_advance, NULL, NULL);
- hb_font_funcs_set_glyph_v_advance_func(funcs, _hb_qt_font_get_glyph_v_advance, NULL, NULL);
+#if !HB_VERSION_ATLEAST(1, 1, 2)
hb_font_funcs_set_glyph_h_origin_func(funcs, _hb_qt_font_get_glyph_h_origin, NULL, NULL);
- hb_font_funcs_set_glyph_v_origin_func(funcs, _hb_qt_font_get_glyph_v_origin, NULL, NULL);
+#endif
hb_font_funcs_set_glyph_h_kerning_func(funcs, _hb_qt_font_get_glyph_h_kerning, NULL, NULL);
- hb_font_funcs_set_glyph_v_kerning_func(funcs, _hb_qt_font_get_glyph_v_kerning, NULL, NULL);
hb_font_funcs_set_glyph_extents_func(funcs, _hb_qt_font_get_glyph_extents, NULL, NULL);
hb_font_funcs_set_glyph_contour_point_func(funcs, _hb_qt_font_get_glyph_contour_point, NULL, NULL);
- hb_font_funcs_set_glyph_name_func(funcs, _hb_qt_font_get_glyph_name, NULL, NULL);
- hb_font_funcs_set_glyph_from_name_func(funcs, _hb_qt_font_get_glyph_from_name, NULL, NULL);
+
+ hb_font_funcs_make_immutable(funcs);
}
~_hb_qt_font_funcs_t()
{
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 67cafa53fe..f3ed8ef63a 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1165,6 +1165,20 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
hb_buffer_clear_contents(buffer);
hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16_t *>(string) + item_pos, item_length, 0, item_length);
+#if defined(Q_OS_DARWIN)
+ // ### temporary workaround for QTBUG-38113
+ // CoreText throws away the PDF token, while the OpenType backend will replace it with
+ // a zero-advance glyph. This becomes a real issue when PDF is the last character,
+ // since it gets treated like if it were a grapheme extender, so we
+ // temporarily replace it with some visible grapheme starter.
+ bool endsWithPDF = actualFontEngine->type() == QFontEngine::Mac && string[item_pos + item_length - 1] == 0x202c;
+ if (Q_UNLIKELY(endsWithPDF)) {
+ uint num_glyphs;
+ hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, &num_glyphs);
+ infos[num_glyphs - 1].codepoint = '.';
+ }
+#endif
+
hb_buffer_set_segment_properties(buffer, &props);
hb_buffer_guess_segment_properties(buffer);
@@ -1286,6 +1300,20 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
while (str_pos < item_length)
log_clusters[str_pos++] = last_glyph_pos;
+#if defined(Q_OS_DARWIN)
+ if (Q_UNLIKELY(endsWithPDF)) {
+ int last_glyph_idx = num_glyphs - 1;
+ g.glyphs[last_glyph_idx] = 0xffff;
+ g.advances[last_glyph_idx] = QFixed();
+ g.offsets[last_glyph_idx].x = QFixed();
+ g.offsets[last_glyph_idx].y = QFixed();
+ g.attributes[last_glyph_idx].clusterStart = true;
+ g.attributes[last_glyph_idx].dontPrint = true;
+
+ log_clusters[item_length - 1] = glyphs_shaped + last_glyph_idx;
+ }
+#endif
+
if (Q_UNLIKELY(engineIdx != 0)) {
for (quint32 i = 0; i < num_glyphs; ++i)
g.glyphs[i] |= (engineIdx << 24);