diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/accessible/qaccessible.cpp | 12 | ||||
-rw-r--r-- | src/gui/configure.json | 4 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 18 | ||||
-rw-r--r-- | src/gui/image/qimage_darwin.mm | 4 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qpnghandler.cpp | 6 | ||||
-rw-r--r-- | src/gui/kernel/qdrag.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qplatformdrag.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qplatformwindow.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qplatformwindow.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 67 | ||||
-rw-r--r-- | src/gui/kernel/qwindow_p.h | 1 | ||||
-rw-r--r-- | src/gui/opengl/qopenglfunctions.cpp | 4 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 459 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_mips_dsp.cpp | 15 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_mips_dsp_p.h | 12 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_neon.cpp | 13 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 1 | ||||
-rw-r--r-- | src/gui/text/qfontmetrics.cpp | 6 | ||||
-rw-r--r-- | src/gui/text/qharfbuzzng.cpp | 117 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 28 |
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); |