diff options
Diffstat (limited to 'src/gui')
118 files changed, 5986 insertions, 2675 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index fce92b9511..dc6933f9ff 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -443,10 +443,11 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QAccessibleInterface::~QAccessibleInterface() - - Destroys the object. + Destroys the QAccessibleInterface. */ +QAccessibleInterface::~QAccessibleInterface() +{ +} /*! \typedef QAccessible::Id @@ -461,12 +462,12 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_LIBRARY Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QAccessibleFactoryInterface_iid, QLatin1String("/accessible"))) +typedef QHash<QString, QAccessiblePlugin*> QAccessiblePluginsHash; +Q_GLOBAL_STATIC(QAccessiblePluginsHash, qAccessiblePlugins) #endif // FIXME turn this into one global static struct Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories) -typedef QHash<QString, QAccessiblePlugin*> QAccessiblePluginsHash; -Q_GLOBAL_STATIC(QAccessiblePluginsHash, qAccessiblePlugins) Q_GLOBAL_STATIC(QList<QAccessible::ActivationObserver *>, qAccessibleActivationObservers) QAccessible::UpdateHandler QAccessible::updateHandler = 0; @@ -608,6 +609,11 @@ QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectH \sa installActivationObserver() */ +QAccessible::ActivationObserver::~ActivationObserver() +{ + // must be empty until ### Qt 6 +} + /*! \internal @@ -1254,10 +1260,6 @@ QColor QAccessibleInterface::backgroundColor() const return QColor(); } -QAccessibleInterface::~QAccessibleInterface() -{ -} - /*! \fn QAccessibleTextInterface *QAccessibleInterface::textInterface() */ @@ -1329,9 +1331,13 @@ QAccessibleInterface::~QAccessibleInterface() the overload taking a \l QObject parameter as it might be cheaper. */ -/*! \fn QAccessibleEvent::~QAccessibleEvent() +/*! Destroys the event. */ +QAccessibleEvent::~QAccessibleEvent() +{ + // must be empty until ### Qt 6 +} /*! \fn QAccessible::Event QAccessibleEvent::type() const Returns the event type. @@ -1392,6 +1398,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const Returns the new value of the accessible object of this event. */ +/*! + \internal +*/ +QAccessibleValueChangeEvent::~QAccessibleValueChangeEvent() +{ + // must be empty until ### Qt 6 +} /*! \class QAccessibleStateChangeEvent @@ -1427,7 +1440,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const other hand tells about the change and has focused set to \c true since the focus state is changed from \c true to \c false. */ - +/*! + \internal +*/ +QAccessibleStateChangeEvent::~QAccessibleStateChangeEvent() +{ + // must be empty until ### Qt 6 +} /*! \class QAccessibleTableModelChangeEvent @@ -1484,6 +1503,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const /*! \fn void QAccessibleTableModelChangeEvent::setModelChangeType(ModelChangeType changeType) Sets the type of change to \a changeType. */ +/*! + \internal +*/ +QAccessibleTableModelChangeEvent::~QAccessibleTableModelChangeEvent() +{ + // must be empty until ### Qt 6 +} /*! @@ -1505,6 +1531,14 @@ QAccessible::Id QAccessibleEvent::uniqueId() const /*! \fn void QAccessibleTextCursorEvent::setCursorPosition(int position) Sets the cursor \a position for this event. */ +/*! + \internal +*/ +QAccessibleTextCursorEvent::~QAccessibleTextCursorEvent() +{ + // must be empty until ### Qt 6 +} + /*! \class QAccessibleTextInsertEvent @@ -1528,6 +1562,14 @@ QAccessible::Id QAccessibleEvent::uniqueId() const /*! \fn QString QAccessibleTextInsertEvent::textInserted() const Returns the text that has been inserted. */ +/*! + \internal +*/ +QAccessibleTextInsertEvent::~QAccessibleTextInsertEvent() +{ + // must be empty until ### Qt 6 +} + /*! \class QAccessibleTextRemoveEvent @@ -1552,6 +1594,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const /*! \fn QString QAccessibleTextRemoveEvent::textRemoved() const Returns the text that has been removed. */ +/*! + \internal +*/ +QAccessibleTextRemoveEvent::~QAccessibleTextRemoveEvent() +{ + // must be empty until ### Qt 6 +} /*! \class QAccessibleTextUpdateEvent @@ -1578,6 +1627,14 @@ QAccessible::Id QAccessibleEvent::uniqueId() const /*! \fn QString QAccessibleTextUpdateEvent::textRemoved() const Returns the removed text. */ +/*! + \internal +*/ +QAccessibleTextUpdateEvent::~QAccessibleTextUpdateEvent() +{ + // must be empty until ### Qt 6 +} + /*! \class QAccessibleTextSelectionEvent @@ -1601,6 +1658,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const /*! \fn void QAccessibleTextSelectionEvent::setSelection(int start, int end) Sets the selection for this event from position \a start to \a end. */ +/*! + \internal +*/ +QAccessibleTextSelectionEvent::~QAccessibleTextSelectionEvent() +{ + // must be empty until ### Qt 6 +} @@ -1839,9 +1903,12 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev) */ /*! - \fn QAccessibleTextInterface::~QAccessibleTextInterface() Destroys the QAccessibleTextInterface. */ +QAccessibleTextInterface::~QAccessibleTextInterface() +{ + // must be empty until ### Qt 6 +} /*! \fn void QAccessibleTextInterface::addSelection(int startOffset, int endOffset) @@ -2221,9 +2288,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun */ /*! - \fn QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface() Destroys the QAccessibleEditableTextInterface. */ +QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface() +{ + // must be empty until ### Qt 6 +} /*! \fn void QAccessibleEditableTextInterface::deleteText(int startOffset, int endOffset) @@ -2262,9 +2332,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun */ /*! - \fn QAccessibleValueInterface::~QAccessibleValueInterface() - Destructor. + Destroys the QAccessibleValueInterface. */ +QAccessibleValueInterface::~QAccessibleValueInterface() +{ + // must be empty until ### Qt 6 +} /*! \fn QVariant QAccessibleValueInterface::currentValue() const @@ -2323,6 +2396,14 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun */ /*! + Destroys the QAccessibleImageInterface. +*/ +QAccessibleImageInterface::~QAccessibleImageInterface() +{ + // must be empty until ### Qt 6 +} + +/*! \class QAccessibleTableCellInterface \inmodule QtGui \ingroup accessibility @@ -2334,9 +2415,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun */ /*! - \fn virtual QAccessibleTableCellInterface::~QAccessibleTableCellInterface() Destroys the QAccessibleTableCellInterface. */ +QAccessibleTableCellInterface::~QAccessibleTableCellInterface() +{ + // must be empty until ### Qt 6 +} /*! \fn virtual int QAccessibleTableCellInterface::columnExtent() const @@ -2390,9 +2474,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun */ /*! - \fn virtual QAccessibleTableInterface::~QAccessibleTableInterface() Destroys the QAccessibleTableInterface. */ +QAccessibleTableInterface::~QAccessibleTableInterface() +{ + // must be empty until ### Qt 6 +} /*! \fn virtual QAccessibleInterface *QAccessibleTableInterface::cellAt(int row, int column) const @@ -2543,9 +2630,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun */ /*! - \fn QAccessibleActionInterface::~QAccessibleActionInterface() Destroys the QAccessibleActionInterface. */ +QAccessibleActionInterface::~QAccessibleActionInterface() +{ + // must be empty until ### Qt 6 +} /*! \fn QStringList QAccessibleActionInterface::actionNames() const diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index bfe1e6c542..a40d7209c3 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -396,10 +396,10 @@ public: static UpdateHandler installUpdateHandler(UpdateHandler); static RootObjectHandler installRootObjectHandler(RootObjectHandler); - class ActivationObserver + class Q_GUI_EXPORT ActivationObserver { public: - virtual ~ActivationObserver() {} + virtual ~ActivationObserver(); virtual void accessibilityActiveChanged(bool active) = 0; }; static void installActivationObserver(ActivationObserver *); @@ -514,7 +514,7 @@ protected: class Q_GUI_EXPORT QAccessibleTextInterface { public: - virtual ~QAccessibleTextInterface() {} + virtual ~QAccessibleTextInterface(); // selection virtual void selection(int selectionIndex, int *startOffset, int *endOffset) const = 0; virtual int selectionCount() const = 0; @@ -547,7 +547,7 @@ public: class Q_GUI_EXPORT QAccessibleEditableTextInterface { public: - virtual ~QAccessibleEditableTextInterface() {} + virtual ~QAccessibleEditableTextInterface(); virtual void deleteText(int startOffset, int endOffset) = 0; virtual void insertText(int offset, const QString &text) = 0; @@ -557,8 +557,7 @@ public: class Q_GUI_EXPORT QAccessibleValueInterface { public: - - virtual ~QAccessibleValueInterface() {} + virtual ~QAccessibleValueInterface(); virtual QVariant currentValue() const = 0; virtual void setCurrentValue(const QVariant &value) = 0; @@ -570,7 +569,7 @@ public: class Q_GUI_EXPORT QAccessibleTableCellInterface { public: - virtual ~QAccessibleTableCellInterface() {} + virtual ~QAccessibleTableCellInterface(); virtual bool isSelected() const = 0; @@ -587,7 +586,7 @@ public: class Q_GUI_EXPORT QAccessibleTableInterface { public: - virtual ~QAccessibleTableInterface() {} + virtual ~QAccessibleTableInterface(); virtual QAccessibleInterface *caption() const = 0; virtual QAccessibleInterface *summary() const = 0; @@ -622,7 +621,7 @@ class Q_GUI_EXPORT QAccessibleActionInterface { Q_DECLARE_TR_FUNCTIONS(QAccessibleActionInterface) public: - virtual ~QAccessibleActionInterface() {} + virtual ~QAccessibleActionInterface(); virtual QStringList actionNames() const = 0; virtual QString localizedActionName(const QString &name) const; @@ -647,7 +646,7 @@ public: class Q_GUI_EXPORT QAccessibleImageInterface { public: - virtual ~QAccessibleImageInterface() {} + virtual ~QAccessibleImageInterface(); virtual QString imageDescription() const = 0; virtual QSize imageSize() const = 0; @@ -691,8 +690,7 @@ public: m_uniqueId = QAccessible::uniqueId(iface); } - virtual ~QAccessibleEvent() - {} + virtual ~QAccessibleEvent(); QAccessible::Event type() const { return m_type; } QObject *object() const { return m_object; } @@ -726,6 +724,7 @@ public: { m_type = QAccessible::StateChanged; } + ~QAccessibleStateChangeEvent(); QAccessible::State changedStates() const { return m_changedStates; @@ -752,6 +751,8 @@ public: m_type = QAccessible::TextCaretMoved; } + ~QAccessibleTextCursorEvent(); + void setCursorPosition(int position) { m_cursorPosition = position; } int cursorPosition() const { return m_cursorPosition; } @@ -776,6 +777,8 @@ public: m_type = QAccessible::TextSelectionChanged; } + ~QAccessibleTextSelectionEvent(); + void setSelection(int start, int end) { m_selectionStart = start; m_selectionEnd = end; @@ -805,6 +808,8 @@ public: m_type = QAccessible::TextInserted; } + ~QAccessibleTextInsertEvent(); + QString textInserted() const { return m_text; } @@ -833,6 +838,8 @@ public: m_type = QAccessible::TextRemoved; } + ~QAccessibleTextRemoveEvent(); + QString textRemoved() const { return m_text; } @@ -860,6 +867,9 @@ public: { m_type = QAccessible::TextUpdated; } + + ~QAccessibleTextUpdateEvent(); + QString textRemoved() const { return m_oldText; } @@ -892,6 +902,8 @@ public: m_type = QAccessible::ValueChanged; } + ~QAccessibleValueChangeEvent(); + void setValue(const QVariant & val) { m_value= val; } QVariant value() const { return m_value; } @@ -926,6 +938,8 @@ public: m_type = QAccessible::TableModelChanged; } + ~QAccessibleTableModelChangeEvent(); + void setModelChangeType(ModelChangeType changeType) { m_modelChangeType = changeType; } ModelChangeType modelChangeType() const { return m_modelChangeType; } diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index cafc966fbb..f115707500 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -362,7 +362,7 @@ static inline int origIcoDepth(const QImage &image) return s.isEmpty() ? 32 : s.toInt(); } -static inline int findBySize(const QList<QImage> &images, const QSize &size) +static inline int findBySize(const QVector<QImage> &images, const QSize &size) { for (int i = 0; i < images.size(); ++i) { if (images.at(i).size() == size) @@ -426,7 +426,7 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco // these files may contain low-resolution images. As this information is lost, // ICOReader sets the original format as an image text key value. Read all matching // images into a list trying to find the highest quality per size. - QList<QImage> icoImages; + QVector<QImage> icoImages; while (imageReader.read(&image)) { if (ignoreSize || image.size() == size) { const int position = findBySize(icoImages, image.size()); diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index fa14c84e83..d3553f28be 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -42,7 +42,6 @@ #include <QtGui/QIconEngine> #include <QtGui/QPalette> #include <QtCore/QList> -#include <QtCore/QHash> #include <QtCore/QDir> #include <QtCore/QSettings> #include <QtGui/QPainter> diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index cd0cbf7f49..3c192a237e 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -476,6 +476,10 @@ bool QImageData::checkForAlphaPixels() const \snippet code/src_gui_image_qimage.cpp 1 \endtable + For images with more than 8-bit per color-channel. The methods + setPixelColor() and pixelColor() can be used to set and get + with QColor values. + QImage also provide the scanLine() function which returns a pointer to the pixel data at the scanline with the given index, and the bits() function which returns a pointer to the first pixel @@ -1769,11 +1773,11 @@ void QImage::fill(const QColor &color) break; case QImage::Format_BGR30: case QImage::Format_A2BGR30_Premultiplied: - fill(qConvertArgb32ToA2rgb30<PixelOrderBGR>(color.rgba())); + fill(qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64())); break; case QImage::Format_RGB30: case QImage::Format_A2RGB30_Premultiplied: - fill(qConvertArgb32ToA2rgb30<PixelOrderRGB>(color.rgba())); + fill(qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64())); break; case QImage::Format_RGB16: fill((uint) qConvertRgb32To16(color.rgba())); @@ -2190,9 +2194,10 @@ int QImage::pixelIndex(int x, int y) const If the \a position is not valid, the results are undefined. \warning This function is expensive when used for massive pixel - manipulations. + manipulations. Use constBits() or constScanLine() when many + pixels needs to be read. - \sa setPixel(), valid(), {QImage#Pixel Manipulation}{Pixel + \sa setPixel(), valid(), constBits(), constScanLine(), {QImage#Pixel Manipulation}{Pixel Manipulation} */ @@ -2242,25 +2247,23 @@ QRgb QImage::pixel(int x, int y) const return *layout->convertToARGB32PM(&result, ptr, 1, layout, 0); } - /*! \fn void QImage::setPixel(const QPoint &position, uint index_or_rgb) Sets the pixel index or color at the given \a position to \a index_or_rgb. - If the image's format is either monochrome or 8-bit, the given \a + If the image's format is either monochrome or paletted, the given \a index_or_rgb value must be an index in the image's color table, otherwise the parameter must be a QRgb value. If \a position is not a valid coordinate pair in the image, or if \a index_or_rgb >= colorCount() in the case of monochrome and - 8-bit images, the result is undefined. + paletted images, the result is undefined. \warning This function is expensive due to the call of the internal \c{detach()} function called within; if performance is a concern, we - recommend the use of \l{QImage::}{scanLine()} to access pixel data - directly. + recommend the use of scanLine() or bits() to access pixel data directly. \sa pixel(), {QImage#Pixel Manipulation}{Pixel Manipulation} */ @@ -2348,6 +2351,102 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) } /*! + \fn QColor QImage::pixelColor(const QPoint &position) const + \since 5.6 + + Returns the color of the pixel at the given \a position as a QColor. + + If the \a position is not valid, an invalid QColor is returned. + + \warning This function is expensive when used for massive pixel + manipulations. Use constBits() or constScanLine() when many + pixels needs to be read. + + \sa setPixel(), valid(), constBits(), constScanLine(), {QImage#Pixel Manipulation}{Pixel + Manipulation} +*/ + +/*! + \overload + \since 5.6 + + Returns the color of the pixel at coordinates (\a x, \a y) as a QColor. +*/ +QColor QImage::pixelColor(int x, int y) const +{ + if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) { + qWarning("QImage::pixelColor: coordinate (%d,%d) out of range", x, y); + return QColor(); + } + + const uchar * s = constScanLine(y); + switch (d->format) { + case Format_BGR30: + case Format_A2BGR30_Premultiplied: + return QColor(qConvertA2rgb30ToRgb64<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x])); + case Format_RGB30: + case Format_A2RGB30_Premultiplied: + return QColor(qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x])); + default: + return QColor(pixel(x, y)); + } +} + +/*! + \fn void QImage::setPixelColor(const QPoint &position, const QColor &color) + \since 5.6 + + Sets the color at the given \a position to \a color. + + If \a position is not a valid coordinate pair in the image, or + the image's format is either monochrome or paletted, the result is undefined. + + \warning This function is expensive due to the call of the internal + \c{detach()} function called within; if performance is a concern, we + recommend the use of scanLine() or bits() to access pixel data directly. + + \sa pixel(), bits(), scanLine(), {QImage#Pixel Manipulation}{Pixel Manipulation} +*/ + +/*! + \overload + \since 5.6 + + Sets the pixel color at (\a x, \a y) to \a color. +*/ +void QImage::setPixelColor(int x, int y, const QColor &color) +{ + if (!d || x < 0 || x >= width() || y < 0 || y >= height() || !color.isValid()) { + qWarning("QImage::setPixelColor: coordinate (%d,%d) out of range", x, y); + return; + } + // detach is called from within scanLine + uchar * s = scanLine(y); + switch (d->format) { + case Format_Mono: + case Format_MonoLSB: + case Format_Indexed8: + qWarning("QImage::setPixelColor: called on monochrome or indexed format"); + return; + case Format_BGR30: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64()) | 0xc0000000; + return; + case Format_A2BGR30_Premultiplied: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64()); + return; + case Format_RGB30: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64()) | 0xc0000000; + return; + case Format_A2RGB30_Premultiplied: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64()); + return; + default: + setPixel(x, y, color.rgba()); + return; + } +} + +/*! Returns \c true if all the colors in the image are shades of gray (i.e. their red, green and blue components are equal); otherwise false. diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 26057f366c..26707021ea 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -34,10 +34,11 @@ #ifndef QIMAGE_H #define QIMAGE_H -#include <QtGui/qtransform.h> -#include <QtGui/qpaintdevice.h> +#include <QtGui/qcolor.h> #include <QtGui/qrgb.h> +#include <QtGui/qpaintdevice.h> #include <QtGui/qpixelformat.h> +#include <QtGui/qtransform.h> #include <QtCore/qbytearray.h> #include <QtCore/qrect.h> #include <QtCore/qstring.h> @@ -220,6 +221,12 @@ public: void setPixel(int x, int y, uint index_or_rgb); void setPixel(const QPoint &pt, uint index_or_rgb); + QColor pixelColor(int x, int y) const; + QColor pixelColor(const QPoint &pt) const; + + void setPixelColor(int x, int y, const QColor &c); + void setPixelColor(const QPoint &pt, const QColor &c); + QVector<QRgb> colorTable() const; #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void setColorTable(const QVector<QRgb> &colors); @@ -352,6 +359,8 @@ inline bool QImage::valid(const QPoint &pt) const { return valid(pt.x(), pt.y()) inline int QImage::pixelIndex(const QPoint &pt) const { return pixelIndex(pt.x(), pt.y());} inline QRgb QImage::pixel(const QPoint &pt) const { return pixel(pt.x(), pt.y()); } inline void QImage::setPixel(const QPoint &pt, uint index_or_rgb) { setPixel(pt.x(), pt.y(), index_or_rgb); } +inline QColor QImage::pixelColor(const QPoint &pt) const { return pixelColor(pt.x(), pt.y()); } +inline void QImage::setPixelColor(const QPoint &pt, const QColor &c) { setPixelColor(pt.x(), pt.y(), c); } #if QT_DEPRECATED_SINCE(5, 0) diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index ba79bf40e5..83ec91bb40 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1203,6 +1203,39 @@ bool QImageReader::autoTransform() const } /*! + \since 5.6 + + This is an image format specific function that forces images with + gamma information to be gamma corrected to \a gamma. For image formats + that do not support gamma correction, this value is ignored. + + To gamma correct to a standard PC color-space, set gamma to \c 1/2.2. + + \sa gamma() +*/ +void QImageReader::setGamma(float gamma) +{ + if (d->initHandler() && d->handler->supportsOption(QImageIOHandler::Gamma)) + d->handler->setOption(QImageIOHandler::Gamma, gamma); +} + +/*! + \since 5.6 + + Returns the gamma level of the decoded image. If setGamma() has been + called and gamma correction is supported it will return the gamma set. + If gamma level is not supported by the image format, \c 0.0 is returned. + + \sa setGamma() +*/ +float QImageReader::gamma() const +{ + if (d->initHandler() && d->handler->supportsOption(QImageIOHandler::Gamma)) + return d->handler->option(QImageIOHandler::Gamma).toFloat(); + return 0.0; +} + +/*! Returns \c true if an image can be read for the device (i.e., the image format is supported, and the device seems to contain valid data); otherwise returns \c false. diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h index 27a29bed49..6745c55b97 100644 --- a/src/gui/image/qimagereader.h +++ b/src/gui/image/qimagereader.h @@ -110,6 +110,9 @@ public: void setAutoTransform(bool enabled); bool autoTransform() const; + void setGamma(float gamma); + float gamma() const; + QByteArray subType() const; QList<QByteArray> supportedSubTypes() const; diff --git a/src/gui/image/qpaintengine_pic.cpp b/src/gui/image/qpaintengine_pic.cpp index 9ab1e2c30b..47480ebbae 100644 --- a/src/gui/image/qpaintengine_pic.cpp +++ b/src/gui/image/qpaintengine_pic.cpp @@ -398,6 +398,7 @@ void QPicturePaintEngine::drawPolygon(const QPointF *points, int numPoints, Poly int pos; QPolygonF polygon; + polygon.reserve(numPoints); for (int i=0; i<numPoints; ++i) polygon << points[i]; diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index b63be19153..4a1e65b20a 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -1216,7 +1216,9 @@ QList<QByteArray> QPicture::inputFormats() static QStringList qToStringList(const QList<QByteArray> &arr) { QStringList list; - for (int i = 0; i < arr.count(); ++i) + const int count = arr.count(); + list.reserve(count); + for (int i = 0; i < count; ++i) list.append(QString::fromLatin1(arr.at(i))); return list; } diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h index 56e6e1249c..a414a122f1 100644 --- a/src/gui/image/qpicture_p.h +++ b/src/gui/image/qpicture_p.h @@ -48,6 +48,7 @@ #include "QtCore/qatomic.h" #include "QtCore/qbuffer.h" #include "QtCore/qobjectdefs.h" +#include "QtCore/qvector.h" #include "QtGui/qpicture.h" #include "QtGui/qpixmap.h" #include "QtGui/qpen.h" @@ -150,8 +151,8 @@ public: QRect override_rect; QScopedPointer<QPaintEngine> paintEngine; bool in_memory_only; - QList<QImage> image_list; - QList<QPixmap> pixmap_list; + QVector<QImage> image_list; + QVector<QPixmap> pixmap_list; QList<QBrush> brush_list; QList<QPen> pen_list; }; diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index f9c362e194..0fefa1f7ea 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -138,6 +138,24 @@ bool QPixmapCache::Key::operator ==(const Key &key) const */ /*! + \fn QPixmapCache::Key::Key(Key &&) + \internal + \since 5.6 +*/ + +/*! + \fn QPixmapCache::Key &QPixmapCache::Key::operator=(Key &&) + \internal + \since 5.6 +*/ + +/*! + \fn void QPixmapCache::Key::swap(Key &) + \internal + \since 5.6 +*/ + +/*! \internal */ QPixmapCache::Key &QPixmapCache::Key::operator =(const Key &other) @@ -179,7 +197,6 @@ public: static QPixmapCache::KeyData* getKeyData(QPixmapCache::Key *key); - QList< QPair<QString,QPixmap> > allPixmaps() const; bool flushDetachedPixmaps(bool nt); private: @@ -423,20 +440,6 @@ QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key) return key->d; } -QList< QPair<QString,QPixmap> > QPMCache::allPixmaps() const -{ - QList< QPair<QString,QPixmap> > r; - QHash<QString, QPixmapCache::Key>::const_iterator it = cacheKeys.begin(); - while (it != cacheKeys.end()) { - QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(it.value()); - if (ptr) - r.append(QPair<QString,QPixmap>(it.key(),*ptr)); - ++it; - } - return r; -} - - Q_GLOBAL_STATIC(QPMCache, pm_cache) int Q_AUTOTEST_EXPORT q_QPixmapCache_keyHashSize() @@ -656,9 +659,4 @@ int QPixmapCache::totalUsed() return (pm_cache()->totalCost()+1023) / 1024; } -QList< QPair<QString,QPixmap> > QPixmapCache::allPixmaps() -{ - return pm_cache()->allPixmaps(); -} - QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h index 345389e987..03311345a2 100644 --- a/src/gui/image/qpixmapcache.h +++ b/src/gui/image/qpixmapcache.h @@ -36,10 +36,6 @@ #include <QtGui/qpixmap.h> -#ifdef Q_TEST_QPIXMAPCACHE -#include <QtCore/qpair.h> -#endif - QT_BEGIN_NAMESPACE @@ -52,12 +48,18 @@ public: public: Key(); Key(const Key &other); +#ifdef Q_COMPILER_RVALUE_REFS + Key(Key &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Q_NULLPTR; } + Key &operator =(Key &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif ~Key(); bool operator ==(const Key &key) const; inline bool operator !=(const Key &key) const { return !operator==(key); } Key &operator =(const Key &other); + void swap(Key &other) Q_DECL_NOTHROW { qSwap(d, other.d); } + private: KeyData *d; friend class QPMCache; @@ -80,7 +82,6 @@ public: #ifdef Q_TEST_QPIXMAPCACHE static void flushDetachedPixmaps(); static int totalUsed(); - static QList< QPair<QString,QPixmap> > allPixmaps(); #endif }; diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 7fbd24787e..776a61d8fe 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -108,10 +108,11 @@ public: }; QPngHandlerPrivate(QPngHandler *qq) - : gamma(0.0), quality(2), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq) + : gamma(0.0), fileGamma(0.0), quality(2), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq) { } float gamma; + float fileGamma; int quality; QString description; QSize scaledSize; @@ -234,13 +235,10 @@ void CALLBACK_CALL_TYPE qpiw_flush_fn(png_structp /* png_ptr */) } static -void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0) +void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0, float file_gamma=0.0) { - if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { - double file_gamma; - png_get_gAMA(png_ptr, info_ptr, &file_gamma); - png_set_gamma(png_ptr, screen_gamma, file_gamma); - } + if (screen_gamma != 0.0 && file_gamma != 0.0) + png_set_gamma(png_ptr, 1.0f / screen_gamma, file_gamma); png_uint_32 width; png_uint_32 height; @@ -557,6 +555,12 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader() readPngTexts(info_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { + double file_gamma = 0.0; + png_get_gAMA(png_ptr, info_ptr, &file_gamma); + fileGamma = file_gamma; + } + state = ReadHeader; return true; } @@ -580,7 +584,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) } bool doScaledRead = false; - setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma); + setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma); if (outImage->isNull()) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); @@ -1063,7 +1067,7 @@ QVariant QPngHandler::option(ImageOption option) const return QVariant(); if (option == Gamma) - return d->gamma; + return d->gamma == 0.0 ? d->fileGamma : d->gamma; else if (option == Quality) return d->quality; else if (option == Description) diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp index 8d848b662f..c5006d88ed 100644 --- a/src/gui/itemmodels/qstandarditemmodel.cpp +++ b/src/gui/itemmodels/qstandarditemmodel.cpp @@ -1224,7 +1224,7 @@ void QStandardItem::setSelectable(bool selectable) The item delegate will render a checkable item with a check box next to the item's text. - \sa isCheckable(), setCheckState(), setTristate() + \sa isCheckable(), setCheckState(), setUserTristate(), setAutoTristate() */ void QStandardItem::setCheckable(bool checkable) { @@ -1244,34 +1244,87 @@ void QStandardItem::setCheckable(bool checkable) The default value is false. - \sa setCheckable(), checkState(), isTristate() + \sa setCheckable(), checkState(), isUserTristate(), isAutoTristate() */ /*! - Sets whether the item is tristate. If \a tristate is true, the - item is checkable with three separate states; otherwise, the item - is checkable with two states. (Note that this also requires that - the item is checkable; see isCheckable().) + \fn void QStandardItem::setTristate(bool tristate) + \obsolete - \sa isTristate(), setCheckable(), setCheckState() + Use QStandardItem::setAutoTristate(bool tristate) instead. + For a tristate checkbox that the user can change between all three + states, use QStandardItem::setUserTristate(bool tristate) instead. */ -void QStandardItem::setTristate(bool tristate) + +/*! + \fn void QStandardItem::isTristate() const + \obsolete + + Use QStandardItem::isAutoTristate() instead. + For a tristate checkbox that the user can change between all three + states, use QStandardItem::isUserTristate() instead. +*/ + +/*! + Sets whether the item is tristate and controlled by QTreeWidget. + This enables automatic management of the state of parent items in QTreeWidget + (checked if all children are checked, unchecked if all children are unchecked, + or partially checked if only some children are checked). + + \since 5.6 + \sa isAutoTristate(), setCheckable(), setCheckState() +*/ +void QStandardItem::setAutoTristate(bool tristate) { Q_D(QStandardItem); - d->changeFlags(tristate, Qt::ItemIsTristate); + d->changeFlags(tristate, Qt::ItemIsAutoTristate); } /*! - \fn bool QStandardItem::isTristate() const + \fn bool QStandardItem::isAutoTristate() const + + Returns whether the item is tristate and is controlled by QTreeWidget. + + The default value is false. + + \since 5.6 + \sa setAutoTristate(), isCheckable(), checkState() +*/ + +/*! + Sets whether the item is tristate and controlled by the user. + If \a tristate is true, the user can cycle through three separate states; + otherwise, the item is checkable with two states. + (Note that this also requires that the item is checkable; see isCheckable().) + + \since 5.6 + \sa isUserTristate(), setCheckable(), setCheckState() +*/ +void QStandardItem::setUserTristate(bool tristate) +{ + Q_D(QStandardItem); + d->changeFlags(tristate, Qt::ItemIsUserTristate); +} + +/*! + \fn bool QStandardItem::isUserTristate() const + \since 5.6 Returns whether the item is tristate; that is, if it's checkable with three - separate states. + separate states and the user can cycle through all three states. The default value is false. - \sa setTristate(), isCheckable(), checkState() + \sa setUserTristate(), isCheckable(), checkState() */ +#if QT_DEPRECATED_SINCE(5, 6) +void QStandardItem::setTristate(bool tristate) +{ + setAutoTristate(tristate); +} +#endif + #ifndef QT_NO_DRAGANDDROP /*! @@ -1750,6 +1803,7 @@ QList<QStandardItem*> QStandardItem::takeRow(int row) int index = d->childIndex(row, 0); // Will return -1 if there are no columns if (index != -1) { int col_count = d->columnCount(); + items.reserve(col_count); for (int column = 0; column < col_count; ++column) { QStandardItem *ch = d->children.at(index + column); if (ch) @@ -2467,7 +2521,9 @@ QList<QStandardItem*> QStandardItemModel::findItems(const QString &text, QModelIndexList indexes = match(index(0, column, QModelIndex()), Qt::DisplayRole, text, -1, flags); QList<QStandardItem*> items; - for (int i = 0; i < indexes.size(); ++i) + const int numIndexes = indexes.size(); + items.reserve(numIndexes); + for (int i = 0; i < numIndexes; ++i) items.append(itemFromIndex(indexes.at(i))); return items; } diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h index 3dd613f907..44156d1907 100644 --- a/src/gui/itemmodels/qstandarditemmodel.h +++ b/src/gui/itemmodels/qstandarditemmodel.h @@ -158,10 +158,20 @@ public: } void setCheckable(bool checkable); - inline bool isTristate() const { - return (flags() & Qt::ItemIsTristate) != 0; + inline bool isAutoTristate() const { + return (flags() & Qt::ItemIsAutoTristate) != 0; } - void setTristate(bool tristate); + void setAutoTristate(bool tristate); + + inline bool isUserTristate() const { + return (flags() & Qt::ItemIsUserTristate) != 0; + } + void setUserTristate(bool tristate); + +#if QT_DEPRECATED_SINCE(5, 6) + QT_DEPRECATED bool isTristate() const { return isAutoTristate(); } + QT_DEPRECATED void setTristate(bool tristate); +#endif #ifndef QT_NO_DRAGANDDROP inline bool isDragEnabled() const { diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index 3ce8ab95ec..b05da1bfd0 100644 --- a/src/gui/kernel/qdnd.cpp +++ b/src/gui/kernel/qdnd.cpp @@ -147,7 +147,9 @@ static QStringList imageReadMimeFormats() { QStringList formats; QList<QByteArray> imageFormats = QImageReader::supportedImageFormats(); - for (int i = 0; i < imageFormats.size(); ++i) { + const int numImageFormats = imageFormats.size(); + formats.reserve(numImageFormats); + for (int i = 0; i < numImageFormats; ++i) { QString format = QLatin1String("image/"); format += QString::fromLatin1(imageFormats.at(i).toLower()); formats.append(format); @@ -166,7 +168,9 @@ static QStringList imageWriteMimeFormats() { QStringList formats; QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats(); - for (int i = 0; i < imageFormats.size(); ++i) { + const int numImageFormats = imageFormats.size(); + formats.reserve(numImageFormats); + for (int i = 0; i < numImageFormats; ++i) { QString format = QLatin1String("image/"); format += QString::fromLatin1(imageFormats.at(i).toLower()); formats.append(format); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 98fb0f1f20..adbaa5ff86 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -263,6 +263,36 @@ QMouseEvent::QMouseEvent(Type type, const QPointF &localPos, const QPointF &wind {} /*! + \since 5.6 + + Constructs a mouse event object. + + The \a type parameter must be QEvent::MouseButtonPress, + QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick, + or QEvent::MouseMove. + + The points \a localPos, \a windowPos and \a screenPos specify the + mouse cursor's position relative to the receiving widget or item, + window, and screen, respectively. + + The \a button that caused the event is given as a value from the + \l Qt::MouseButton enum. If the event \a type is \l MouseMove, + the appropriate button for this event is Qt::NoButton. \a buttons + is the state of all buttons at the time of the event, \a modifiers + is the state of all keyboard modifiers. + + The source of the event is specified by \a source. + +*/ +QMouseEvent::QMouseEvent(QEvent::Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos, + Qt::MouseButton button, Qt::MouseButtons buttons, + Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source) + : QInputEvent(type, modifiers), l(localPos), w(windowPos), s(screenPos), b(button), mouseState(buttons), caps(0) +{ + QGuiApplicationPrivate::setMouseEventSource(this, source); +} + +/*! \internal */ QMouseEvent::~QMouseEvent() @@ -1941,6 +1971,11 @@ QInputMethodEvent::QInputMethodEvent(const QInputMethodEvent &other) { } +QInputMethodEvent::~QInputMethodEvent() +{ + // must be empty until ### Qt 6 +} + /*! Sets the commit string to \a commitString. diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index a1f32026ac..dd7b35e2bb 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -106,6 +106,9 @@ public: QMouseEvent(Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); + QMouseEvent(Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos, + Qt::MouseButton button, Qt::MouseButtons buttons, + Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source); ~QMouseEvent(); #ifndef QT_NO_INTEGER_EVENT_COORDINATES @@ -528,6 +531,8 @@ public: }; QInputMethodEvent(); QInputMethodEvent(const QString &preeditText, const QList<Attribute> &attributes); + ~QInputMethodEvent(); + void setCommitString(const QString &commitString, int replaceFrom = 0, int replaceLength = 0); inline const QList<Attribute> &attributes() const { return attrs; } inline const QString &preeditString() const { return preedit; } diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 6aa1d26c66..b56a9da255 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1329,6 +1329,9 @@ void QGuiApplicationPrivate::init() #endif #ifndef QT_NO_LIBRARY + if (qEnvironmentVariableIntValue("QT_LOAD_TESTABILITY") > 0) + loadTestability = true; + if (loadTestability) { QLibrary testLib(QStringLiteral("qttestability")); if (testLib.load()) { @@ -1343,6 +1346,8 @@ void QGuiApplicationPrivate::init() qCritical() << "Library qttestability load failed:" << testLib.errorString(); } } +#else + Q_UNUSED(loadTestability); #endif // QT_NO_LIBRARY } @@ -1692,12 +1697,14 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo // A mouse event should not change both position and buttons at the same time. Instead we // should first send a move event followed by a button changed event. Since this is not the case // with the current event, we split it in two. - QWindowSystemInterfacePrivate::MouseEvent *mouseButtonEvent = new QWindowSystemInterfacePrivate::MouseEvent( + QWindowSystemInterfacePrivate::MouseEvent mouseButtonEvent( e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers); if (e->flags & QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic) - mouseButtonEvent->flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; - QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(mouseButtonEvent); - stateChange = Qt::NoButton; + mouseButtonEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; + e->buttons = buttons; + processMouseEvent(e); + processMouseEvent(&mouseButtonEvent); + return; } QWindow *window = e->window.data(); @@ -1766,9 +1773,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo if (!window) return; - QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers); + QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers, e->source); ev.setTimestamp(e->timestamp); - setMouseEventSource(&ev, e->source); #ifndef QT_NO_CURSOR if (!e->synthetic()) { if (const QScreen *screen = window->screen()) @@ -1827,9 +1833,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo if (!e->window.isNull() || e->nullWindow()) { // QTBUG-36364, check if window closed in response to press const QEvent::Type doubleClickType = frameStrut ? QEvent::NonClientAreaMouseButtonDblClick : QEvent::MouseButtonDblClick; QMouseEvent dblClickEvent(doubleClickType, localPoint, localPoint, globalPoint, - button, buttons, e->modifiers); + button, buttons, e->modifiers, e->source); dblClickEvent.setTimestamp(e->timestamp); - setMouseEventSource(&dblClickEvent, e->source); QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent); } } diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h index 20dcbbc139..34003cdf41 100644 --- a/src/gui/kernel/qkeymapper_p.h +++ b/src/gui/kernel/qkeymapper_p.h @@ -50,7 +50,6 @@ #include <qlist.h> #include <qlocale.h> #include <qevent.h> -#include <qhash.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 5bf22b9394..9dc06138a6 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -39,6 +39,7 @@ #ifndef QT_NO_SHORTCUT #include "qdebug.h" +#include <QtCore/qhashfunctions.h> #ifndef QT_NO_REGEXP # include "qregexp.h" #endif @@ -1100,7 +1101,7 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence int i = 0; int lastI = 0; while ((i = sl.indexOf(QLatin1Char('+'), i + 1)) != -1) { - const QString sub = sl.mid(lastI, i - lastI + 1); + const QStringRef sub = sl.midRef(lastI, i - lastI + 1); // If we get here the shortcuts contains at least one '+'. We break up // along the following strategy: // Meta+Ctrl++ ( "Meta+", "Ctrl+", "+" ) @@ -1409,6 +1410,16 @@ bool QKeySequence::operator==(const QKeySequence &other) const d->key[3] == other.d->key[3]); } +/*! + \since 5.6 + + Calculates the hash value of \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QKeySequence &key, uint seed) Q_DECL_NOTHROW +{ + return qHashRange(key.d->key, key.d->key + QKeySequencePrivate::MaxKeyCount, seed); +} /*! Provides an arbitrary comparison of this key sequence and @@ -1523,6 +1534,7 @@ QList<QKeySequence> QKeySequence::listFromString(const QString &str, SequenceFor QList<QKeySequence> result; QStringList strings = str.split(QLatin1String("; ")); + result.reserve(strings.count()); foreach (const QString &string, strings) { result << fromString(string, format); } @@ -1565,15 +1577,14 @@ QString QKeySequence::listToString(const QList<QKeySequence> &list, SequenceForm */ QDataStream &operator<<(QDataStream &s, const QKeySequence &keysequence) { - QList<quint32> list; - list << keysequence.d->key[0]; - - if (s.version() >= 5 && keysequence.count() > 1) { - list << keysequence.d->key[1]; - list << keysequence.d->key[2]; - list << keysequence.d->key[3]; + Q_STATIC_ASSERT_X(QKeySequencePrivate::MaxKeyCount == 4, "Forgot to adapt QDataStream &operator<<(QDataStream &s, const QKeySequence &keysequence) to new QKeySequence::MaxKeyCount"); + const bool extended = s.version() >= 5 && keysequence.count() > 1; + s << quint32(extended ? 4 : 1) << quint32(keysequence.d->key[0]); + if (extended) { + s << quint32(keysequence.d->key[1]) + << quint32(keysequence.d->key[2]) + << quint32(keysequence.d->key[3]); } - s << list; return s; } diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index cd7af5718f..d6171c86f2 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -43,11 +43,12 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_SHORTCUT +class QKeySequence; + /***************************************************************************** QKeySequence stream functions *****************************************************************************/ #ifndef QT_NO_DATASTREAM -class QKeySequence; Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &out, QKeySequence &ks); #endif @@ -59,6 +60,8 @@ void qt_set_sequence_auto_mnemonic(bool b); class QVariant; class QKeySequencePrivate; +Q_GUI_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QKeySequence &key, uint seed = 0) Q_DECL_NOTHROW; + class Q_GUI_EXPORT QKeySequence { Q_GADGET @@ -177,10 +180,10 @@ public: int operator[](uint i) const; QKeySequence &operator=(const QKeySequence &other); #ifdef Q_COMPILER_RVALUE_REFS - inline QKeySequence &operator=(QKeySequence &&other) - { qSwap(d, other.d); return *this; } + QKeySequence &operator=(QKeySequence &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif - inline void swap(QKeySequence &other) { qSwap(d, other.d); } + void swap(QKeySequence &other) Q_DECL_NOTHROW { qSwap(d, other.d); } + bool operator==(const QKeySequence &other) const; inline bool operator!= (const QKeySequence &other) const { return !(*this == other); } @@ -204,6 +207,7 @@ private: friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks); friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QKeySequence &ks); + friend Q_GUI_EXPORT uint qHash(const QKeySequence &key, uint seed) Q_DECL_NOTHROW; friend class QShortcutMap; friend class QShortcut; diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 56a3729a4a..7ca1786019 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -226,7 +226,7 @@ public: QOpenGLContext *context; }; -static QThreadStorage<QGuiGLThreadContext *> qwindow_context_storage; +Q_GLOBAL_STATIC(QThreadStorage<QGuiGLThreadContext *>, qwindow_context_storage); static QOpenGLContext *global_share_context = 0; #ifndef QT_NO_DEBUG @@ -336,14 +336,14 @@ QOpenGLContext *qt_gl_global_share_context() */ QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context) { - QGuiGLThreadContext *threadContext = qwindow_context_storage.localData(); + QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData(); if (!threadContext) { if (!QThread::currentThread()) { qWarning("No QTLS available. currentContext won't work"); return 0; } threadContext = new QGuiGLThreadContext; - qwindow_context_storage.setLocalData(threadContext); + qwindow_context_storage()->setLocalData(threadContext); } QOpenGLContext *previous = threadContext->context; threadContext->context = context; @@ -412,8 +412,8 @@ int QOpenGLContextPrivate::maxTextureSize() */ QOpenGLContext* QOpenGLContext::currentContext() { - QGuiGLThreadContext *threadContext = qwindow_context_storage.localData(); - if(threadContext) { + QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData(); + if (threadContext) { return threadContext->context; } return 0; diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index a529957ad6..89c24b66bf 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -54,7 +54,10 @@ #include <QtGui/qopengl.h> #include <QtGui/qopenglversionfunctions.h> +#if QT_DEPRECATED_SINCE(5, 5) #include <QtCore/qhash.h> +#endif +#include <QtCore/qhashfunctions.h> #include <QtCore/qpair.h> #include <QtCore/qvariant.h> diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index 3d37088182..2d0458f705 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -36,7 +36,6 @@ #include <QtCore/QVariant> #include <QtCore/QSharedData> #include <QtCore/QSettings> -#include <QtCore/QHash> #include <QtCore/QUrl> #include <QtGui/QColor> diff --git a/src/gui/kernel/qplatformintegrationfactory.cpp b/src/gui/kernel/qplatformintegrationfactory.cpp index d58ac3a33f..5a1fb3ca83 100644 --- a/src/gui/kernel/qplatformintegrationfactory.cpp +++ b/src/gui/kernel/qplatformintegrationfactory.cpp @@ -72,6 +72,12 @@ QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platfor } if (QPlatformIntegration *ret = loadIntegration(loader(), platform, paramList, argc, argv)) return ret; +#else + Q_UNUSED(platform); + Q_UNUSED(paramList); + Q_UNUSED(argc); + Q_UNUSED(argv); + Q_UNUSED(platformPluginPath); #endif return 0; } @@ -102,6 +108,7 @@ QStringList QPlatformIntegrationFactory::keys(const QString &platformPluginPath) list.append(loader()->keyMap().values()); return list; #else + Q_UNUSED(platformPluginPath); return QStringList(); #endif } diff --git a/src/gui/kernel/qplatformthemefactory.cpp b/src/gui/kernel/qplatformthemefactory.cpp index d4902ac163..bcc37dad06 100644 --- a/src/gui/kernel/qplatformthemefactory.cpp +++ b/src/gui/kernel/qplatformthemefactory.cpp @@ -63,6 +63,9 @@ QPlatformTheme *QPlatformThemeFactory::create(const QString& key, const QString } if (QPlatformTheme *ret = qLoadPlugin1<QPlatformTheme, QPlatformThemePlugin>(loader(), platform, paramList)) return ret; +#else + Q_UNUSED(key); + Q_UNUSED(platformPluginPath); #endif return 0; } @@ -93,6 +96,7 @@ QStringList QPlatformThemeFactory::keys(const QString &platformPluginPath) list += loader()->keyMap().values(); return list; #else + Q_UNUSED(platformPluginPath); return QStringList(); #endif } diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 038be09dc7..1e0d4f766a 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -37,6 +37,7 @@ #include "qguiapplication_p.h" #include <qpa/qplatformscreen.h> +#include <QtCore/QDebug> #include <QtCore/private/qobject_p.h> QT_BEGIN_NAMESPACE @@ -328,6 +329,7 @@ QList<QScreen *> QScreen::virtualSiblings() const Q_D(const QScreen); QList<QPlatformScreen *> platformScreens = d->platformScreen->virtualSiblings(); QList<QScreen *> screens; + screens.reserve(platformScreens.count()); foreach (QPlatformScreen *platformScreen, platformScreens) screens << platformScreen->screen(); return screens; @@ -654,4 +656,41 @@ QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height) return platformScreen->grabWindow(window, x, y, width, height); } +#ifndef QT_NO_DEBUG_STREAM + +static inline void formatRect(QDebug &debug, const QRect r) +{ + debug << r.width() << 'x' << r.height() + << forcesign << r.x() << r.y() << noforcesign; +} + +Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen) +{ + const QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QScreen(" << (void *)screen; + if (screen) { + debug << ", name=" << screen->name(); + if (debug.verbosity() > 2) { + if (screen == QGuiApplication::primaryScreen()) + debug << ", primary"; + debug << ", geometry="; + formatRect(debug, screen->geometry()); + debug << ", available="; + formatRect(debug, screen->availableGeometry()); + debug << ", logical DPI=" << screen->logicalDotsPerInchX() + << ',' << screen->logicalDotsPerInchY() + << ", physical DPI=" << screen->physicalDotsPerInchX() + << ',' << screen->physicalDotsPerInchY() + << ", devicePixelRatio=" << screen->devicePixelRatio() + << ", orientation=" << screen->orientation() + << ", physical size=" << screen->physicalSize().width() + << 'x' << screen->physicalSize().height() << "mm"; + } + } + debug << ')'; + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + QT_END_NAMESPACE diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h index 255e735baf..f60fafcf63 100644 --- a/src/gui/kernel/qscreen.h +++ b/src/gui/kernel/qscreen.h @@ -52,6 +52,9 @@ class QScreenPrivate; class QWindow; class QRect; class QPixmap; +#ifndef QT_NO_DEBUG_STREAM +class QDebug; +#endif class Q_GUI_EXPORT QScreen : public QObject { @@ -153,6 +156,10 @@ private: friend class QPlatformScreen; }; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QScreen *); +#endif + QT_END_NAMESPACE #endif // QSCREEN_H diff --git a/src/gui/kernel/qtouchdevice.cpp b/src/gui/kernel/qtouchdevice.cpp index 1a6e9deba8..9d19fa4b92 100644 --- a/src/gui/kernel/qtouchdevice.cpp +++ b/src/gui/kernel/qtouchdevice.cpp @@ -195,7 +195,7 @@ void QTouchDevice::setName(const QString &name) d->name = name; } -typedef QList<QTouchDevice *> TouchDevices; +typedef QList<const QTouchDevice *> TouchDevices; Q_GLOBAL_STATIC(TouchDevices, deviceList) static QBasicMutex devicesMutex; @@ -214,26 +214,22 @@ static void cleanupDevicesList() QList<const QTouchDevice *> QTouchDevice::devices() { QMutexLocker lock(&devicesMutex); - QList<QTouchDevice *> *devList = deviceList(); - QList<const QTouchDevice *> constDevList; - for (int i = 0, count = devList->count(); i != count; ++i) - constDevList.append(devList->at(i)); - return constDevList; + return *deviceList(); } /*! \internal */ -bool QTouchDevicePrivate::isRegistered(QTouchDevice *dev) +bool QTouchDevicePrivate::isRegistered(const QTouchDevice *dev) { - QMutexLocker lock(&devicesMutex); + QMutexLocker locker(&devicesMutex); return deviceList()->contains(dev); } /*! \internal */ -void QTouchDevicePrivate::registerDevice(QTouchDevice *dev) +void QTouchDevicePrivate::registerDevice(const QTouchDevice *dev) { QMutexLocker lock(&devicesMutex); if (deviceList()->isEmpty()) diff --git a/src/gui/kernel/qtouchdevice_p.h b/src/gui/kernel/qtouchdevice_p.h index 9c0bcf3414..4aff8f2f33 100644 --- a/src/gui/kernel/qtouchdevice_p.h +++ b/src/gui/kernel/qtouchdevice_p.h @@ -45,7 +45,6 @@ // We mean it. // -#include <QtCore/qobject.h> #include <QtGui/qtouchdevice.h> QT_BEGIN_NAMESPACE @@ -65,8 +64,8 @@ public: QString name; int maxTouchPoints; - static void registerDevice(QTouchDevice *dev); - static bool isRegistered(QTouchDevice *dev); + static void registerDevice(const QTouchDevice *dev); + static bool isRegistered(const QTouchDevice *dev); }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index b54e85a1d3..81e00c8d95 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2471,6 +2471,45 @@ void QWindowPrivate::applyCursor() } #endif // QT_NO_CURSOR +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QWindow *window) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + if (window) { + debug << window->metaObject()->className() << '(' << (void *)window; + if (!window->objectName().isEmpty()) + debug << ", name=" << window->objectName(); + if (debug.verbosity() > 2) { + const QRect geometry = window->geometry(); + if (window->isVisible()) + debug << ", visible"; + if (window->isExposed()) + debug << ", exposed"; + debug << ", state=" << window->windowState() + << ", type=" << window->type() << ", flags=" << window->flags() + << ", surface type=" << window->surfaceType(); + if (window->isTopLevel()) + debug << ", toplevel"; + debug << ", " << geometry.width() << 'x' << geometry.height() + << forcesign << geometry.x() << geometry.y() << noforcesign; + const QMargins margins = window->frameMargins(); + if (!margins.isNull()) + debug << ", margins=" << margins; + debug << ", devicePixelRatio=" << window->devicePixelRatio(); + if (const QPlatformWindow *platformWindow = window->handle()) + debug << ", winId=0x" << hex << platformWindow->winId() << dec; + if (const QScreen *screen = window->screen()) + debug << ", on " << screen->name(); + } + debug << ')'; + } else { + debug << "QWindow(0x0)"; + } + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + QT_END_NAMESPACE #include "moc_qwindow.cpp" diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index f9fe37718c..67585ce963 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -78,6 +78,9 @@ class QBackingStore; class QScreen; class QAccessibleInterface; class QWindowContainer; +#ifndef QT_NO_DEBUG_STREAM +class QDebug; +#endif class Q_GUI_EXPORT QWindow : public QObject, public QSurface { @@ -367,6 +370,10 @@ template <> inline const QWindow *qobject_cast<const QWindow*>(const QObject *o) } #endif // !Q_QDOC +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QWindow *); +#endif + QT_END_NAMESPACE #endif // QWINDOW_H diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index b17978cb7d..17bce6c70f 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -45,9 +45,10 @@ QT_BEGIN_NAMESPACE QElapsedTimer QWindowSystemInterfacePrivate::eventTime; -bool QWindowSystemInterfacePrivate::synchronousWindowsSystemEvents = false; +bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false; QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed; QMutex QWindowSystemInterfacePrivate::flushEventMutex; +QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler; //------------------------------------------------------------ // @@ -93,14 +94,14 @@ void QWindowSystemInterface::handleLeaveEvent(QWindow *tlw) */ void QWindowSystemInterface::handleEnterLeaveEvent(QWindow *enter, QWindow *leave, const QPointF &local, const QPointF& global) { - bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowsSystemEvents; + bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents; if (wasSynchronous) - setSynchronousWindowsSystemEvents(false); + setSynchronousWindowSystemEvents(false); handleLeaveEvent(leave); handleEnterEvent(enter, local, global); if (wasSynchronous) { flushWindowSystemEvents(); - setSynchronousWindowsSystemEvents(true); + setSynchronousWindowSystemEvents(true); } } @@ -425,8 +426,9 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e void QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) { - if (synchronousWindowsSystemEvents) { + if (synchronousWindowSystemEvents) { QGuiApplicationPrivate::processWindowSystemEvent(ev); + delete ev; } else { windowSystemEventQueue.append(ev); QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher(); @@ -453,6 +455,7 @@ QList<QTouchEvent::TouchPoint> QWindowSystemInterfacePrivate::convertTouchPoints Qt::TouchPointStates states; QTouchEvent::TouchPoint p; + touchPoints.reserve(points.count()); QList<QWindowSystemInterface::TouchPoint>::const_iterator point = points.constBegin(); QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd(); while (point != end) { @@ -604,17 +607,35 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla QWindowSystemInterfacePrivate::getWindowSystemEvent(); if (!event) break; - nevents++; - QGuiApplicationPrivate::processWindowSystemEvent(event); + + if (QWindowSystemInterfacePrivate::eventHandler) { + if (QWindowSystemInterfacePrivate::eventHandler->sendEvent(event)) + nevents++; + } else { + nevents++; + QGuiApplicationPrivate::processWindowSystemEvent(event); + } delete event; } return (nevents > 0); } -void QWindowSystemInterface::setSynchronousWindowsSystemEvents(bool enable) +void QWindowSystemInterfacePrivate::installWindowSystemEventHandler(QWindowSystemEventHandler *handler) +{ + if (!eventHandler) + eventHandler = handler; +} + +void QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(QWindowSystemEventHandler *handler) +{ + if (eventHandler == handler) + eventHandler = 0; +} + +void QWindowSystemInterface::setSynchronousWindowSystemEvents(bool enable) { - QWindowSystemInterfacePrivate::synchronousWindowsSystemEvents = enable; + QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = enable; } int QWindowSystemInterface::windowSystemEventsQueued() @@ -790,13 +811,26 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo } #endif -Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier) { - QWindowSystemInterface::handleMouseEvent(w, local, global, b, mods); +Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp) +{ + QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) { - QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count); + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + + // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms + // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for + // shortcut overriding on other platforms. +#if defined(Q_OS_OSX) + if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(w, timestamp, k, mods, text)) + return; +#endif // Q_OS_OSX + + QWindowSystemInterfacePrivate::KeyEvent e(w, timestamp, t, k, mods, text, autorep, count); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) @@ -804,35 +838,49 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count); } -static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt) -{ - QWindowSystemInterface::TouchPoint p; - p.id = pt.id(); - p.flags = pt.flags(); - p.normalPosition = pt.normalizedPos(); - p.area = pt.screenRect(); - p.pressure = pt.pressure(); - p.state = pt.state(); - p.velocity = pt.velocity(); - p.rawPositions = pt.rawScreenPositions(); - return p; -} -static QList<struct QWindowSystemInterface::TouchPoint> touchPointList(const QList<QTouchEvent::TouchPoint>& pointList) + +Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, + const QList<QTouchEvent::TouchPoint> &points, + Qt::KeyboardModifiers mods = Qt::NoModifier) { - QList<struct QWindowSystemInterface::TouchPoint> newList; + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + + if (!points.size()) // Touch events must have at least one point + return; + + if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. + return; + + QEvent::Type type; + Qt::TouchPointStates states; - Q_FOREACH (QTouchEvent::TouchPoint p, pointList) - { - newList.append(touchPoint(p)); + QList<QTouchEvent::TouchPoint>::const_iterator point = points.constBegin(); + QList<QTouchEvent::TouchPoint>::const_iterator end = points.constEnd(); + while (point != end) { + states |= point->state(); + ++point; } - return newList; + + // Determine the event type based on the combined point states. + type = QEvent::TouchUpdate; + if (states == Qt::TouchPointPressed) + type = QEvent::TouchBegin; + else if (states == Qt::TouchPointReleased) + type = QEvent::TouchEnd; + + QWindowSystemInterfacePrivate::TouchEvent e(w, timestamp, type, device, points, mods); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, - const QList<QTouchEvent::TouchPoint> &points, - Qt::KeyboardModifiers mods = Qt::NoModifier) +QWindowSystemEventHandler::~QWindowSystemEventHandler() +{ + QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(this); +} + +bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) { - QWindowSystemInterface::handleTouchEvent(w, device, touchPointList(points), mods); + QGuiApplicationPrivate::processWindowSystemEvent(e); + return true; } QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index c004fc6ef2..7ad491cdac 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -210,7 +210,7 @@ public: // For event dispatcher implementations static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags); - static void setSynchronousWindowsSystemEvents(bool enable); + static void setSynchronousWindowSystemEvents(bool enable); static void flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); static void deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags); static int windowSystemEventsQueued(); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 2ec402a1e9..7160971305 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -54,6 +54,8 @@ QT_BEGIN_NAMESPACE +class QWindowSystemEventHandler; + class Q_GUI_EXPORT QWindowSystemInterfacePrivate { public: enum EventType { @@ -481,12 +483,23 @@ public: static void handleWindowSystemEvent(WindowSystemEvent *ev); static QElapsedTimer eventTime; - static bool synchronousWindowsSystemEvents; + static bool synchronousWindowSystemEvents; static QWaitCondition eventsFlushed; static QMutex flushEventMutex; static QList<QTouchEvent::TouchPoint> convertTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points, QEvent::Type *type); + + static void installWindowSystemEventHandler(QWindowSystemEventHandler *handler); + static void removeWindowSystemEventhandler(QWindowSystemEventHandler *handler); + static QWindowSystemEventHandler *eventHandler; +}; + +class Q_GUI_EXPORT QWindowSystemEventHandler +{ +public: + virtual ~QWindowSystemEventHandler(); + virtual bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *event); }; QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 1c008ccb42..68cd8a82b4 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -135,20 +135,42 @@ static const char operators[][3] = {"!=", "<", "<=", "=", ">", ">="}; static inline QString valueKey() { return QStringLiteral("value"); } static inline QString opKey() { return QStringLiteral("op"); } static inline QString versionKey() { return QStringLiteral("version"); } +static inline QString releaseKey() { return QStringLiteral("release"); } static inline QString typeKey() { return QStringLiteral("type"); } static inline QString osKey() { return QStringLiteral("os"); } static inline QString vendorIdKey() { return QStringLiteral("vendor_id"); } static inline QString glVendorKey() { return QStringLiteral("gl_vendor"); } static inline QString deviceIdKey() { return QStringLiteral("device_id"); } static inline QString driverVersionKey() { return QStringLiteral("driver_version"); } +static inline QString driverDescriptionKey() { return QStringLiteral("driver_description"); } static inline QString featuresKey() { return QStringLiteral("features"); } static inline QString idKey() { return QStringLiteral("id"); } static inline QString descriptionKey() { return QStringLiteral("description"); } static inline QString exceptionsKey() { return QStringLiteral("exceptions"); } +typedef QJsonArray::ConstIterator JsonArrayConstIt; + +static inline bool contains(const QJsonArray &haystack, unsigned needle) +{ + for (JsonArrayConstIt it = haystack.constBegin(), cend = haystack.constEnd(); it != cend; ++it) { + if (needle == it->toString().toUInt(Q_NULLPTR, /* base */ 0)) + return true; + } + return false; +} + +static inline bool contains(const QJsonArray &haystack, const QString &needle) +{ + for (JsonArrayConstIt it = haystack.constBegin(), cend = haystack.constEnd(); it != cend; ++it) { + if (needle == it->toString()) + return true; + } + return false; +} + namespace { // VersionTerm describing a version term consisting of number and operator -// found in "os", "driver_version", "gl_version". +// found in os.version and driver_version. struct VersionTerm { VersionTerm() : op(NotEqual) {} static VersionTerm fromJson(const QJsonValue &v); @@ -206,9 +228,38 @@ struct OsTypeTerm static OsTypeTerm fromJson(const QJsonValue &v); static QString hostOs(); static QVersionNumber hostKernelVersion() { return QVersionNumber::fromString(QSysInfo::kernelVersion()); } + static QString hostOsRelease() { + QString ver; +#ifdef Q_OS_WIN + switch (QSysInfo::windowsVersion()) { + case QSysInfo::WV_XP: + case QSysInfo::WV_2003: + ver = QStringLiteral("xp"); + break; + case QSysInfo::WV_VISTA: + ver = QStringLiteral("vista"); + break; + case QSysInfo::WV_WINDOWS7: + ver = QStringLiteral("7"); + break; + case QSysInfo::WV_WINDOWS8: + ver = QStringLiteral("8"); + break; + case QSysInfo::WV_WINDOWS8_1: + ver = QStringLiteral("8.1"); + break; + case QSysInfo::WV_WINDOWS10: + ver = QStringLiteral("10"); + break; + default: + break; + } +#endif + return ver; + } bool isNull() const { return type.isEmpty(); } - bool matches(const QString &osName, const QVersionNumber &kernelVersion) const + bool matches(const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease) const { if (isNull() || osName.isEmpty() || kernelVersion.isNull()) { qWarning() << Q_FUNC_INFO << "called with invalid parameters"; @@ -216,11 +267,17 @@ struct OsTypeTerm } if (type != osName) return false; - return versionTerm.isNull() || versionTerm.matches(kernelVersion); + if (!versionTerm.isNull() && !versionTerm.matches(kernelVersion)) + return false; + // release is a list of Windows versions where the rule should match + if (!release.isEmpty() && !contains(release, osRelease)) + return false; + return true; } QString type; VersionTerm versionTerm; + QJsonArray release; }; OsTypeTerm OsTypeTerm::fromJson(const QJsonValue &v) @@ -231,6 +288,7 @@ OsTypeTerm OsTypeTerm::fromJson(const QJsonValue &v) const QJsonObject o = v.toObject(); result.type = o.value(typeKey()).toString(); result.versionTerm = VersionTerm::fromJson(o.value(versionKey())); + result.release = o.value(releaseKey()).toArray(); return result; } @@ -251,17 +309,6 @@ QString OsTypeTerm::hostOs() } } // anonymous namespace -typedef QJsonArray::ConstIterator JsonArrayConstIt; - -static inline bool contains(const QJsonArray &a, unsigned needle) -{ - for (JsonArrayConstIt it = a.constBegin(), cend = a.constEnd(); it != cend; ++it) { - if (needle == it->toString().toUInt(Q_NULLPTR, /* base */ 0)) - return true; - } - return false; -} - static QString msgSyntaxWarning(const QJsonObject &object, const QString &what) { QString result; @@ -277,17 +324,18 @@ static QString msgSyntaxWarning(const QJsonObject &object, const QString &what) static bool matches(const QJsonObject &object, const QString &osName, const QVersionNumber &kernelVersion, + const QString &osRelease, const QOpenGLConfig::Gpu &gpu) { const OsTypeTerm os = OsTypeTerm::fromJson(object.value(osKey())); - if (!os.isNull() && !os.matches(osName, kernelVersion)) + if (!os.isNull() && !os.matches(osName, kernelVersion, osRelease)) return false; const QJsonValue exceptionsV = object.value(exceptionsKey()); if (exceptionsV.isArray()) { const QJsonArray exceptionsA = exceptionsV.toArray(); for (JsonArrayConstIt it = exceptionsA.constBegin(), cend = exceptionsA.constEnd(); it != cend; ++it) { - if (matches(it->toObject(), osName, kernelVersion, gpu)) + if (matches(it->toObject(), osName, kernelVersion, osRelease, gpu)) return false; } } @@ -336,12 +384,22 @@ static bool matches(const QJsonObject &object, QLatin1String("Driver version must be of type object.")); } } + + if (!gpu.driverDescription.isEmpty()) { + const QJsonValue driverDescriptionV = object.value(driverDescriptionKey()); + if (driverDescriptionV.isString()) { + if (!gpu.driverDescription.contains(driverDescriptionV.toString().toUtf8())) + return false; + } + } + return true; } static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, const QString &osName, const QVersionNumber &kernelVersion, + const QString &osRelease, const QJsonDocument &doc, QSet<QString> *result, QString *errorMessage) @@ -358,7 +416,7 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, for (JsonArrayConstIt eit = entriesA.constBegin(), ecend = entriesA.constEnd(); eit != ecend; ++eit) { if (eit->isObject()) { const QJsonObject object = eit->toObject(); - if (matches(object, osName, kernelVersion, gpu)) { + if (matches(object, osName, kernelVersion, osRelease, gpu)) { const QJsonValue featuresListV = object.value(featuresKey()); if (featuresListV.isArray()) { const QJsonArray featuresListA = featuresListV.toArray(); @@ -374,6 +432,7 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, const QString &osName, const QVersionNumber &kernelVersion, + const QString &osRelease, const QByteArray &jsonAsciiData, QSet<QString> *result, QString *errorMessage) { @@ -389,12 +448,13 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, << error.offset << ")."; return false; } - return readGpuFeatures(gpu, osName, kernelVersion, document, result, errorMessage); + return readGpuFeatures(gpu, osName, kernelVersion, osRelease, document, result, errorMessage); } static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, const QString &osName, const QVersionNumber &kernelVersion, + const QString &osRelease, const QString &fileName, QSet<QString> *result, QString *errorMessage) { @@ -407,7 +467,7 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, << file.errorString(); return false; } - const bool success = readGpuFeatures(gpu, osName, kernelVersion, file.readAll(), result, errorMessage); + const bool success = readGpuFeatures(gpu, osName, kernelVersion, osRelease, file.readAll(), result, errorMessage); if (!success) { errorMessage->prepend(QLatin1String("Error reading \"") + QDir::toNativeSeparators(fileName) @@ -417,37 +477,39 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu, } QSet<QString> QOpenGLConfig::gpuFeatures(const QOpenGLConfig::Gpu &gpu, - const QString &osName, - const QVersionNumber &kernelVersion, - const QJsonDocument &doc) + const QString &osName, + const QVersionNumber &kernelVersion, + const QString &osRelease, + const QJsonDocument &doc) { QSet<QString> result; QString errorMessage; - if (!readGpuFeatures(gpu, osName, kernelVersion, doc, &result, &errorMessage)) + if (!readGpuFeatures(gpu, osName, kernelVersion, osRelease, doc, &result, &errorMessage)) qWarning().noquote() << errorMessage; return result; } QSet<QString> QOpenGLConfig::gpuFeatures(const QOpenGLConfig::Gpu &gpu, - const QString &osName, - const QVersionNumber &kernelVersion, - const QString &fileName) + const QString &osName, + const QVersionNumber &kernelVersion, + const QString &osRelease, + const QString &fileName) { QSet<QString> result; QString errorMessage; - if (!readGpuFeatures(gpu, osName, kernelVersion, fileName, &result, &errorMessage)) + if (!readGpuFeatures(gpu, osName, kernelVersion, osRelease, fileName, &result, &errorMessage)) qWarning().noquote() << errorMessage; return result; } QSet<QString> QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QJsonDocument &doc) { - return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), doc); + return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), OsTypeTerm::hostOsRelease(), doc); } QSet<QString> QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QString &fileName) { - return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), fileName); + return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), OsTypeTerm::hostOsRelease(), fileName); } QOpenGLConfig::Gpu QOpenGLConfig::Gpu::fromContext() diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h index 980e02aea6..31a083d96f 100644 --- a/src/gui/opengl/qopengl_p.h +++ b/src/gui/opengl/qopengl_p.h @@ -79,19 +79,21 @@ public: bool isValid() const { return deviceId || !glVendor.isEmpty(); } bool equals(const Gpu &other) const { return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion - && glVendor == other.glVendor; + && driverDescription == other.driverDescription && glVendor == other.glVendor; } uint vendorId; uint deviceId; QVersionNumber driverVersion; + QByteArray driverDescription; QByteArray glVendor; - static Gpu fromDevice(uint vendorId, uint deviceId, QVersionNumber driverVersion) { + static Gpu fromDevice(uint vendorId, uint deviceId, QVersionNumber driverVersion, const QByteArray &driverDescription) { Gpu gpu; gpu.vendorId = vendorId; gpu.deviceId = deviceId; gpu.driverVersion = driverVersion; + gpu.driverDescription = driverDescription; return gpu; } @@ -105,10 +107,10 @@ public: }; static QSet<QString> gpuFeatures(const Gpu &gpu, - const QString &osName, const QVersionNumber &kernelVersion, + const QString &osName, const QVersionNumber &kernelVersion, const QString &osVersion, const QJsonDocument &doc); static QSet<QString> gpuFeatures(const Gpu &gpu, - const QString &osName, const QVersionNumber &kernelVersion, + const QString &osName, const QVersionNumber &kernelVersion, const QString &osVersion, const QString &fileName); static QSet<QString> gpuFeatures(const Gpu &gpu, const QJsonDocument &doc); static QSet<QString> gpuFeatures(const Gpu &gpu, const QString &fileName); diff --git a/src/gui/opengl/qopengldebug.h b/src/gui/opengl/qopengldebug.h index 425ab78d7a..d24940cb3c 100644 --- a/src/gui/opengl/qopengldebug.h +++ b/src/gui/opengl/qopengldebug.h @@ -97,14 +97,14 @@ public: QOpenGLDebugMessage(); QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage); - ~QOpenGLDebugMessage(); QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage); #ifdef Q_COMPILER_RVALUE_REFS - inline QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&debugMessage) - { d.swap(debugMessage.d); return *this; } + QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif - inline void swap(QOpenGLDebugMessage &debugMessage) { d.swap(debugMessage.d); } + ~QOpenGLDebugMessage(); + + void swap(QOpenGLDebugMessage &other) Q_DECL_NOTHROW { qSwap(d, other.d); } Source source() const; Type type() const; diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h index 7def687f49..e50ca1a94c 100644 --- a/src/gui/opengl/qopenglextensions_p.h +++ b/src/gui/opengl/qopenglextensions_p.h @@ -78,8 +78,9 @@ public: private: bool init(); QFunctionPointer resolve(const char *name); - +#ifndef QT_NO_LIBRARY QLibrary m_gl; +#endif }; class Q_GUI_EXPORT QOpenGLExtensions : public QOpenGLFunctions @@ -113,7 +114,8 @@ public: GeometryShaders = 0x00080000, MapBufferRange = 0x00100000, Sized8Formats = 0x00200000, - DiscardFramebuffer = 0x00400000 + DiscardFramebuffer = 0x00400000, + Sized16Formats = 0x00800000 }; Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension) diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 8ddb693e73..2b8488ab0e 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -423,11 +423,14 @@ static int qt_gl_resolve_extensions() // We don't match GL_APPLE_texture_format_BGRA8888 here because it has different semantics. if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888")) extensions |= QOpenGLExtensions::BGRATextureFormat; - if (extensionMatcher.match("GL_EXT_discard_framebuffer")) extensions |= QOpenGLExtensions::DiscardFramebuffer; + if (extensionMatcher.match("GL_EXT_texture_norm16")) + extensions |= QOpenGLExtensions::Sized16Formats; } else { - extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer; + extensions |= QOpenGLExtensions::ElementIndexUint + | QOpenGLExtensions::MapBuffer + | QOpenGLExtensions::Sized16Formats; if (format.version() >= qMakePair(1, 2)) extensions |= QOpenGLExtensions::BGRATextureFormat; @@ -3212,7 +3215,9 @@ Q_GLOBAL_STATIC(QOpenGLES3Helper, qgles3Helper) bool QOpenGLES3Helper::init() { -#ifndef Q_OS_IOS +#ifdef QT_NO_LIBRARY + return false; +#elif !defined(Q_OS_IOS) # ifdef Q_OS_WIN # ifndef QT_DEBUG m_gl.setFileName(QStringLiteral("libGLESv2")); @@ -3236,8 +3241,11 @@ QFunctionPointer QOpenGLES3Helper::resolve(const char *name) { #ifdef Q_OS_IOS return QFunctionPointer(dlsym(RTLD_DEFAULT, name)); -#else +#elif !defined(QT_NO_LIBRARY) return m_gl.resolve(name); +#else + Q_UNUSED(name); + return 0; #endif } diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index ab493fa85c..13bad9aabb 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -34,8 +34,14 @@ #include "qopenglgradientcache_p.h" #include <private/qdrawhelper_p.h> #include <private/qopenglcontext_p.h> +#include <private/qrgba64_p.h> #include <QtCore/qmutex.h> -#include <QtGui/qopenglfunctions.h> +#include "qopenglfunctions.h" +#include "qopenglextensions_p.h" + +#ifndef GL_RGBA16 +#define GL_RGBA16 0x805B +#endif QT_BEGIN_NAMESPACE @@ -137,17 +143,79 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient } CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); - uint buffer[1024]; - generateGradientColorTable(gradient, buffer, paletteSize(), opacity); funcs->glGenTextures(1, &cache_entry.texId); funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + if (static_cast<QOpenGLExtensions *>(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats)) { + QRgba64 buffer[1024]; + generateGradientColorTable(gradient, buffer, paletteSize(), opacity); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, paletteSize(), 1, + 0, GL_RGBA, GL_UNSIGNED_SHORT, buffer); + } else { + uint buffer[1024]; + generateGradientColorTable(gradient, buffer, paletteSize(), opacity); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + } return cache.insert(hash_val, cache_entry).value().texId; } //TODO: Let GL generate the texture using an FBO +void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const +{ + int pos = 0; + QGradientStops s = gradient.stops(); + QVector<QRgba64> colors(s.size()); + + for (int i = 0; i < s.size(); ++i) + colors[i] = s[i].second.rgba64(); + + bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); + + uint alpha = qRound(opacity * 256); + QRgba64 current_color = combineAlpha256(colors[0], alpha); + qreal incr = 1.0 / qreal(size); + qreal fpos = 1.5 * incr; + colorTable[pos++] = qPremultiply(current_color); + + while (fpos <= s.first().first) { + colorTable[pos] = colorTable[pos - 1]; + pos++; + fpos += incr; + } + + if (colorInterpolation) + current_color = qPremultiply(current_color); + + for (int i = 0; i < s.size() - 1; ++i) { + qreal delta = 1/(s[i+1].first - s[i].first); + QRgba64 next_color = combineAlpha256(colors[i+1], alpha); + if (colorInterpolation) + next_color = qPremultiply(next_color); + + while (fpos < s[i+1].first && pos < size) { + int dist = int(256 * ((fpos - s[i].first) * delta)); + int idist = 256 - dist; + if (colorInterpolation) + colorTable[pos] = interpolate256(current_color, idist, next_color, dist); + else + colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist)); + ++pos; + fpos += incr; + } + current_color = next_color; + } + + Q_ASSERT(s.size() > 0); + + QRgba64 last_color = qPremultiply(combineAlpha256(colors[s.size() - 1], alpha)); + for (;pos < size; ++pos) + colorTable[pos] = last_color; + + // Make sure the last color stop is represented at the end of the table + colorTable[size-1] = last_color; +} + void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const { int pos = 0; diff --git a/src/gui/opengl/qopenglgradientcache_p.h b/src/gui/opengl/qopenglgradientcache_p.h index bcdf3f4fcf..61949d5b7c 100644 --- a/src/gui/opengl/qopenglgradientcache_p.h +++ b/src/gui/opengl/qopenglgradientcache_p.h @@ -50,6 +50,7 @@ #include <private/qopenglcontext_p.h> #include <QtCore/qmutex.h> #include <QGradient> +#include <qrgba64.h> QT_BEGIN_NAMESPACE @@ -83,6 +84,9 @@ public: private: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& gradient, + QRgba64 *colorTable, + int size, qreal opacity) const; + inline void generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const; GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity); diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp index c0657feaa0..e509b26a95 100644 --- a/src/gui/opengl/qopenglpaintdevice.cpp +++ b/src/gui/opengl/qopenglpaintdevice.cpp @@ -169,6 +169,10 @@ QOpenGLPaintDevicePrivate::QOpenGLPaintDevicePrivate(const QSize &sz) { } +QOpenGLPaintDevicePrivate::~QOpenGLPaintDevicePrivate() +{ +} + class QOpenGLEngineThreadStorage { public: diff --git a/src/gui/opengl/qopenglpaintdevice_p.h b/src/gui/opengl/qopenglpaintdevice_p.h index 57d93ee80a..54ea09240d 100644 --- a/src/gui/opengl/qopenglpaintdevice_p.h +++ b/src/gui/opengl/qopenglpaintdevice_p.h @@ -56,7 +56,7 @@ class Q_GUI_EXPORT QOpenGLPaintDevicePrivate { public: QOpenGLPaintDevicePrivate(const QSize &size); - virtual ~QOpenGLPaintDevicePrivate() { } + virtual ~QOpenGLPaintDevicePrivate(); static QOpenGLPaintDevicePrivate *get(QOpenGLPaintDevice *dev) { return dev->d_func(); } diff --git a/src/gui/opengl/qopenglpixeltransferoptions.h b/src/gui/opengl/qopenglpixeltransferoptions.h index bf726813bd..cb4697ec7c 100644 --- a/src/gui/opengl/qopenglpixeltransferoptions.h +++ b/src/gui/opengl/qopenglpixeltransferoptions.h @@ -49,15 +49,14 @@ class Q_GUI_EXPORT QOpenGLPixelTransferOptions public: QOpenGLPixelTransferOptions(); QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &); - QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &); - ~QOpenGLPixelTransferOptions(); - #ifdef Q_COMPILER_RVALUE_REFS - QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) + QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif + QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &); + ~QOpenGLPixelTransferOptions(); - void swap(QOpenGLPixelTransferOptions &other) + void swap(QOpenGLPixelTransferOptions &other) Q_DECL_NOTHROW { data.swap(other.data); } void setAlignment(int alignment); diff --git a/src/gui/opengl/qopenglversionfunctions.h b/src/gui/opengl/qopenglversionfunctions.h index fcf665f97e..2fd3b9dab9 100644 --- a/src/gui/opengl/qopenglversionfunctions.h +++ b/src/gui/opengl/qopenglversionfunctions.h @@ -47,7 +47,10 @@ #ifndef QT_NO_OPENGL +#if QT_DEPRECATED_SINCE(5, 5) #include <QtCore/qhash.h> +#endif +#include <QtCore/qhashfunctions.h> #include <QtCore/qpair.h> #include <QtGui/qopengl.h> diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index a861516821..791b5f1a9a 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -43,6 +43,8 @@ HEADERS += \ painting/qrasterizer_p.h \ painting/qregion.h \ painting/qrgb.h \ + painting/qrgba64.h \ + painting/qrgba64_p.h \ painting/qstroker_p.h \ painting/qtextureglyphcache_p.h \ painting/qtransform.h \ @@ -58,6 +60,7 @@ SOURCES += \ painting/qbrush.cpp \ painting/qcolor.cpp \ painting/qcolor_p.cpp \ + painting/qcompositionfunctions.cpp \ painting/qcosmeticstroker.cpp \ painting/qcssutil.cpp \ painting/qdrawhelper.cpp \ diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 670717c5f1..d6eb8d8a48 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -1163,6 +1163,7 @@ QDataStream &operator>>(QDataStream &s, QBrush &b) QColor c; s >> numStops; + stops.reserve(numStops); for (quint32 i = 0; i < numStops; ++i) { s >> n >> c; stops << QPair<qreal, QColor>(n, c); diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index d50c42f1ee..f1ceb464c8 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -416,6 +416,18 @@ QColor::QColor(QRgb color) ct.argb.pad = 0; } +/*! + \since 5.6 + + Constructs a color with the value \a rgba64. + + \sa fromRgba64() +*/ + +QColor::QColor(QRgba64 rgba64) +{ + setRgba64(rgba64); +} /*! \internal @@ -941,7 +953,7 @@ void QColor::setRgb(int r, int g, int b, int a) For an invalid color, the alpha value of the returned color is unspecified. - \sa setRgba(), rgb() + \sa setRgba(), rgb(), rgba64() */ QRgb QColor::rgba() const @@ -954,7 +966,7 @@ QRgb QColor::rgba() const /*! Sets the RGB value to \a rgba, including its alpha. - \sa rgba(), rgb() + \sa rgba(), rgb(), setRgba64() */ void QColor::setRgba(QRgb rgba) { @@ -967,6 +979,40 @@ void QColor::setRgba(QRgb rgba) } /*! + \since 5.6 + + Returns the RGB64 value of the color, including its alpha. + + For an invalid color, the alpha value of the returned color is unspecified. + + \sa setRgba64(), rgba(), rgb() +*/ + +QRgba64 QColor::rgba64() const +{ + if (cspec != Invalid && cspec != Rgb) + return toRgb().rgba64(); + return qRgba64(ct.argb.red, ct.argb.green, ct.argb.blue, ct.argb.alpha); +} + +/*! + \since 5.6 + + Sets the RGB64 value to \a rgba, including its alpha. + + \sa \setRgba(), rgba64() +*/ +void QColor::setRgba64(QRgba64 rgba) +{ + cspec = Rgb; + ct.argb.alpha = rgba.alpha(); + ct.argb.red = rgba.red(); + ct.argb.green = rgba.green(); + ct.argb.blue = rgba.blue(); + ct.argb.pad = 0; +} + +/*! \fn QRgb QColor::rgb() const Returns the RGB value of the color. The alpha value is opaque. @@ -1850,7 +1896,7 @@ QColor QColor::fromRgb(QRgb rgb) Unlike the fromRgb() function, the alpha-channel specified by the given QRgb value is included. - \sa fromRgb(), isValid() + \sa fromRgb(), fromRgba64(), isValid() */ QColor QColor::fromRgba(QRgb rgba) @@ -1865,7 +1911,7 @@ QColor QColor::fromRgba(QRgb rgba) All the values must be in the range 0-255. - \sa toRgb(), fromRgbF(), isValid() + \sa toRgb(), fromRgba64(), fromRgbF(), isValid() */ QColor QColor::fromRgb(int r, int g, int b, int a) { @@ -1894,7 +1940,7 @@ QColor QColor::fromRgb(int r, int g, int b, int a) All the values must be in the range 0.0-1.0. - \sa fromRgb(), toRgb(), isValid() + \sa fromRgb(), fromRgba64(), toRgb(), isValid() */ QColor QColor::fromRgbF(qreal r, qreal g, qreal b, qreal a) { @@ -1916,6 +1962,38 @@ QColor QColor::fromRgbF(qreal r, qreal g, qreal b, qreal a) return color; } + +/*! + \since 5.6 + + Static convenience function that returns a QColor constructed from the RGBA64 + color values, \a r (red), \a g (green), \a b (blue), and \a a + (alpha-channel, i.e. transparency). + + \sa fromRgb(), fromRgbF(), toRgb(), isValid() +*/ +QColor QColor::fromRgba64(ushort r, ushort g, ushort b, ushort a) +{ + QColor color; + color.setRgba64(qRgba64(r, g, b, a)); + return color; +} + +/*! + \since 5.6 + + Static convenience function that returns a QColor constructed from the + given QRgba64 value \a rgba64. + + \sa fromRgb(), fromRgbF(), toRgb(), isValid() +*/ +QColor QColor::fromRgba64(QRgba64 rgba64) +{ + QColor color; + color.setRgba64(rgba64); + return color; +} + /*! Static convenience function that returns a QColor constructed from the HSV color values, \a h (hue), \a s (saturation), \a v (value), and \a a diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index 06c218365b..9175875310 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -37,6 +37,7 @@ #include <QtGui/qrgb.h> #include <QtCore/qnamespace.h> #include <QtCore/qstringlist.h> +#include <QtGui/qrgba64.h> QT_BEGIN_NAMESPACE @@ -63,6 +64,7 @@ public: QColor(Qt::GlobalColor color); QColor(int r, int g, int b, int a = 255); QColor(QRgb rgb); + QColor(QRgba64 rgba64); QColor(const QString& name); QColor(const char *name); QColor(const QColor &color); // ### Qt 6: remove, the trivial one is fine. @@ -109,6 +111,9 @@ public: QRgb rgba() const; void setRgba(QRgb rgba); + QRgba64 rgba64() const; + void setRgba64(QRgba64 rgba); + QRgb rgb() const; void setRgb(QRgb rgb); @@ -173,6 +178,9 @@ public: static QColor fromRgb(int r, int g, int b, int a = 255); static QColor fromRgbF(qreal r, qreal g, qreal b, qreal a = 1.0); + static QColor fromRgba64(ushort r, ushort g, ushort b, ushort a = USHRT_MAX); + static QColor fromRgba64(QRgba64 rgba); + static QColor fromHsv(int h, int s, int v, int a = 255); static QColor fromHsvF(qreal h, qreal s, qreal v, qreal a = 1.0); diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp new file mode 100644 index 0000000000..ba428a7938 --- /dev/null +++ b/src/gui/painting/qcompositionfunctions.cpp @@ -0,0 +1,2197 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> +#include <private/qdrawhelper_p.h> +#include <private/qrgba64_p.h> + +QT_BEGIN_NAMESPACE + +# define PRELOAD_INIT(x) +# define PRELOAD_INIT2(x,y) +# define PRELOAD_COND(x) +# define PRELOAD_COND2(x,y) + +/* The constant alpha factor describes an alpha factor that gets applied + to the result of the composition operation combining it with the destination. + + The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1. + we get the unmodified operation + + result = src op dest + dest = result * const_alpha + dest * (1. - const_alpha) + + This means that in the comments below, the first line is the const_alpha==255 case, the + second line the general one. + + In the lines below: + s == src, sa == alpha(src), sia = 1 - alpha(src) + d == dest, da == alpha(dest), dia = 1 - alpha(dest) + ca = const_alpha, cia = 1 - const_alpha + + The methods exist in two variants. One where we have a constant source, the other + where the source is an array of pixels. +*/ + +/* + result = 0 + d = d * cia +*/ +#define comp_func_Clear_impl(dest, length, const_alpha)\ +{\ + if (const_alpha == 255) {\ + QT_MEMFILL_UINT(dest, length, 0);\ + } else {\ + int ialpha = 255 - const_alpha;\ + PRELOAD_INIT(dest)\ + for (int i = 0; i < length; ++i) {\ + PRELOAD_COND(dest)\ + dest[i] = BYTE_MUL(dest[i], ialpha);\ + }\ + }\ +} + +void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha) +{ + comp_func_Clear_impl(dest, length, const_alpha); +} + +void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha) +{ + if (const_alpha == 255) + qt_memfill64((quint64*)dest, 0, length); + else { + int ialpha = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha255(dest[i], ialpha); + } + } +} + +void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha) +{ + comp_func_Clear_impl(dest, length, const_alpha); +} + +void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha) +{ + if (const_alpha == 255) + qt_memfill64((quint64*)dest, 0, length); + else { + int ialpha = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha255(dest[i], ialpha); + } + } +} + +/* + result = s + dest = s * ca + d * cia +*/ +void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) { + QT_MEMFILL_UINT(dest, length, color); + } else { + int ialpha = 255 - const_alpha; + color = BYTE_MUL(color, const_alpha); + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + dest[i] = color + BYTE_MUL(dest[i], ialpha); + } + } +} + +void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255) + qt_memfill64((quint64*)dest, color, length); + else { + int ialpha = 255 - const_alpha; + color = multiplyAlpha255(color, const_alpha); + for (int i = 0; i < length; ++i) { + dest[i] = color + multiplyAlpha255(dest[i], ialpha); + } + } +} + +void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + ::memcpy(dest, src, length * sizeof(uint)); + } else { + int ialpha = 255 - const_alpha; + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); + } + } +} + +void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + ::memcpy(dest, src, length * sizeof(quint64)); + else { + int ialpha = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + dest[i] = interpolate255(src[i], const_alpha, dest[i], ialpha); + } + } +} + +void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint) +{ +} + +void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint) +{ +} + +void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint) +{ +} + +void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, uint) +{ +} + +/* + result = s + d * sia + dest = (s + d * sia) * ca + d * cia + = s * ca + d * (sia * ca + cia) + = s * ca + d * (1 - sa*ca) +*/ +void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha) +{ + if ((const_alpha & qAlpha(color)) == 255) { + QT_MEMFILL_UINT(dest, length, color); + } else { + if (const_alpha != 255) + color = BYTE_MUL(color, const_alpha); + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color)); + } + } +} + +void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255 && color.isOpaque()) { + qt_memfill64((quint64*)dest, color, length); + } else { + if (const_alpha != 255) + color = multiplyAlpha255(color, const_alpha); + for (int i = 0; i < length; ++i) { + dest[i] = color + multiplyAlpha65535(dest[i], 65535 - color.alpha()); + } + } +} + +void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint s = src[i]; + if (s >= 0xff000000) + dest[i] = s; + else if (s != 0) + dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); + } + } else { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint s = BYTE_MUL(src[i], const_alpha); + dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); + } + } +} + +void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + QRgba64 s = src[i]; + if (s.isOpaque()) + dest[i] = s; + else if (!s.isTransparent()) + dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha()); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 s = multiplyAlpha255(src[i], const_alpha); + dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha()); + } + } +} + +/* + result = d + s * dia + dest = (d + s * dia) * ca + d * cia + = d + s * dia * ca +*/ +void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha != 255) + color = BYTE_MUL(color, const_alpha); + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + dest[i] = d + BYTE_MUL(color, qAlpha(~d)); + } +} + +void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha != 255) + color = multiplyAlpha255(color, const_alpha); + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = d + multiplyAlpha65535(color, 65535 - d.alpha()); + } +} + +void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + dest[i] = d + BYTE_MUL(src[i], qAlpha(~d)); + } + } else { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = BYTE_MUL(src[i], const_alpha); + dest[i] = d + BYTE_MUL(s, qAlpha(~d)); + } + } +} + +void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = d + multiplyAlpha65535(src[i], 65535 - d.alpha()); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + QRgba64 s = multiplyAlpha255(src[i], const_alpha); + dest[i] = d + multiplyAlpha65535(s, 65535 - d.alpha()); + } + } +} + +/* + result = s * da + dest = s * da * ca + d * cia +*/ +void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha) +{ + PRELOAD_INIT(dest) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + dest[i] = BYTE_MUL(color, qAlpha(dest[i])); + } + } else { + color = BYTE_MUL(color, const_alpha); + uint cia = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia); + } + } +} + +void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(color, dest[i].alpha()); + } + } else { + uint ca = const_alpha * 257; + uint cia = 65535 - ca; + color = multiplyAlpha65535(color, ca); + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = interpolate65535(color, d.alpha(), d, cia); + } + } +} + +void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + dest[i] = BYTE_MUL(src[i], qAlpha(dest[i])); + } + } else { + uint cia = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = BYTE_MUL(src[i], const_alpha); + dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia); + } + } +} + +void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(src[i], dest[i].alpha()); + } + } else { + uint ca = const_alpha * 257; + uint cia = 65535 - ca; + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + QRgba64 s = multiplyAlpha65535(src[i], ca); + dest[i] = interpolate65535(s, d.alpha(), d, cia); + } + } +} + +/* + result = d * sa + dest = d * sa * ca + d * cia + = d * (sa * ca + cia) +*/ +void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha) +{ + uint a = qAlpha(color); + if (const_alpha != 255) { + a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; + } + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + dest[i] = BYTE_MUL(dest[i], a); + } +} + +void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + uint a = color.alpha(); + uint ca64k = const_alpha * 257; + if (const_alpha != 255) + a = qt_div_65535(a * ca64k) + 65535 - ca64k; + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(dest[i], a); + } +} + +void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + dest[i] = BYTE_MUL(dest[i], qAlpha(src[i])); + } + } else { + int cia = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia; + dest[i] = BYTE_MUL(dest[i], a); + } + } +} + +void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(dest[i], src[i].alpha()); + } + } else { + uint ca = const_alpha * 257; + uint cia = 65535 - ca; + for (int i = 0; i < length; ++i) { + uint a = qt_div_65535(src[i].alpha() * ca) + cia; + dest[i] = multiplyAlpha65535(dest[i], a); + } + } +} + +/* + result = s * dia + dest = s * dia * ca + d * cia +*/ + +void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha) +{ + PRELOAD_INIT(dest) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + dest[i] = BYTE_MUL(color, qAlpha(~dest[i])); + } + } else { + color = BYTE_MUL(color, const_alpha); + int cia = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia); + } + } +} + +void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(color, 65535 - dest[i].alpha()); + } + } else { + uint ca = const_alpha * 257; + uint cia = 65535 - ca; + color = multiplyAlpha65535(color, ca); + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = interpolate65535(color, 65535 - d.alpha(), d, cia); + } + } +} + +void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i])); + } + } else { + int cia = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint s = BYTE_MUL(src[i], const_alpha); + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia); + } + } +} + +void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(src[i], 65535 - dest[i].alpha()); + } + } else { + uint ca = const_alpha * 257; + uint cia = 65535 - ca; + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + QRgba64 s = multiplyAlpha65535(src[i], ca); + dest[i] = interpolate65535(s, 65535 - d.alpha(), d, cia); + } + } +} + +/* + result = d * sia + dest = d * sia * ca + d * cia + = d * (sia * ca + cia) +*/ +void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha) +{ + uint a = qAlpha(~color); + if (const_alpha != 255) + a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + dest[i] = BYTE_MUL(dest[i], a); + } +} + +void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + uint a = 65535 - color.alpha(); + uint ca64k = const_alpha * 257; + if (const_alpha != 255) + a = qt_div_65535(a * ca64k) + 65535 - ca64k; + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(dest[i], a); + } +} + +void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i])); + } + } else { + int cia = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia; + dest[i] = BYTE_MUL(dest[i], sia); + } + } +} + +void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha65535(dest[i], 65535 - src[i].alpha()); + } + } else { + uint ca = const_alpha * 257; + uint cia = 65535 - ca; + for (int i = 0; i < length; ++i) { + uint a = qt_div_65535((65535 - src[i].alpha()) * ca) + cia; + dest[i] = multiplyAlpha65535(dest[i], a); + } + } +} + +/* + result = s*da + d*sia + dest = s*da*ca + d*sia*ca + d *cia + = s*ca * da + d * (sia*ca + cia) + = s*ca * da + d * (1 - sa*ca) +*/ +void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha != 255) { + color = BYTE_MUL(color, const_alpha); + } + uint sia = qAlpha(~color); + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia); + } +} + +void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha != 255) + color = multiplyAlpha255(color, const_alpha); + uint sia = 65535 - color.alpha(); + for (int i = 0; i < length; ++i) { + dest[i] = interpolate65535(color, dest[i].alpha(), dest[i], sia); + } +} + +void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint s = src[i]; + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); + } + } else { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint s = BYTE_MUL(src[i], const_alpha); + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); + } + } +} + +void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + QRgba64 s = src[i]; + QRgba64 d = dest[i]; + dest[i] = interpolate65535(s, d.alpha(), d, 65535 - s.alpha()); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 s = multiplyAlpha255(src[i], const_alpha); + QRgba64 d = dest[i]; + dest[i] = interpolate65535(s, d.alpha(), d, 65535 - s.alpha()); + } + } +} + +/* + result = d*sa + s*dia + dest = d*sa*ca + s*dia*ca + d *cia + = s*ca * dia + d * (sa*ca + cia) +*/ +void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha) +{ + uint a = qAlpha(color); + if (const_alpha != 255) { + color = BYTE_MUL(color, const_alpha); + a = qAlpha(color) + 255 - const_alpha; + } + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d)); + } +} + +void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + uint a = color.alpha(); + if (const_alpha != 255) { + color = multiplyAlpha255(color, const_alpha); + a = color.alpha() + 65535 - (const_alpha * 257); + } + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = interpolate65535(d, a, color, 65535 - d.alpha()); + } +} + +void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint s = src[i]; + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d)); + } + } else { + int cia = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint s = BYTE_MUL(src[i], const_alpha); + uint d = dest[i]; + uint a = qAlpha(s) + cia; + dest[i] = INTERPOLATE_PIXEL_255(d, a, s, qAlpha(~d)); + } + } +} + +void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + QRgba64 s = src[i]; + QRgba64 d = dest[i]; + dest[i] = interpolate65535(d, s.alpha(), s, 65535 - d.alpha()); + } + } else { + int ca = const_alpha * 257; + int cia = 65535 - ca; + for (int i = 0; i < length; ++i) { + QRgba64 s = multiplyAlpha65535(src[i], ca); + QRgba64 d = dest[i]; + uint a = s.alpha() + cia; + dest[i] = interpolate65535(d, a, s, 65535 - d.alpha()); + } + } +} + +/* + result = d*sia + s*dia + dest = d*sia*ca + s*dia*ca + d *cia + = s*ca * dia + d * (sia*ca + cia) + = s*ca * dia + d * (1 - sa*ca) +*/ +void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha != 255) + color = BYTE_MUL(color, const_alpha); + uint sia = qAlpha(~color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia); + } +} + +void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha != 255) + color = multiplyAlpha255(color, const_alpha); + uint sia = 65535 - color.alpha(); + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = interpolate65535(color, 65535 - d.alpha(), d, sia); + } +} + +void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + PRELOAD_INIT2(dest, src) + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); + } + } else { + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = BYTE_MUL(src[i], const_alpha); + dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); + } + } +} + +void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + QRgba64 s = src[i]; + dest[i] = interpolate65535(s, 65535 - d.alpha(), d, 65535 - s.alpha()); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + QRgba64 s = multiplyAlpha255(src[i], const_alpha); + dest[i] = interpolate65535(s, 65535 - d.alpha(), d, 65535 - s.alpha()); + } + } +} + +struct QFullCoverage { + inline void store(uint *dest, const uint src) const + { + *dest = src; + } +}; + +struct QPartialCoverage { + inline QPartialCoverage(uint const_alpha) + : ca(const_alpha) + , ica(255 - const_alpha) + { + } + + inline void store(uint *dest, const uint src) const + { + *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica); + } + +private: + const uint ca; + const uint ica; +}; + +static inline int mix_alpha(int da, int sa) +{ + return 255 - ((255 - sa) * (255 - da) >> 8); +} + +/* + Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa) + = Sca + Dca +*/ +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int length, uint color, const T &coverage) +{ + uint s = color; + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + d = comp_func_Plus_one_pixel(d, s); + coverage.store(&dest[i], d); + } +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl_rgb64(QRgba64 *dest, int length, QRgba64 color, const T &coverage) +{ + QRgba64 s = color; + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + d = comp_func_Plus_one_pixel(d, s); + coverage.store(&dest[i], d); + } +} + +void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Plus_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Plus_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = addWithSaturation(dest[i], color); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 d = addWithSaturation(dest[i], color); + dest[i] = interpolate255(d, const_alpha, dest[i], 255 - const_alpha); + } + } +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + d = comp_func_Plus_one_pixel(d, s); + + coverage.store(&dest[i], d); + } +} + +void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Plus_impl(dest, src, length, QFullCoverage()); + else + comp_func_Plus_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + dest[i] = addWithSaturation(dest[i], src[i]); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 d = addWithSaturation(dest[i], src[i]); + dest[i] = interpolate255(d, const_alpha, dest[i], 255 - const_alpha); + } + } +} + +/* + Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) +*/ +static inline int multiply_op(int dst, int src, int da, int sa) +{ + return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) multiply_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) multiply_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Multiply_impl(dest, src, length, QFullCoverage()); + else + comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) + = Sca + Dca - Sca.Dca +*/ +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) 255 - qt_div_255((255-a) * (255-b)) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Screen_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) 255 - (((255-a) * (255-b)) >> 8) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Screen_impl(dest, src, length, QFullCoverage()); + else + comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + if 2.Dca < Da + Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + otherwise + Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) +*/ +static inline int overlay_op(int dst, int src, int da, int sa) +{ + const int temp = src * (255 - da) + dst * (255 - sa); + if (2 * dst < da) + return qt_div_255(2 * src * dst + temp); + else + return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) overlay_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) overlay_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Overlay_impl(dest, src, length, QFullCoverage()); + else + comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + Da' = Sa + Da - Sa.Da +*/ +static inline int darken_op(int dst, int src, int da, int sa) +{ + return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) darken_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Darken_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) darken_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Darken_impl(dest, src, length, QFullCoverage()); + else + comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + Da' = Sa + Da - Sa.Da +*/ +static inline int lighten_op(int dst, int src, int da, int sa) +{ + return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) lighten_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) lighten_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Lighten_impl(dest, src, length, QFullCoverage()); + else + comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + if Sca.Da + Dca.Sa >= Sa.Da + Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + otherwise + Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) +*/ +static inline int color_dodge_op(int dst, int src, int da, int sa) +{ + const int sa_da = sa * da; + const int dst_sa = dst * sa; + const int src_da = src * da; + + const int temp = src * (255 - da) + dst * (255 - sa); + if (src_da + dst_sa >= sa_da) + return qt_div_255(sa_da + temp); + else + return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a,b) color_dodge_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) color_dodge_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_ColorDodge_impl(dest, src, length, QFullCoverage()); + else + comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + if Sca.Da + Dca.Sa <= Sa.Da + Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + otherwise + Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) +*/ +static inline int color_burn_op(int dst, int src, int da, int sa) +{ + const int src_da = src * da; + const int dst_sa = dst * sa; + const int sa_da = sa * da; + + const int temp = src * (255 - da) + dst * (255 - sa); + + if (src == 0 || src_da + dst_sa <= sa_da) + return qt_div_255(temp); + return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) color_burn_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) color_burn_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_ColorBurn_impl(dest, src, length, QFullCoverage()); + else + comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + if 2.Sca < Sa + Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + otherwise + Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) +*/ +static inline uint hardlight_op(int dst, int src, int da, int sa) +{ + const uint temp = src * (255 - da) + dst * (255 - sa); + + if (2 * src < sa) + return qt_div_255(2 * src * dst + temp); + else + return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) hardlight_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) hardlight_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_HardLight_impl(dest, src, length, QFullCoverage()); + else + comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + if 2.Sca <= Sa + Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) + otherwise if 2.Sca > Sa and 4.Dca <= Da + Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) + otherwise if 2.Sca > Sa and 4.Dca > Da + Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) +*/ +static inline int soft_light_op(int dst, int src, int da, int sa) +{ + const int src2 = src << 1; + const int dst_np = da != 0 ? (255 * dst) / da : 0; + const int temp = (src * (255 - da) + dst * (255 - sa)) * 255; + + if (src2 < sa) + return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025; + else if (4 * dst <= da) + return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025; + else { + return (dst * sa * 255 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025; + } +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) soft_light_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) soft_light_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_SoftLight_impl(dest, src, length, QFullCoverage()); + else + comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa) + = Sca + Dca - 2.min(Sca.Da, Dca.Sa) +*/ +static inline int difference_op(int dst, int src, int da, int sa) +{ + return src + dst - qt_div_255(2 * qMin(src * da, dst * sa)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) difference_op(a, b, da, sa) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Difference_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) difference_op(a, b, da, sa) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Difference_impl(dest, src, length, QFullCoverage()); + else + comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +/* + Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) +*/ +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage) +{ + int sa = qAlpha(color); + int sr = qRed(color); + int sg = qGreen(color); + int sb = qBlue(color); + + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) + uint d = dest[i]; + int da = qAlpha(d); + +#define OP(a, b) (a + b - qt_div_255(2*(a*b))) + int r = OP( qRed(d), sr); + int b = OP( qBlue(d), sb); + int g = OP(qGreen(d), sg); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + +template <typename T> +Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) + uint d = dest[i]; + uint s = src[i]; + + int da = qAlpha(d); + int sa = qAlpha(s); + +#define OP(a, b) (a + b - ((a*b) >> 7)) + int r = OP( qRed(d), qRed(s)); + int b = OP( qBlue(d), qBlue(s)); + int g = OP(qGreen(d), qGreen(s)); + int a = mix_alpha(da, sa); +#undef OP + + coverage.store(&dest[i], qRgba(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Exclusion_impl(dest, src, length, QFullCoverage()); + else + comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha)); +} + +void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) + *dest++ |= color; +} + +void QT_FASTCALL rasterop_SourceOrDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) + *dest++ |= *src++; +} + +void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + color |= 0xff000000; + while (length--) + *dest++ &= color; +} + +void QT_FASTCALL rasterop_SourceAndDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (*src & *dest) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + color &= 0x00ffffff; + while (length--) + *dest++ ^= color; +} + +void QT_FASTCALL rasterop_SourceXorDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (*src ^ *dest) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + color = ~color; + while (length--) { + *dest = (color & ~(*dest)) | 0xff000000; + ++dest; + } +} + +void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (~(*src) & ~(*dest)) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + color = ~color | 0xff000000; + while (length--) { + *dest = color | ~(*dest); + ++dest; + } +} + +void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = ~(*src) | ~(*dest) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + color = ~color & 0x00ffffff; + while (length--) { + *dest = color ^ (*dest); + ++dest; + } +} + +void QT_FASTCALL rasterop_NotSourceXorDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = ((~(*src)) ^ (*dest)) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, + uint color, uint const_alpha) +{ + Q_UNUSED(const_alpha); + qt_memfill(dest, ~color | 0xff000000, length); +} + +void QT_FASTCALL rasterop_NotSource(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, + int length, uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) + *dest++ = ~(*src++) | 0xff000000; +} + +void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + color = ~color | 0xff000000; + while (length--) { + *dest = color & *dest; + ++dest; + } +} + +void QT_FASTCALL rasterop_NotSourceAndDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (~(*src) & *dest) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (color & ~(*dest)) | 0xff000000; + ++dest; + } +} + +void QT_FASTCALL rasterop_SourceAndNotDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (*src & ~(*dest)) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (~(*src) | *dest) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + color = ~color | 0xff000000; + while (length--) + *dest++ |= color; +} + +void QT_FASTCALL rasterop_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (*src | ~(*dest)) | 0xff000000; + ++dest; ++src; + } +} + +void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(const_alpha); + while (length--) { + *dest = (color | ~(*dest)) | 0xff000000; + ++dest; + } +} + +void QT_FASTCALL rasterop_ClearDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(src); + comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha); +} + +void QT_FASTCALL rasterop_solid_ClearDestination(uint *Q_DECL_RESTRICT dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(color); + comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha); +} + +void QT_FASTCALL rasterop_SetDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(src); + comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha); +} + +void QT_FASTCALL rasterop_solid_SetDestination(uint *Q_DECL_RESTRICT dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(color); + comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha); +} + +void QT_FASTCALL rasterop_NotDestination(uint *Q_DECL_RESTRICT dest, + const uint *Q_DECL_RESTRICT src, + int length, + uint const_alpha) +{ + Q_UNUSED(src); + rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha); +} + +void QT_FASTCALL rasterop_solid_NotDestination(uint *Q_DECL_RESTRICT dest, + int length, + uint color, + uint const_alpha) +{ + Q_UNUSED(color); + rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha); +} + +CompositionFunctionSolid qt_functionForModeSolid_C[] = { + comp_func_solid_SourceOver, + comp_func_solid_DestinationOver, + comp_func_solid_Clear, + comp_func_solid_Source, + comp_func_solid_Destination, + comp_func_solid_SourceIn, + comp_func_solid_DestinationIn, + comp_func_solid_SourceOut, + comp_func_solid_DestinationOut, + comp_func_solid_SourceAtop, + comp_func_solid_DestinationAtop, + comp_func_solid_XOR, + comp_func_solid_Plus, + comp_func_solid_Multiply, + comp_func_solid_Screen, + comp_func_solid_Overlay, + comp_func_solid_Darken, + comp_func_solid_Lighten, + comp_func_solid_ColorDodge, + comp_func_solid_ColorBurn, + comp_func_solid_HardLight, + comp_func_solid_SoftLight, + comp_func_solid_Difference, + comp_func_solid_Exclusion, + rasterop_solid_SourceOrDestination, + rasterop_solid_SourceAndDestination, + rasterop_solid_SourceXorDestination, + rasterop_solid_NotSourceAndNotDestination, + rasterop_solid_NotSourceOrNotDestination, + rasterop_solid_NotSourceXorDestination, + rasterop_solid_NotSource, + rasterop_solid_NotSourceAndDestination, + rasterop_solid_SourceAndNotDestination, + rasterop_solid_NotSourceOrDestination, + rasterop_solid_SourceOrNotDestination, + rasterop_solid_ClearDestination, + rasterop_solid_SetDestination, + rasterop_solid_NotDestination +}; + +CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = { + comp_func_solid_SourceOver_rgb64, + comp_func_solid_DestinationOver_rgb64, + comp_func_solid_Clear_rgb64, + comp_func_solid_Source_rgb64, + comp_func_solid_Destination_rgb64, + comp_func_solid_SourceIn_rgb64, + comp_func_solid_DestinationIn_rgb64, + comp_func_solid_SourceOut_rgb64, + comp_func_solid_DestinationOut_rgb64, + comp_func_solid_SourceAtop_rgb64, + comp_func_solid_DestinationAtop_rgb64, + comp_func_solid_XOR_rgb64, + comp_func_solid_Plus_rgb64, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +CompositionFunction qt_functionForMode_C[] = { + comp_func_SourceOver, + comp_func_DestinationOver, + comp_func_Clear, + comp_func_Source, + comp_func_Destination, + comp_func_SourceIn, + comp_func_DestinationIn, + comp_func_SourceOut, + comp_func_DestinationOut, + comp_func_SourceAtop, + comp_func_DestinationAtop, + comp_func_XOR, + comp_func_Plus, + comp_func_Multiply, + comp_func_Screen, + comp_func_Overlay, + comp_func_Darken, + comp_func_Lighten, + comp_func_ColorDodge, + comp_func_ColorBurn, + comp_func_HardLight, + comp_func_SoftLight, + comp_func_Difference, + comp_func_Exclusion, + rasterop_SourceOrDestination, + rasterop_SourceAndDestination, + rasterop_SourceXorDestination, + rasterop_NotSourceAndNotDestination, + rasterop_NotSourceOrNotDestination, + rasterop_NotSourceXorDestination, + rasterop_NotSource, + rasterop_NotSourceAndDestination, + rasterop_SourceAndNotDestination, + rasterop_NotSourceOrDestination, + rasterop_SourceOrNotDestination, + rasterop_ClearDestination, + rasterop_SetDestination, + rasterop_NotDestination +}; + +CompositionFunction64 qt_functionForMode64_C[] = { + comp_func_SourceOver_rgb64, + comp_func_DestinationOver_rgb64, + comp_func_Clear_rgb64, + comp_func_Source_rgb64, + comp_func_Destination_rgb64, + comp_func_SourceIn_rgb64, + comp_func_DestinationIn_rgb64, + comp_func_SourceOut_rgb64, + comp_func_DestinationOut_rgb64, + comp_func_SourceAtop_rgb64, + comp_func_DestinationAtop_rgb64, + comp_func_XOR_rgb64, + comp_func_Plus_rgb64, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +QT_END_NAMESPACE diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index 8fb5f4fd3f..61d57ca3f8 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -33,6 +33,7 @@ #include "qcosmeticstroker_p.h" #include "private/qpainterpath_p.h" +#include "private/qrgba64_p.h" #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -280,7 +281,7 @@ void QCosmeticStroker::setup() drawCaps = state->lastPen.capStyle() != Qt::FlatCap; if (strokeSelection & FastDraw) { - color = INTERPOLATE_PIXEL_256(state->penData.solid.color, opacity, 0, 0); + color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32(); QRasterBuffer *buffer = state->penData.rasterBuffer; pixels = (uint *)buffer->buffer(); ppl = buffer->bytesPerLine()>>2; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index d74b48a3ca..07e5a3d19b 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -51,6 +51,7 @@ #include <private/qdrawhelper_mips_dsp_p.h> #endif #include <private/qguiapplication_p.h> +#include <private/qrgba64_p.h> #include <qmath.h> QT_BEGIN_NAMESPACE @@ -184,6 +185,36 @@ static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int } template<QImage::Format Format> +static const QRgba64 *QT_FASTCALL convertToRGB64(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1); + Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1); + Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1); + + Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>(); + Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>(); + Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>(); + + Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8; + Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8; + Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8; + + for (int i = 0; i < count; ++i) { + uint red = (src[i] >> redShift<Format>()) & redMask; + uint green = (src[i] >> greenShift<Format>()) & greenMask; + uint blue = (src[i] >> blueShift<Format>()) & blueMask; + + red = ((red << redLeftShift) | (red >> redRightShift)) << 16; + green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8; + blue = (blue << blueLeftShift) | (blue >> blueRightShift); + buffer[i] = QRgba64::fromRgba(red, green, blue, 255); + } + + return buffer; +} + +template<QImage::Format Format> static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -219,6 +250,41 @@ static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint } template<QImage::Format Format> +static const QRgba64 *QT_FASTCALL convertARGBPMToARGB64PM(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1); + Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1); + Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1); + Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1); + + Q_CONSTEXPR uchar alphaLeftShift = 8 - alphaWidth<Format>(); + Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>(); + Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>(); + Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>(); + + Q_CONSTEXPR uchar alphaRightShift = 2 * alphaWidth<Format>() - 8; + Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8; + Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8; + Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8; + + for (int i = 0; i < count; ++i) { + uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask; + uint red = (src[i] >> redShift<Format>()) & redMask; + uint green = (src[i] >> greenShift<Format>()) & greenMask; + uint blue = (src[i] >> blueShift<Format>()) & blueMask; + + alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift); + red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift)); + green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift)); + blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift)); + buffer[i] = QRgba64::fromRgba(red, green, blue, alpha); + } + + return buffer; +} + +template<QImage::Format Format> static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -320,7 +386,8 @@ template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixe false, bitsPerPixel<Format>(), convertToRGB32<Format>, convertRGBFromARGB32PM<Format>, - convertRGBFromRGB32<Format> + convertRGBFromRGB32<Format>, + convertToRGB64<Format> }; } @@ -334,7 +401,8 @@ template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixe true, bitsPerPixel<Format>(), convertARGBPMToARGB32PM<Format>, convertARGBPMFromARGB32PM<Format>, - convertARGBPMFromRGB32<Format> + convertARGBPMFromRGB32<Format>, + convertARGBPMToARGB64PM<Format> }; } @@ -349,6 +417,14 @@ static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint return buffer; } +static const QRgba64 *QT_FASTCALL convertIndexedToARGB64PM(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *clut) +{ + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromArgb32(clut[src[i]]).premultiplied(); + return buffer; +} + static const uint *QT_FASTCALL convertPassThrough(uint *, const uint *src, int, const QPixelLayout *, const QRgb *) { @@ -391,6 +467,22 @@ static const uint *QT_FASTCALL convertGrayscale8ToRGB32(uint *buffer, const uint return buffer; } +static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromRgba(0, 0, 0, src[i]); + return buffer; +} + +static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromRgba(src[i], src[i], src[i], 255); + return buffer; +} + static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -407,6 +499,111 @@ static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const return buffer; } +#ifdef __SSE2__ +template<bool RGBA, bool maskAlpha> +static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count) +{ + const __m128i amask = _mm_set1_epi32(0xff000000); + int i = 0; + if (((uintptr_t)buffer & 0xf) && count > 0) { + uint s = *src++; + if (RGBA) + s = RGBA2ARGB(s); + *buffer++ = QRgba64::fromArgb32(s); + i++; + } + for (; i < count-3; i += 4) { + __m128i vs = _mm_loadu_si128((const __m128i*)src); + if (maskAlpha) + vs = _mm_or_si128(vs, amask); + src += 4; + __m128i v1 = _mm_unpacklo_epi8(vs, vs); + __m128i v2 = _mm_unpackhi_epi8(vs, vs); + if (!RGBA) { + v1 = _mm_shufflelo_epi16(v1, _MM_SHUFFLE(3, 0, 1, 2)); + v2 = _mm_shufflelo_epi16(v2, _MM_SHUFFLE(3, 0, 1, 2)); + v1 = _mm_shufflehi_epi16(v1, _MM_SHUFFLE(3, 0, 1, 2)); + v2 = _mm_shufflehi_epi16(v2, _MM_SHUFFLE(3, 0, 1, 2)); + } + _mm_store_si128((__m128i*)(buffer), v1); + buffer += 2; + _mm_store_si128((__m128i*)(buffer), v2); + buffer += 2; + } + + for (; i < count; ++i) { + uint s = *src++; + if (RGBA) + s = RGBA2ARGB(s); + *buffer++ = QRgba64::fromArgb32(s); + } +} +#endif + +static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ +#ifdef __SSE2__ + qConvertARGB32PMToARGB64PM_sse2<false, true>(buffer, src, count); +#else + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromArgb32(0xff000000 | src[i]); +#endif + return buffer; +} + +static const QRgba64 *QT_FASTCALL convertARGB32ToARGB64PM(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ +#ifdef __SSE2__ + qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count); + for (int i = 0; i < count; ++i) + buffer[i] = buffer[i].premultiplied(); +#else + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied(); +#endif + return buffer; +} + +static const QRgba64 *QT_FASTCALL convertARGB32PMToARGB64PM(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ +#ifdef __SSE2__ + qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count); +#else + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromArgb32(src[i]); +#endif + return buffer; +} + +static const QRgba64 *QT_FASTCALL convertRGBA8888ToARGB64PM(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ +#ifdef __SSE2__ + qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count); + for (int i = 0; i < count; ++i) + buffer[i] = buffer[i].premultiplied(); +#else + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i])).premultiplied(); +#endif + return buffer; +} + +static const QRgba64 *QT_FASTCALL convertRGBA8888PMToARGB64PM(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ +#ifdef __SSE2__ + qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count); +#else + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i])); +#endif + return buffer; +} + static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -440,6 +637,60 @@ static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const ui return buffer; } +#ifdef __SSE2__ +template<QtPixelOrder PixelOrder> +static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count) +{ + const __m128i rmask = _mm_set1_epi32(0x3ff00000); + const __m128i gmask = _mm_set1_epi32(0x000ffc00); + const __m128i bmask = _mm_set1_epi32(0x000003ff); + const __m128i afactor = _mm_set1_epi16(0x5555); + int i = 0; + if (((uintptr_t)buffer & 0xf) && count > 0) { + *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++); + i++; + } + for (; i < count-3; i += 4) { + __m128i vs = _mm_loadu_si128((const __m128i*)src); + src += 4; + __m128i va = _mm_srli_epi32(vs, 30); + __m128i vr = _mm_and_si128(vs, rmask); + __m128i vb = _mm_and_si128(vs, bmask); + __m128i vg = _mm_and_si128(vs, gmask); + va = _mm_mullo_epi16(va, afactor); + vr = _mm_or_si128(_mm_srli_epi32(vr, 14), _mm_srli_epi32(vr, 24)); + vg = _mm_or_si128(_mm_srli_epi32(vg, 4), _mm_srli_epi32(vg, 14)); + vb = _mm_or_si128(_mm_slli_epi32(vb, 6), _mm_srli_epi32(vb, 4)); + __m128i vrb; + if (PixelOrder == PixelOrderRGB) + vrb = _mm_or_si128(vr, _mm_slli_si128(vb, 2)); + else + vrb = _mm_or_si128(vb, _mm_slli_si128(vr, 2)); + __m128i vga = _mm_or_si128(vg, _mm_slli_si128(va, 2)); + _mm_store_si128((__m128i*)(buffer), _mm_unpacklo_epi16(vrb, vga)); + buffer += 2; + _mm_store_si128((__m128i*)(buffer), _mm_unpackhi_epi16(vrb, vga)); + buffer += 2; + } + + for (; i < count; ++i) + *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++); +} +#endif + +template<QtPixelOrder PixelOrder> +static const QRgba64 *QT_FASTCALL convertA2RGB30PMToARGB64PM(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ +#ifdef __SSE2__ + qConvertA2RGB30PMToARGB64PM_sse2<PixelOrder>(buffer, src, count); +#else + for (int i = 0; i < count; ++i) + buffer[i] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]); +#endif + return buffer; +} + template<QtPixelOrder PixelOrder> static const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) @@ -601,15 +852,15 @@ inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint // convertFromArgb32() assumes that no color channel is more than 8 bits. // QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits. QPixelLayout qPixelLayouts[QImage::NImageFormats] = { - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0, 0 }, // Format_Invalid - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0, 0 }, // Format_Mono - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0, 0 }, // Format_MonoLSB - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0, 0 }, // Format_Indexed8 + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0, 0, 0 }, // Format_Invalid + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Mono + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_MonoLSB + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Indexed8 // Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong, // but everywhere this generic conversion would be wrong is currently overloaded. - { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough }, // Format_RGB32 - { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough }, // Format_ARGB32 - { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough }, // Format_ARGB32_Premultiplied + { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB32ToRGB64 }, // Format_RGB32 + { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertARGB32ToARGB64PM }, // Format_ARGB32 + { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertARGB32PMToARGB64PM }, // Format_ARGB32_Premultiplied #ifdef Q_COMPILER_CONSTEXPR pixelLayoutRGB<QImage::Format_RGB16>(), pixelLayoutARGBPM<QImage::Format_ARGB8565_Premultiplied>(), @@ -624,55 +875,73 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { { 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32<QImage::Format_RGB16>, convertRGBFromARGB32PM<QImage::Format_RGB16>, - convertRGBFromRGB32<QImage::Format_RGB16>}, + convertRGBFromRGB32<QImage::Format_RGB16>, + convertToRGB64<QImage::Format_RGB16>, + }, { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertARGBPMToARGB32PM<QImage::Format_ARGB8565_Premultiplied>, convertARGBPMFromARGB32PM<QImage::Format_ARGB8565_Premultiplied>, - convertARGBPMFromRGB32<QImage::Format_ARGB8565_Premultiplied>}, + convertARGBPMFromRGB32<QImage::Format_ARGB8565_Premultiplied>, + convertARGBPMToARGB64PM<QImage::Format_ARGB8565_Premultiplied>, + }, { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32<QImage::Format_RGB666>, convertRGBFromARGB32PM<QImage::Format_RGB666>, - convertRGBFromRGB32<QImage::Format_RGB666>}, + convertRGBFromRGB32<QImage::Format_RGB666>, + convertToRGB64<QImage::Format_RGB666>, + }, { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24, convertARGBPMToARGB32PM<QImage::Format_ARGB6666_Premultiplied>, convertARGBPMFromARGB32PM<QImage::Format_ARGB6666_Premultiplied>, - convertARGBPMFromRGB32<QImage::Format_ARGB6666_Premultiplied>}, + convertARGBPMFromRGB32<QImage::Format_ARGB6666_Premultiplied>, + convertARGBPMToARGB64PM<QImage::Format_ARGB6666_Premultiplied>, + }, { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32<QImage::Format_RGB555>, convertRGBFromARGB32PM<QImage::Format_RGB555>, - convertRGBFromRGB32<QImage::Format_RGB555> }, + convertRGBFromRGB32<QImage::Format_RGB555>, + convertToRGB64<QImage::Format_RGB555>, + }, { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertARGBPMToARGB32PM<QImage::Format_ARGB8555_Premultiplied>, convertARGBPMFromARGB32PM<QImage::Format_ARGB8555_Premultiplied>, - convertARGBPMFromRGB32<QImage::Format_ARGB8555_Premultiplied>}, + convertARGBPMFromRGB32<QImage::Format_ARGB8555_Premultiplied>, + convertARGBPMToARGB64PM<QImage::Format_ARGB8555_Premultiplied>, + }, { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32<QImage::Format_RGB888>, convertRGBFromARGB32PM<QImage::Format_RGB888>, - convertRGBFromRGB32<QImage::Format_RGB888>}, + convertRGBFromRGB32<QImage::Format_RGB888>, + convertToRGB64<QImage::Format_RGB888>, + }, { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32<QImage::Format_RGB444>, convertRGBFromARGB32PM<QImage::Format_RGB444>, - convertRGBFromRGB32<QImage::Format_RGB444>}, + convertRGBFromRGB32<QImage::Format_RGB444>, + convertToRGB64<QImage::Format_RGB444>, + }, { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, convertARGBPMToARGB32PM<QImage::Format_ARGB4444_Premultiplied>, convertARGBPMFromARGB32PM<QImage::Format_ARGB4444_Premultiplied>, - convertARGBPMFromRGB32<QImage::Format_ARGB4444_Premultiplied>}, + convertARGBPMFromRGB32<QImage::Format_ARGB4444_Premultiplied>, + convertARGBPMToARGB64PM<QImage::Format_ARGB4444_Premultiplied>, + }, #endif #if Q_BYTE_ORDER == Q_BIG_ENDIAN - { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888 - { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBA8888 - { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32}, // Format_RGBA8888_Premultiplied + { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888 + { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 + { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM}, // Format_RGBA8888_Premultiplied #else - { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888 - { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBA8888 (ABGR32) - { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBA8888_Premultiplied + { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888 + { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 (ABGR32) + { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBA8888_Premultiplied #endif - { 10, 20, 10, 10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR> }, // Format_BGR30 - { 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied - { 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB> }, // Format_RGB30 - { 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied - { 0, 0, 0, 0, 0, 0, 8, 0, false, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0 }, // Format_Alpha8 - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32 } // Format_Grayscale8 + { 10, 20, 10, 10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_BGR30 + { 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied + { 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_RGB30 + { 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied + { 0, 0, 0, 0, 0, 0, 8, 0, false, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8 + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8 }; const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = { @@ -758,6 +1027,20 @@ static uint *QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, in return const_cast<uint *>(layout->convertToARGB32PM(buffer, ptr, length, layout, 0)); } +static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) +{ + const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; + uint buffer32[buffer_size]; + const uint *ptr = qFetchPixels[layout->bpp](buffer32, rasterBuffer->scanLine(y), x, length); + return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, ptr, length, layout, 0)); +} + +static QRgba64 *QT_FASTCALL destFetch64uint32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) +{ + const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; + const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x; + return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, src, length, layout, 0)); +} static DestFetchProc destFetchProc[QImage::NImageFormats] = { @@ -788,6 +1071,35 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] = destFetch, // Format_Grayscale8 }; +static DestFetchProc64 destFetchProc64[QImage::NImageFormats] = +{ + 0, // Format_Invalid + destFetch64, // Format_Mono, + destFetch64, // Format_MonoLSB + 0, // Format_Indexed8 + destFetch64uint32, // Format_RGB32 + destFetch64uint32, // Format_ARGB32, + destFetch64uint32, // Format_ARGB32_Premultiplied + destFetch64, // Format_RGB16 + destFetch64, // Format_ARGB8565_Premultiplied + destFetch64, // Format_RGB666 + destFetch64, // Format_ARGB6666_Premultiplied + destFetch64, // Format_RGB555 + destFetch64, // Format_ARGB8555_Premultiplied + destFetch64, // Format_RGB888 + destFetch64, // Format_RGB444 + destFetch64, // Format_ARGB4444_Premultiplied + destFetch64uint32, // Format_RGBX8888 + destFetch64uint32, // Format_RGBA8888 + destFetch64uint32, // Format_RGBA8888_Premultiplied + destFetch64uint32, // Format_BGR30 + destFetch64uint32, // Format_A2BGR30_Premultiplied + destFetch64uint32, // Format_RGB30 + destFetch64uint32, // Format_A2RGB30_Premultiplied + destFetch64, // Format_Alpha8 + destFetch64, // Format_Grayscale8 +}; + /* Returns the color in the mono destination color table that is the "nearest" to /color/. @@ -904,6 +1216,97 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con } } +static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length) +{ + for (int i = 0; i < length; ++i) { + dest[i] = src[i].toArgb32(); + } +} + +static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint buf[buffer_size]; + const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; + StorePixelsFunc store = qStorePixels[layout->bpp]; + uchar *dest = rasterBuffer->scanLine(y); + while (length) { + int l = qMin(length, buffer_size); + const uint *ptr = 0; + convertFromRgb64(buf, buffer, l); + if (!layout->premultiplied && !layout->alphaWidth) + ptr = layout->convertFromRGB32(buf, buf, l, layout, 0); + else + ptr = layout->convertFromARGB32PM(buf, buf, l, layout, 0); + store(dest, ptr, x, l); + length -= l; + buffer += l; + x += l; + } +} + +#ifdef __SSE2__ +template<QtPixelOrder PixelOrder> +static inline void qConvertARGB64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *buffer, int count) +{ + const __m128i gmask = _mm_set1_epi32(0x000ffc00); + const __m128i cmask = _mm_set1_epi32(0x000003ff); + int i = 0; + __m128i vr, vg, vb, va; + for (; i < count-1; i += 2) { + __m128i vs = _mm_loadu_si128((const __m128i*)buffer); + buffer += 2; + vr = _mm_srli_epi64(vs, 6); + vg = _mm_srli_epi64(vs, 16 + 6 - 10); + vb = _mm_srli_epi64(vs, 32 + 6); + vr = _mm_and_si128(vr, cmask); + vg = _mm_and_si128(vg, gmask); + vb = _mm_and_si128(vb, cmask); + va = _mm_srli_epi64(vs, 48 + 14); + if (PixelOrder == PixelOrderRGB) + vr = _mm_slli_epi32(vr, 20); + else + vb = _mm_slli_epi32(vb, 20); + va = _mm_slli_epi32(va, 30); + __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va)); + vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0)); + _mm_storel_epi64((__m128i*)dest, vd); + dest += 2; + } + + for (; i < count; ++i) + *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++); +} +#endif + +static void QT_FASTCALL destStore64ARGB32(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint *dest = (uint*)rasterBuffer->scanLine(y) + x; + for (int i = 0; i < length; ++i) { + dest[i] = buffer[i].unpremultiplied().toArgb32(); + } +} + +static void QT_FASTCALL destStore64RGBA8888(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint *dest = (uint*)rasterBuffer->scanLine(y) + x; + for (int i = 0; i < length; ++i) { + dest[i] = ARGB2RGBA(buffer[i].unpremultiplied().toArgb32()); + } +} + +template<QtPixelOrder PixelOrder> +static void QT_FASTCALL destStore64RGB30(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint *dest = (uint*)rasterBuffer->scanLine(y) + x; +#ifdef __SSE2__ + qConvertARGB64PMToA2RGB30PM_sse2<PixelOrder>(dest, buffer, length); +#else + for (int i = 0; i < length; ++i) { + dest[i] = qConvertRgb64ToRgb30<PixelOrder>(buffer[i]); + } +#endif +} + static DestStoreProc destStoreProc[QImage::NImageFormats] = { 0, // Format_Invalid @@ -933,6 +1336,35 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] = destStore, // Format_Grayscale8 }; +static DestStoreProc64 destStoreProc64[QImage::NImageFormats] = +{ + 0, // Format_Invalid + destStore64, // Format_Mono, + destStore64, // Format_MonoLSB + 0, // Format_Indexed8 + destStore64, // Format_RGB32 + destStore64ARGB32, // Format_ARGB32, + destStore64, // Format_ARGB32_Premultiplied + destStore64, // Format_RGB16 + destStore64, // Format_ARGB8565_Premultiplied + destStore64, // Format_RGB666 + destStore64, // Format_ARGB6666_Premultiplied + destStore64, // Format_RGB555 + destStore64, // Format_ARGB8555_Premultiplied + destStore64, // Format_RGB888 + destStore64, // Format_RGB444 + destStore64, // Format_ARGB4444_Premultiplied + destStore64, // Format_RGBX8888 + destStore64RGBA8888, // Format_RGBA8888 + destStore64, // Format_RGBA8888_Premultiplied + destStore64RGB30<PixelOrderBGR>, // Format_BGR30 + destStore64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied + destStore64RGB30<PixelOrderRGB>, // Format_RGB30 + destStore64RGB30<PixelOrderRGB>, // Format_A2RGB30_Premultiplied + destStore64, // Format_Alpha8 + destStore64, // Format_Grayscale8 +}; + /* Source fetches @@ -988,6 +1420,21 @@ static const uint *QT_FASTCALL fetchUntransformedRGB16(uint *buffer, const Opera return buffer; } +static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Operator *, + const QSpanData *data, int y, int x, int length) +{ + const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; + const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0; + if (layout->bpp != QPixelLayout::BPP32) { + uint buffer32[buffer_size]; + const uint *ptr = qFetchPixels[layout->bpp](buffer32, data->texture.scanLine(y), x, length); + return layout->convertToARGB64PM(buffer, ptr, length, layout, clut); + } else { + const uint *src = (const uint *)data->texture.scanLine(y) + x; + return layout->convertToARGB64PM(buffer, src, length, layout, clut); + } +} + // blendType is either BlendTransformed or BlendTransformedTiled template<TextureBlendType blendType> static const uint *QT_FASTCALL fetchTransformedARGB32PM(uint *buffer, const Operator *, const QSpanData *data, @@ -1155,6 +1602,111 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, return layout->convertToARGB32PM(buffer, buffer, length, layout, clut); } +template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */ +static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Operator *, const QSpanData *data, + int y, int x, int length) +{ + int image_width = data->texture.width; + int image_height = data->texture.height; + + const qreal cx = x + qreal(0.5); + const qreal cy = y + qreal(0.5); + + const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0; + + uint buffer32[buffer_size]; + QRgba64 *b = buffer; + if (data->fast_matrix) { + // The increment pr x in the scanline + int fdx = (int)(data->m11 * fixed_scale); + int fdy = (int)(data->m12 * fixed_scale); + + int fx = int((data->m21 * cy + + data->m11 * cx + data->dx) * fixed_scale); + int fy = int((data->m22 * cy + + data->m12 * cx + data->dy) * fixed_scale); + + int i = 0, j = 0; + while (i < length) { + if (j == buffer_size) { + layout->convertToARGB64PM(b, buffer32, buffer_size, layout, clut); + b += buffer_size; + j = 0; + } + int px = fx >> 16; + int py = fy >> 16; + + if (blendType == BlendTransformedTiled) { + px %= image_width; + py %= image_height; + if (px < 0) px += image_width; + if (py < 0) py += image_height; + } else { + px = qBound(0, px, image_width - 1); + py = qBound(0, py, image_height - 1); + } + buffer32[j] = fetch(data->texture.scanLine(py), px); + + fx += fdx; + fy += fdy; + ++i; ++j; + } + if (j > 0) { + layout->convertToARGB64PM(b, buffer32, j, layout, clut); + b += j; + } + } else { + const qreal fdx = data->m11; + const qreal fdy = data->m12; + const qreal fdw = data->m13; + + qreal fx = data->m21 * cy + data->m11 * cx + data->dx; + qreal fy = data->m22 * cy + data->m12 * cx + data->dy; + qreal fw = data->m23 * cy + data->m13 * cx + data->m33; + + int i = 0, j = 0; + while (i < length) { + if (j == buffer_size) { + layout->convertToARGB64PM(b, buffer32, buffer_size, layout, clut); + b += buffer_size; + j = 0; + } + const qreal iw = fw == 0 ? 1 : 1 / fw; + const qreal tx = fx * iw; + const qreal ty = fy * iw; + int px = int(tx) - (tx < 0); + int py = int(ty) - (ty < 0); + + if (blendType == BlendTransformedTiled) { + px %= image_width; + py %= image_height; + if (px < 0) px += image_width; + if (py < 0) py += image_height; + } else { + px = qBound(0, px, image_width - 1); + py = qBound(0, py, image_height - 1); + } + buffer32[j] = fetch(data->texture.scanLine(py), px); + + fx += fdx; + fy += fdy; + fw += fdw; + //force increment to avoid /0 + if (!fw) { + fw += fdw; + } + ++i; ++j; + } + if (j > 0) { + layout->convertToARGB64PM(b, buffer32, j, layout, clut); + b += j; + } + } + return buffer; +} + /** \internal interpolate 4 argb pixels with the distx and disty factor. distx and disty bust be between 0 and 16 @@ -1245,6 +1797,42 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i } #endif +#if defined(__SSE2__) +static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty) +{ + const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0)); + const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0)); + + __m128i vt = _mm_loadu_si128((const __m128i*)t); + if (disty) { + __m128i vb = _mm_loadu_si128((const __m128i*)b); + vt = _mm_mulhi_epu16(vt, _mm_set1_epi16(0x10000 - disty)); + vb = _mm_mulhi_epu16(vb, _mm_set1_epi16(disty)); + vt = _mm_add_epi16(vt, vb); + } + vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx)); + vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8)); +#ifdef Q_PROCESSOR_X86_64 + return QRgba64::fromRgba64(_mm_cvtsi128_si64(vt)); +#else + QRgba64 out; + _mm_storel_epi64((__m128i*)&out, vt); + return out; +#endif +} +#else +static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty) +{ + const uint dx = distx>>8; + const uint dy = disty>>8; + const uint idx = 256 - dx; + const uint idy = 256 - dy; + QRgba64 xtop = interpolate256(t[0], idx, t[1], dx); + QRgba64 xbot = interpolate256(b[0], idx, b[1], dx); + return interpolate256(xtop, idy, xbot, dy); +} +#endif + template<TextureBlendType blendType> void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2); @@ -2130,6 +2718,349 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper return buffer; } +template<TextureBlendType blendType> +static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, const Operator *, + const QSpanData *data, int y, int x, int length) +{ + const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; + const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0; + + int image_width = data->texture.width; + int image_height = data->texture.height; + + int image_x1 = data->texture.x1; + int image_y1 = data->texture.y1; + int image_x2 = data->texture.x2 - 1; + int image_y2 = data->texture.y2 - 1; + + const qreal cx = x + qreal(0.5); + const qreal cy = y + qreal(0.5); + + const qreal fdx = data->m11; + const qreal fdy = data->m12; + const qreal fdw = data->m13; + + if (data->fast_matrix) { + // The increment pr x in the scanline + int fdx = (int)(data->m11 * fixed_scale); + int fdy = (int)(data->m12 * fixed_scale); + + int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale); + int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale); + + fx -= half_point; + fy -= half_point; + + if (fdy == 0) { //simple scale, no rotation + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + uint sbuf1[buffer_size]; + uint sbuf2[buffer_size]; + QRgba64 buf1[buffer_size]; + QRgba64 buf2[buffer_size]; + QRgba64 *b = buffer; + while (length) { + int len = qMin(length, buffer_size / 2); + int fracX = fx; + int i = 0; + int disty = (fy & 0x0000ffff); +#if defined(__SSE2__) + const __m128i vdy = _mm_set1_epi16(disty); + const __m128i vidy = _mm_set1_epi16(0x10000 - disty); + if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) { + for (; i < len; ++i) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + if (x1 != x2) + break; + sbuf1[i * 2 + 0] = ((const uint*)s1)[x1]; + sbuf1[i * 2 + 1] = ((const uint*)s1)[x2]; + sbuf2[i * 2 + 0] = ((const uint*)s2)[x1]; + sbuf2[i * 2 + 1] = ((const uint*)s2)[x2]; + fx += fdx; + } + + const __m128i v_fdx = _mm_set1_epi32(fdx*4); + __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx); + for (; i < len-3; i+=4) { + int offset = _mm_extract_epi16(v_fx, 1); + sbuf1[i * 2 + 0] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 0] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1]; + offset = _mm_extract_epi16(v_fx, 3); + sbuf1[i * 2 + 2] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 2] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1]; + offset = _mm_extract_epi16(v_fx, 5); + sbuf1[i * 2 + 4] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 4] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1]; + offset = _mm_extract_epi16(v_fx, 7); + sbuf1[i * 2 + 6] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 6] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1]; + v_fx = _mm_add_epi32(v_fx, v_fdx); + } + fx = _mm_cvtsi128_si32(v_fx); + } +#endif + for (; i < len; ++i) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + + if (layout->bpp == QPixelLayout::BPP32) { + sbuf1[i * 2 + 0] = ((const uint*)s1)[x1]; + sbuf1[i * 2 + 1] = ((const uint*)s1)[x2]; + sbuf2[i * 2 + 0] = ((const uint*)s2)[x1]; + sbuf2[i * 2 + 1] = ((const uint*)s2)[x2]; + + } else { + sbuf1[i * 2 + 0] = fetch(s1, x1); + sbuf1[i * 2 + 1] = fetch(s1, x2); + sbuf2[i * 2 + 0] = fetch(s2, x1); + sbuf2[i * 2 + 1] = fetch(s2, x2); + } + + fx += fdx; + } + layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut); + if (disty) + layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut); + + for (int i = 0; i < len; ++i) { + int distx = (fracX & 0x0000ffff); +#if defined(__SSE2__) + const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0)); + const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0)); + __m128i vt = _mm_loadu_si128((const __m128i*)(buf1 + i*2)); + if (disty) { + __m128i vb = _mm_loadu_si128((const __m128i*)(buf2 + i*2)); + vt = _mm_mulhi_epu16(vt, vidy); + vb = _mm_mulhi_epu16(vb, vdy); + vt = _mm_add_epi16(vt, vb); + } + vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx)); + vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8)); + _mm_storel_epi64((__m128i*)(b+i), vt); +#else + b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty); +#endif + fracX += fdx; + } + length -= len; + b += len; + } + } else { //rotation + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + uint sbuf1[buffer_size]; + uint sbuf2[buffer_size]; + QRgba64 buf1[buffer_size]; + QRgba64 buf2[buffer_size]; + QRgba64 *end = buffer + length; + QRgba64 *b = buffer; + + while (b < end) { + int len = qMin(length, buffer_size / 2); + int fracX = fx; + int fracY = fy; + int i = 0; +#if defined(__SSE2__) + if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) { + for (; i < len; ++i) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + if (x1 != x2 && y1 != y2) + break; + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + sbuf1[i * 2 + 0] = ((const uint*)s1)[x1]; + sbuf1[i * 2 + 1] = ((const uint*)s1)[x2]; + sbuf2[i * 2 + 0] = ((const uint*)s2)[x1]; + sbuf2[i * 2 + 1] = ((const uint*)s2)[x2]; + fx += fdx; + fy += fdy; + } + + const __m128i v_fdx = _mm_set1_epi32(fdx*4); + const __m128i v_fdy = _mm_set1_epi32(fdy*4); + __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx); + __m128i v_fy = _mm_setr_epi32(fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy); + const int bytesPerLine = data->texture.bytesPerLine; + const uchar *s1 = data->texture.imageData; + const uchar *s2 = s1 + bytesPerLine; + const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0)); + for (; i < len-3; i+=4) { + if (fdx > 0 && (short)_mm_extract_epi16(v_fx, 7) >= image_x2) + break; + if (fdx < 0 && (short)_mm_extract_epi16(v_fx, 7) < image_x1) + break; + if (fdy > 0 && (short)_mm_extract_epi16(v_fy, 7) >= image_y2) + break; + if (fdy < 0 && (short)_mm_extract_epi16(v_fy, 7) < image_y1) + break; + const __m128i vy = _mm_packs_epi32(_mm_srai_epi32(v_fy, 16), _mm_setzero_si128()); + __m128i voffset = _mm_unpacklo_epi16(_mm_mullo_epi16(vy, vbpl), _mm_mulhi_epu16(vy, vbpl)); + voffset = _mm_add_epi32(voffset, _mm_srli_epi32(v_fx, 16)); + + int offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4); + sbuf1[i * 2 + 0] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 0] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1]; + offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4); + sbuf1[i * 2 + 2] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 2] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1]; + offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4); + sbuf1[i * 2 + 4] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 4] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1]; + offset = _mm_cvtsi128_si32(voffset); + sbuf1[i * 2 + 6] = ((const uint*)s1)[offset]; + sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1]; + sbuf2[i * 2 + 6] = ((const uint*)s2)[offset]; + sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1]; + + v_fx = _mm_add_epi32(v_fx, v_fdx); + v_fy = _mm_add_epi32(v_fy, v_fdy); + } + fx = _mm_cvtsi128_si32(v_fx); + fy = _mm_cvtsi128_si32(v_fy); + } +#endif + for (; i < len; ++i) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + if (layout->bpp == QPixelLayout::BPP32) { + sbuf1[i * 2 + 0] = ((const uint*)s1)[x1]; + sbuf1[i * 2 + 1] = ((const uint*)s1)[x2]; + sbuf2[i * 2 + 0] = ((const uint*)s2)[x1]; + sbuf2[i * 2 + 1] = ((const uint*)s2)[x2]; + + } else { + sbuf1[i * 2 + 0] = fetch(s1, x1); + sbuf1[i * 2 + 1] = fetch(s1, x2); + sbuf2[i * 2 + 0] = fetch(s2, x1); + sbuf2[i * 2 + 1] = fetch(s2, x2); + } + + fx += fdx; + fy += fdy; + } + layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut); + layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut); + + for (int i = 0; i < len; ++i) { + int distx = (fracX & 0x0000ffff); + int disty = (fracY & 0x0000ffff); + b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty); + fracX += fdx; + fracY += fdy; + } + + length -= len; + b += len; + } + } + } else { + qreal fx = data->m21 * cy + data->m11 * cx + data->dx; + qreal fy = data->m22 * cy + data->m12 * cx + data->dy; + qreal fw = data->m23 * cy + data->m13 * cx + data->m33; + + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + uint sbuf1[buffer_size]; + uint sbuf2[buffer_size]; + QRgba64 buf1[buffer_size]; + QRgba64 buf2[buffer_size]; + QRgba64 *b = buffer; + + int distxs[buffer_size / 2]; + int distys[buffer_size / 2]; + + while (length) { + int len = qMin(length, buffer_size / 2); + for (int i = 0; i < len; ++i) { + const qreal iw = fw == 0 ? 1 : 1 / fw; + const qreal px = fx * iw - qreal(0.5); + const qreal py = fy * iw - qreal(0.5); + + int x1 = int(px) - (px < 0); + int x2; + int y1 = int(py) - (py < 0); + int y2; + + distxs[i] = int((px - x1) * (1<<16)); + distys[i] = int((py - y1) * (1<<16)); + + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + if (layout->bpp == QPixelLayout::BPP32) { + sbuf1[i * 2 + 0] = ((const uint*)s1)[x1]; + sbuf1[i * 2 + 1] = ((const uint*)s1)[x2]; + sbuf2[i * 2 + 0] = ((const uint*)s2)[x1]; + sbuf2[i * 2 + 1] = ((const uint*)s2)[x2]; + + } else { + sbuf1[i * 2 + 0] = fetch(s1, x1); + sbuf1[i * 2 + 1] = fetch(s1, x2); + sbuf2[i * 2 + 0] = fetch(s2, x1); + sbuf2[i * 2 + 1] = fetch(s2, x2); + } + + fx += fdx; + fy += fdy; + fw += fdw; + //force increment to avoid /0 + if (!fw) + fw += fdw; + } + + layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut); + layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut); + + for (int i = 0; i < len; ++i) { + int distx = distxs[i]; + int disty = distys[i]; + b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty); + } + + length -= len; + b += len; + } + } + + return buffer; +} + static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { // Untransformed { @@ -2298,12 +3229,186 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { }, }; +static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = { + // Untransformed + { + 0, // Invalid + fetchUntransformed64, // Mono + fetchUntransformed64, // MonoLsb + fetchUntransformed64, // Indexed8 + fetchUntransformed64, // RGB32 + fetchUntransformed64, // ARGB32 + fetchUntransformed64, // ARGB32_Premultiplied + fetchUntransformed64, // RGB16 + fetchUntransformed64, // ARGB8565_Premultiplied + fetchUntransformed64, // RGB666 + fetchUntransformed64, // ARGB6666_Premultiplied + fetchUntransformed64, // RGB555 + fetchUntransformed64, // ARGB8555_Premultiplied + fetchUntransformed64, // RGB888 + fetchUntransformed64, // RGB444 + fetchUntransformed64, // ARGB4444_Premultiplied + fetchUntransformed64, // RGBX8888 + fetchUntransformed64, // RGBA8888 + fetchUntransformed64, // RGBA8888_Premultiplied + fetchUntransformed64, // Format_BGR30 + fetchUntransformed64, // Format_A2BGR30_Premultiplied + fetchUntransformed64, // Format_RGB30 + fetchUntransformed64, // Format_A2RGB30_Premultiplied + fetchUntransformed64, // Alpha8 + fetchUntransformed64, // Grayscale8 + }, + // Tiled + { + 0, // Invalid + fetchUntransformed64, // Mono + fetchUntransformed64, // MonoLsb + fetchUntransformed64, // Indexed8 + fetchUntransformed64, // RGB32 + fetchUntransformed64, // ARGB32 + fetchUntransformed64, // ARGB32_Premultiplied + fetchUntransformed64, // RGB16 + fetchUntransformed64, // ARGB8565_Premultiplied + fetchUntransformed64, // RGB666 + fetchUntransformed64, // ARGB6666_Premultiplied + fetchUntransformed64, // RGB555 + fetchUntransformed64, // ARGB8555_Premultiplied + fetchUntransformed64, // RGB888 + fetchUntransformed64, // RGB444 + fetchUntransformed64, // ARGB4444_Premultiplied + fetchUntransformed64, // RGBX8888 + fetchUntransformed64, // RGBA8888 + fetchUntransformed64, // RGBA8888_Premultiplied + fetchUntransformed64, // BGR30 + fetchUntransformed64, // A2BGR30_Premultiplied + fetchUntransformed64, // RGB30 + fetchUntransformed64, // A2RGB30_Premultiplied + fetchUntransformed64, // Alpha8 + fetchUntransformed64, // Grayscale8 + }, + // Transformed + { + 0, // Invalid + fetchTransformed64<BlendTransformed>, // Mono + fetchTransformed64<BlendTransformed>, // MonoLsb + fetchTransformed64<BlendTransformed>, // Indexed8 + fetchTransformed64<BlendTransformed>, // RGB32 + fetchTransformed64<BlendTransformed>, // ARGB32 + fetchTransformed64<BlendTransformed>, // ARGB32_Premultiplied + fetchTransformed64<BlendTransformed>, // RGB16 + fetchTransformed64<BlendTransformed>, // ARGB8565_Premultiplied + fetchTransformed64<BlendTransformed>, // RGB666 + fetchTransformed64<BlendTransformed>, // ARGB6666_Premultiplied + fetchTransformed64<BlendTransformed>, // RGB555 + fetchTransformed64<BlendTransformed>, // ARGB8555_Premultiplied + fetchTransformed64<BlendTransformed>, // RGB888 + fetchTransformed64<BlendTransformed>, // RGB444 + fetchTransformed64<BlendTransformed>, // ARGB4444_Premultiplied + fetchTransformed64<BlendTransformed>, // RGBX8888 + fetchTransformed64<BlendTransformed>, // RGBA8888 + fetchTransformed64<BlendTransformed>, // RGBA8888_Premultiplied + fetchTransformed64<BlendTransformed>, // BGR30 + fetchTransformed64<BlendTransformed>, // A2BGR30_Premultiplied + fetchTransformed64<BlendTransformed>, // RGB30 + fetchTransformed64<BlendTransformed>, // A2RGB30_Premultiplied + fetchTransformed64<BlendTransformed>, // Alpah8 + fetchTransformed64<BlendTransformed>, // Grayscale8 + }, + { + 0, // TransformedTiled + fetchTransformed64<BlendTransformedTiled>, // Mono + fetchTransformed64<BlendTransformedTiled>, // MonoLsb + fetchTransformed64<BlendTransformedTiled>, // Indexed8 + fetchTransformed64<BlendTransformedTiled>, // RGB32 + fetchTransformed64<BlendTransformedTiled>, // ARGB32 + fetchTransformed64<BlendTransformedTiled>, // ARGB32_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // RGB16 + fetchTransformed64<BlendTransformedTiled>, // ARGB8565_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // RGB666 + fetchTransformed64<BlendTransformedTiled>, // ARGB6666_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // RGB555 + fetchTransformed64<BlendTransformedTiled>, // ARGB8555_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // RGB888 + fetchTransformed64<BlendTransformedTiled>, // RGB444 + fetchTransformed64<BlendTransformedTiled>, // ARGB4444_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // RGBX8888 + fetchTransformed64<BlendTransformedTiled>, // RGBA8888 + fetchTransformed64<BlendTransformedTiled>, // RGBA8888_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // BGR30 + fetchTransformed64<BlendTransformedTiled>, // A2BGR30_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // RGB30 + fetchTransformed64<BlendTransformedTiled>, // A2RGB30_Premultiplied + fetchTransformed64<BlendTransformedTiled>, // Alpha8 + fetchTransformed64<BlendTransformedTiled>, // Grayscale8 + }, + { + 0, // Bilinear + fetchTransformedBilinear64<BlendTransformedBilinear>, // Mono + fetchTransformedBilinear64<BlendTransformedBilinear>, // MonoLsb + fetchTransformedBilinear64<BlendTransformedBilinear>, // Indexed8 + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB32 + fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB32 + fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB32_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB16 + fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB8565_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB666 + fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB6666_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB555 + fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB8555_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB888 + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB444 + fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB4444_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGBX8888 + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGBA8888 + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGBA8888_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // BGR30 + fetchTransformedBilinear64<BlendTransformedBilinear>, // A2BGR30_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB30 + fetchTransformedBilinear64<BlendTransformedBilinear>, // A2RGB30_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinear>, // Alpha8 + fetchTransformedBilinear64<BlendTransformedBilinear>, // Grayscale8 + }, + { + 0, // BilinearTiled + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Mono + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // MonoLsb + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Indexed8 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB32 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB32 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB32_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB16 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB8565_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB666 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB6666_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB555 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB8555_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB888 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB444 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB4444_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGBX8888 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGBA8888 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGBA8888_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // BGR30 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // A2BGR30_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB30 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // A2RGB30_Premultiplied + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Alpha8 + fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Grayscale8 + }, +}; + #define FIXPT_BITS 8 #define FIXPT_SIZE (1<<FIXPT_BITS) static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos) { int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; + return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); +} + +static const QRgba64& qt_gradient_pixel64_fixed(const QGradientData *data, int fixed_pos) +{ + int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; return data->colorTable[qt_gradient_clamp(data, ipos)]; } @@ -2320,10 +3425,50 @@ static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const Q } } -static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Operator *op, const QSpanData *data, - int y, int x, int length) +class GradientBase32 { - const uint *b = buffer; +public: + typedef uint Type; + static Type null() { return 0; } + static Type fetchSingle(const QGradientData& gradient, qreal v) + { + return qt_gradient_pixel(&gradient, v); + } + static Type fetchSingle(const QGradientData& gradient, int v) + { + return qt_gradient_pixel_fixed(&gradient, v); + } + static void memfill(Type *buffer, Type fill, int length) + { + qt_memfill32(buffer, fill, length); + } +}; + +class GradientBase64 +{ +public: + typedef QRgba64 Type; + static Type null() { return QRgba64::fromRgba64(0); } + static Type fetchSingle(const QGradientData& gradient, qreal v) + { + return qt_gradient_pixel64(&gradient, v); + } + static Type fetchSingle(const QGradientData& gradient, int v) + { + return qt_gradient_pixel64_fixed(&gradient, v); + } + static void memfill(Type *buffer, Type fill, int length) + { + qt_memfill64((quint64*)buffer, fill, length); + } +}; + +template<class GradientBase, typename BlendType> +static inline const BlendType * QT_FASTCALL qt_fetch_linear_gradient_template( + BlendType *buffer, const Operator *op, const QSpanData *data, + int y, int x, int length) +{ + const BlendType *b = buffer; qreal t, inc; bool affine = true; @@ -2343,10 +3488,10 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope } } - const uint *end = buffer + length; + const BlendType *end = buffer + length; if (affine) { if (inc > qreal(-1e-5) && inc < qreal(1e-5)) { - QT_MEMFILL_UINT(buffer, length, qt_gradient_pixel_fixed(&data->gradient, int(t * FIXPT_SIZE))); + GradientBase::memfill(buffer, GradientBase::fetchSingle(data->gradient, int(t * FIXPT_SIZE)), length); } else { if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) && t+inc*length > qreal(INT_MIN >> (FIXPT_BITS + 1))) { @@ -2354,14 +3499,14 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope int t_fixed = int(t * FIXPT_SIZE); int inc_fixed = int(inc * FIXPT_SIZE); while (buffer < end) { - *buffer = qt_gradient_pixel_fixed(&data->gradient, t_fixed); + *buffer = GradientBase::fetchSingle(data->gradient, t_fixed); t_fixed += inc_fixed; ++buffer; } } else { // we have to fall back to float math while (buffer < end) { - *buffer = qt_gradient_pixel(&data->gradient, t/GRADIENT_STOPTABLE_SIZE); + *buffer = GradientBase::fetchSingle(data->gradient, t/GRADIENT_STOPTABLE_SIZE); t += inc; ++buffer; } @@ -2374,7 +3519,7 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope qreal y = ry/rw; t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off; - *buffer = qt_gradient_pixel(&data->gradient, t); + *buffer = GradientBase::fetchSingle(data->gradient, t); rx += data->m11; ry += data->m12; rw += data->m13; @@ -2388,6 +3533,18 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope return b; } +static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Operator *op, const QSpanData *data, + int y, int x, int length) +{ + return qt_fetch_linear_gradient_template<GradientBase32, uint>(buffer, op, data, y, x, length); +} + +static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data, + int y, int x, int length) +{ + return qt_fetch_linear_gradient_template<GradientBase64, QRgba64>(buffer, op, data, y, x, length); +} + static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data) { v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x; @@ -2402,19 +3559,22 @@ static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const Q v->extended = !qFuzzyIsNull(data->gradient.radial.focal.radius) || v->a <= 0; } -class RadialFetchPlain +template <class GradientBase> +class RadialFetchPlain : public GradientBase { public: - static inline void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det, - qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b) + typedef typename GradientBase::Type BlendType; + static void fetch(BlendType *buffer, BlendType *end, + const Operator *op, const QSpanData *data, qreal det, + qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b) { if (op->radial.extended) { while (buffer < end) { - quint32 result = 0; + BlendType result = GradientBase::null(); if (det >= 0) { qreal w = qSqrt(det) - b; if (data->gradient.radial.focal.radius + op->radial.dr * w >= 0) - result = qt_gradient_pixel(&data->gradient, w); + result = GradientBase::fetchSingle(data->gradient, w); } *buffer = result; @@ -2427,7 +3587,7 @@ public: } } else { while (buffer < end) { - *buffer++ = qt_gradient_pixel(&data->gradient, qSqrt(det) - b); + *buffer++ = GradientBase::fetchSingle(data->gradient, qSqrt(det) - b); det += delta_det; delta_det += delta_delta_det; @@ -2440,15 +3600,23 @@ public: const uint * QT_FASTCALL qt_fetch_radial_gradient_plain(uint *buffer, const Operator *op, const QSpanData *data, int y, int x, int length) { - return qt_fetch_radial_gradient_template<RadialFetchPlain>(buffer, op, data, y, x, length); + return qt_fetch_radial_gradient_template<RadialFetchPlain<GradientBase32>, uint>(buffer, op, data, y, x, length); } static SourceFetchProc qt_fetch_radial_gradient = qt_fetch_radial_gradient_plain; -static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) +const QRgba64 * QT_FASTCALL qt_fetch_radial_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data, + int y, int x, int length) +{ + return qt_fetch_radial_gradient_template<RadialFetchPlain<GradientBase64>, QRgba64>(buffer, op, data, y, x, length); +} + +template <class GradientBase, typename BlendType> +static inline const BlendType * QT_FASTCALL qt_fetch_conical_gradient_template( + BlendType *buffer, const QSpanData *data, + int y, int x, int length) { - const uint *b = buffer; + const BlendType *b = buffer; qreal rx = data->m21 * (y + qreal(0.5)) + data->dx + data->m11 * (x + qreal(0.5)); qreal ry = data->m22 * (y + qreal(0.5)) @@ -2457,14 +3625,14 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op const qreal inv2pi = M_1_PI / 2.0; - const uint *end = buffer + length; + const BlendType *end = buffer + length; if (affine) { rx -= data->gradient.conical.center.x; ry -= data->gradient.conical.center.y; while (buffer < end) { qreal angle = qAtan2(ry, rx) + data->gradient.conical.angle; - *buffer = qt_gradient_pixel(&data->gradient, 1 - angle * inv2pi); + *buffer = GradientBase::fetchSingle(data->gradient, 1 - angle * inv2pi); rx += data->m11; ry += data->m12; @@ -2480,7 +3648,7 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op rx/rw - data->gradient.conical.center.y) + data->gradient.conical.angle; - *buffer = qt_gradient_pixel(&data->gradient, 1 - angle * inv2pi); + *buffer = GradientBase::fetchSingle(data->gradient, 1 - angle * inv2pi); rx += data->m11; ry += data->m12; @@ -2494,1763 +3662,29 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op return b; } -# define PRELOAD_INIT(x) -# define PRELOAD_INIT2(x,y) -# define PRELOAD_COND(x) -# define PRELOAD_COND2(x,y) - -/* The constant alpha factor describes an alpha factor that gets applied - to the result of the composition operation combining it with the destination. - - The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1. - we get the unmodified operation - - result = src op dest - dest = result * const_alpha + dest * (1. - const_alpha) - - This means that in the comments below, the first line is the const_alpha==255 case, the - second line the general one. - - In the lines below: - s == src, sa == alpha(src), sia = 1 - alpha(src) - d == dest, da == alpha(dest), dia = 1 - alpha(dest) - ca = const_alpha, cia = 1 - const_alpha - - The methods exist in two variants. One where we have a constant source, the other - where the source is an array of pixels. -*/ - -/* - result = 0 - d = d * cia -*/ -#define comp_func_Clear_impl(dest, length, const_alpha)\ -{\ - if (const_alpha == 255) {\ - QT_MEMFILL_UINT(dest, length, 0);\ - } else {\ - int ialpha = 255 - const_alpha;\ - PRELOAD_INIT(dest)\ - for (int i = 0; i < length; ++i) {\ - PRELOAD_COND(dest)\ - dest[i] = BYTE_MUL(dest[i], ialpha);\ - }\ - }\ -} - -void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha) -{ - comp_func_Clear_impl(dest, length, const_alpha); -} - -void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha) -{ - comp_func_Clear_impl(dest, length, const_alpha); -} - -/* - result = s - dest = s * ca + d * cia -*/ -void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) { - QT_MEMFILL_UINT(dest, length, color); - } else { - int ialpha = 255 - const_alpha; - color = BYTE_MUL(color, const_alpha); - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - dest[i] = color + BYTE_MUL(dest[i], ialpha); - } - } -} - -void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) { - ::memcpy(dest, src, length * sizeof(uint)); - } else { - int ialpha = 255 - const_alpha; - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); - } - } -} - -void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint) -{ -} - -void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint) -{ -} - -/* - result = s + d * sia - dest = (s + d * sia) * ca + d * cia - = s * ca + d * (sia * ca + cia) - = s * ca + d * (1 - sa*ca) -*/ -void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha) -{ - if ((const_alpha & qAlpha(color)) == 255) { - QT_MEMFILL_UINT(dest, length, color); - } else { - if (const_alpha != 255) - color = BYTE_MUL(color, const_alpha); - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color)); - } - } -} - -void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint s = src[i]; - if (s >= 0xff000000) - dest[i] = s; - else if (s != 0) - dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); - } - } else { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint s = BYTE_MUL(src[i], const_alpha); - dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); - } - } -} - -/* - result = d + s * dia - dest = (d + s * dia) * ca + d * cia - = d + s * dia * ca -*/ -void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha != 255) - color = BYTE_MUL(color, const_alpha); - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - dest[i] = d + BYTE_MUL(color, qAlpha(~d)); - } -} - -void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - dest[i] = d + BYTE_MUL(src[i], qAlpha(~d)); - } - } else { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = BYTE_MUL(src[i], const_alpha); - dest[i] = d + BYTE_MUL(s, qAlpha(~d)); - } - } -} - -/* - result = s * da - dest = s * da * ca + d * cia -*/ -void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha) -{ - PRELOAD_INIT(dest) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - dest[i] = BYTE_MUL(color, qAlpha(dest[i])); - } - } else { - color = BYTE_MUL(color, const_alpha); - uint cia = 255 - const_alpha; - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia); - } - } -} - -void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - dest[i] = BYTE_MUL(src[i], qAlpha(dest[i])); - } - } else { - uint cia = 255 - const_alpha; - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = BYTE_MUL(src[i], const_alpha); - dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia); - } - } -} - -/* - result = d * sa - dest = d * sa * ca + d * cia - = d * (sa * ca + cia) -*/ -void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha) -{ - uint a = qAlpha(color); - if (const_alpha != 255) { - a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; - } - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - dest[i] = BYTE_MUL(dest[i], a); - } -} - -void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - dest[i] = BYTE_MUL(dest[i], qAlpha(src[i])); - } - } else { - int cia = 255 - const_alpha; - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia; - dest[i] = BYTE_MUL(dest[i], a); - } - } -} - -/* - result = s * dia - dest = s * dia * ca + d * cia -*/ - -void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha) -{ - PRELOAD_INIT(dest) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - dest[i] = BYTE_MUL(color, qAlpha(~dest[i])); - } - } else { - color = BYTE_MUL(color, const_alpha); - int cia = 255 - const_alpha; - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia); - } - } -} - -void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i])); - } - } else { - int cia = 255 - const_alpha; - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint s = BYTE_MUL(src[i], const_alpha); - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia); - } - } -} - -/* - result = d * sia - dest = d * sia * ca + d * cia - = d * (sia * ca + cia) -*/ -void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha) -{ - uint a = qAlpha(~color); - if (const_alpha != 255) - a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - dest[i] = BYTE_MUL(dest[i], a); - } -} - -void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i])); - } - } else { - int cia = 255 - const_alpha; - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia; - dest[i] = BYTE_MUL(dest[i], sia); - } - } -} - -/* - result = s*da + d*sia - dest = s*da*ca + d*sia*ca + d *cia - = s*ca * da + d * (sia*ca + cia) - = s*ca * da + d * (1 - sa*ca) -*/ -void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha != 255) { - color = BYTE_MUL(color, const_alpha); - } - uint sia = qAlpha(~color); - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia); - } -} - -void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint s = src[i]; - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); - } - } else { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint s = BYTE_MUL(src[i], const_alpha); - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); - } - } -} - -/* - result = d*sa + s*dia - dest = d*sa*ca + s*dia*ca + d *cia - = s*ca * dia + d * (sa*ca + cia) -*/ -void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha) -{ - uint a = qAlpha(color); - if (const_alpha != 255) { - color = BYTE_MUL(color, const_alpha); - a = qAlpha(color) + 255 - const_alpha; - } - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d)); - } -} - -void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint s = src[i]; - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d)); - } - } else { - int cia = 255 - const_alpha; - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint s = BYTE_MUL(src[i], const_alpha); - uint d = dest[i]; - uint a = qAlpha(s) + cia; - dest[i] = INTERPOLATE_PIXEL_255(d, a, s, qAlpha(~d)); - } - } -} - -/* - result = d*sia + s*dia - dest = d*sia*ca + s*dia*ca + d *cia - = s*ca * dia + d * (sia*ca + cia) - = s*ca * dia + d * (1 - sa*ca) -*/ -void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha != 255) - color = BYTE_MUL(color, const_alpha); - uint sia = qAlpha(~color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia); - } -} - -void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - PRELOAD_INIT2(dest, src) - if (const_alpha == 255) { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); - } - } else { - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = BYTE_MUL(src[i], const_alpha); - dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); - } - } -} - -struct QFullCoverage { - inline void store(uint *dest, const uint src) const - { - *dest = src; - } -}; - -struct QPartialCoverage { - inline QPartialCoverage(uint const_alpha) - : ca(const_alpha) - , ica(255 - const_alpha) - { - } - - inline void store(uint *dest, const uint src) const - { - *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica); - } - -private: - const uint ca; - const uint ica; -}; - -static inline int mix_alpha(int da, int sa) -{ - return 255 - ((255 - sa) * (255 - da) >> 8); -} - -/* - Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa) - = Sca + Dca -*/ -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int length, uint color, const T &coverage) -{ - uint s = color; - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - d = comp_func_Plus_one_pixel(d, s); - coverage.store(&dest[i], d); - } -} - -void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Plus_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Plus_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - d = comp_func_Plus_one_pixel(d, s); - - coverage.store(&dest[i], d); - } -} - -void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Plus_impl(dest, src, length, QFullCoverage()); - else - comp_func_Plus_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) -*/ -static inline int multiply_op(int dst, int src, int da, int sa) -{ - return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) multiply_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) multiply_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Multiply_impl(dest, src, length, QFullCoverage()); - else - comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) - = Sca + Dca - Sca.Dca -*/ -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) 255 - qt_div_255((255-a) * (255-b)) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Screen_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) 255 - (((255-a) * (255-b)) >> 8) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Screen_impl(dest, src, length, QFullCoverage()); - else - comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - if 2.Dca < Da - Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - otherwise - Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) -*/ -static inline int overlay_op(int dst, int src, int da, int sa) -{ - const int temp = src * (255 - da) + dst * (255 - sa); - if (2 * dst < da) - return qt_div_255(2 * src * dst + temp); - else - return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) overlay_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) overlay_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Overlay_impl(dest, src, length, QFullCoverage()); - else - comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - Da' = Sa + Da - Sa.Da -*/ -static inline int darken_op(int dst, int src, int da, int sa) -{ - return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) darken_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Darken_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) darken_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Darken_impl(dest, src, length, QFullCoverage()); - else - comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - Da' = Sa + Da - Sa.Da -*/ -static inline int lighten_op(int dst, int src, int da, int sa) -{ - return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) lighten_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) lighten_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Lighten_impl(dest, src, length, QFullCoverage()); - else - comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - if Sca.Da + Dca.Sa >= Sa.Da - Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) - otherwise - Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) -*/ -static inline int color_dodge_op(int dst, int src, int da, int sa) -{ - const int sa_da = sa * da; - const int dst_sa = dst * sa; - const int src_da = src * da; - - const int temp = src * (255 - da) + dst * (255 - sa); - if (src_da + dst_sa >= sa_da) - return qt_div_255(sa_da + temp); - else - return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a,b) color_dodge_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) color_dodge_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_ColorDodge_impl(dest, src, length, QFullCoverage()); - else - comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - if Sca.Da + Dca.Sa <= Sa.Da - Dca' = Sca.(1 - Da) + Dca.(1 - Sa) - otherwise - Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) -*/ -static inline int color_burn_op(int dst, int src, int da, int sa) -{ - const int src_da = src * da; - const int dst_sa = dst * sa; - const int sa_da = sa * da; - - const int temp = src * (255 - da) + dst * (255 - sa); - - if (src == 0 || src_da + dst_sa <= sa_da) - return qt_div_255(temp); - return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) color_burn_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) color_burn_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_ColorBurn_impl(dest, src, length, QFullCoverage()); - else - comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - if 2.Sca < Sa - Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - otherwise - Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) -*/ -static inline uint hardlight_op(int dst, int src, int da, int sa) -{ - const uint temp = src * (255 - da) + dst * (255 - sa); - - if (2 * src < sa) - return qt_div_255(2 * src * dst + temp); - else - return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) hardlight_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) hardlight_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_HardLight_impl(dest, src, length, QFullCoverage()); - else - comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - if 2.Sca <= Sa - Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) - otherwise if 2.Sca > Sa and 4.Dca <= Da - Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) - otherwise if 2.Sca > Sa and 4.Dca > Da - Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) -*/ -static inline int soft_light_op(int dst, int src, int da, int sa) -{ - const int src2 = src << 1; - const int dst_np = da != 0 ? (255 * dst) / da : 0; - const int temp = (src * (255 - da) + dst * (255 - sa)) * 255; - - if (src2 < sa) - return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025; - else if (4 * dst <= da) - return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025; - else { - return (dst * sa * 255 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025; - } -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) soft_light_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) soft_light_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_SoftLight_impl(dest, src, length, QFullCoverage()); - else - comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa) - = Sca + Dca - 2.min(Sca.Da, Dca.Sa) -*/ -static inline int difference_op(int dst, int src, int da, int sa) -{ - return src + dst - qt_div_255(2 * qMin(src * da, dst * sa)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) difference_op(a, b, da, sa) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Difference_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) difference_op(a, b, da, sa) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Difference_impl(dest, src, length, QFullCoverage()); - else - comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -/* - Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) -*/ -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage) -{ - int sa = qAlpha(color); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - - PRELOAD_INIT(dest) - for (int i = 0; i < length; ++i) { - PRELOAD_COND(dest) - uint d = dest[i]; - int da = qAlpha(d); - -#define OP(a, b) (a + b - qt_div_255(2*(a*b))) - int r = OP( qRed(d), sr); - int b = OP( qBlue(d), sb); - int g = OP(qGreen(d), sg); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - -template <typename T> -Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) -{ - PRELOAD_INIT2(dest, src) - for (int i = 0; i < length; ++i) { - PRELOAD_COND2(dest, src) - uint d = dest[i]; - uint s = src[i]; - - int da = qAlpha(d); - int sa = qAlpha(s); - -#define OP(a, b) (a + b - ((a*b) >> 7)) - int r = OP( qRed(d), qRed(s)); - int b = OP( qBlue(d), qBlue(s)); - int g = OP(qGreen(d), qGreen(s)); - int a = mix_alpha(da, sa); -#undef OP - - coverage.store(&dest[i], qRgba(r, g, b, a)); - } -} - -void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_Exclusion_impl(dest, src, length, QFullCoverage()); - else - comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha)); -} - -void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) - *dest++ |= color; -} - -void QT_FASTCALL rasterop_SourceOrDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) - *dest++ |= *src++; -} - -void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - color |= 0xff000000; - while (length--) - *dest++ &= color; -} - -void QT_FASTCALL rasterop_SourceAndDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (*src & *dest) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - color &= 0x00ffffff; - while (length--) - *dest++ ^= color; -} - -void QT_FASTCALL rasterop_SourceXorDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (*src ^ *dest) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - color = ~color; - while (length--) { - *dest = (color & ~(*dest)) | 0xff000000; - ++dest; - } -} - -void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (~(*src) & ~(*dest)) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - color = ~color | 0xff000000; - while (length--) { - *dest = color | ~(*dest); - ++dest; - } -} - -void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = ~(*src) | ~(*dest) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - color = ~color & 0x00ffffff; - while (length--) { - *dest = color ^ (*dest); - ++dest; - } -} - -void QT_FASTCALL rasterop_NotSourceXorDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = ((~(*src)) ^ (*dest)) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, - uint color, uint const_alpha) -{ - Q_UNUSED(const_alpha); - qt_memfill(dest, ~color | 0xff000000, length); -} - -void QT_FASTCALL rasterop_NotSource(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, - int length, uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) - *dest++ = ~(*src++) | 0xff000000; -} - -void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - color = ~color | 0xff000000; - while (length--) { - *dest = color & *dest; - ++dest; - } -} - -void QT_FASTCALL rasterop_NotSourceAndDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (~(*src) & *dest) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (color & ~(*dest)) | 0xff000000; - ++dest; - } -} - -void QT_FASTCALL rasterop_SourceAndNotDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (*src & ~(*dest)) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (~(*src) | *dest) | 0xff000000; - ++dest; ++src; - } -} - -void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest, - int length, - uint color, - uint const_alpha) +static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Operator *, const QSpanData *data, + int y, int x, int length) { - Q_UNUSED(const_alpha); - color = ~color | 0xff000000; - while (length--) - *dest++ |= color; + return qt_fetch_conical_gradient_template<GradientBase32, uint>(buffer, data, y, x, length); } -void QT_FASTCALL rasterop_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) +static const QRgba64 * QT_FASTCALL qt_fetch_conical_gradient_rgb64(QRgba64 *buffer, const Operator *, const QSpanData *data, + int y, int x, int length) { - Q_UNUSED(const_alpha); - while (length--) { - *dest = (*src | ~(*dest)) | 0xff000000; - ++dest; ++src; - } + return qt_fetch_conical_gradient_template<GradientBase64, QRgba64>(buffer, data, y, x, length); } -void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(const_alpha); - while (length--) { - *dest = (color | ~(*dest)) | 0xff000000; - ++dest; - } -} +extern CompositionFunctionSolid qt_functionForModeSolid_C[]; +extern CompositionFunctionSolid64 qt_functionForModeSolid64_C[]; -void QT_FASTCALL rasterop_ClearDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(src); - comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha); -} - -void QT_FASTCALL rasterop_solid_ClearDestination(uint *Q_DECL_RESTRICT dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(color); - comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha); -} - -void QT_FASTCALL rasterop_SetDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(src); - comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha); -} - -void QT_FASTCALL rasterop_solid_SetDestination(uint *Q_DECL_RESTRICT dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(color); - comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha); -} - -void QT_FASTCALL rasterop_NotDestination(uint *Q_DECL_RESTRICT dest, - const uint *Q_DECL_RESTRICT src, - int length, - uint const_alpha) -{ - Q_UNUSED(src); - rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha); -} - -void QT_FASTCALL rasterop_solid_NotDestination(uint *Q_DECL_RESTRICT dest, - int length, - uint color, - uint const_alpha) -{ - Q_UNUSED(color); - rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha); -} - -static CompositionFunctionSolid functionForModeSolid_C[] = { - comp_func_solid_SourceOver, - comp_func_solid_DestinationOver, - comp_func_solid_Clear, - comp_func_solid_Source, - comp_func_solid_Destination, - comp_func_solid_SourceIn, - comp_func_solid_DestinationIn, - comp_func_solid_SourceOut, - comp_func_solid_DestinationOut, - comp_func_solid_SourceAtop, - comp_func_solid_DestinationAtop, - comp_func_solid_XOR, - comp_func_solid_Plus, - comp_func_solid_Multiply, - comp_func_solid_Screen, - comp_func_solid_Overlay, - comp_func_solid_Darken, - comp_func_solid_Lighten, - comp_func_solid_ColorDodge, - comp_func_solid_ColorBurn, - comp_func_solid_HardLight, - comp_func_solid_SoftLight, - comp_func_solid_Difference, - comp_func_solid_Exclusion, - rasterop_solid_SourceOrDestination, - rasterop_solid_SourceAndDestination, - rasterop_solid_SourceXorDestination, - rasterop_solid_NotSourceAndNotDestination, - rasterop_solid_NotSourceOrNotDestination, - rasterop_solid_NotSourceXorDestination, - rasterop_solid_NotSource, - rasterop_solid_NotSourceAndDestination, - rasterop_solid_SourceAndNotDestination, - rasterop_solid_NotSourceOrDestination, - rasterop_solid_SourceOrNotDestination, - rasterop_solid_ClearDestination, - rasterop_solid_SetDestination, - rasterop_solid_NotDestination -}; +static const CompositionFunctionSolid *functionForModeSolid = qt_functionForModeSolid_C; +static const CompositionFunctionSolid64 *functionForModeSolid64 = qt_functionForModeSolid64_C; -static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C; - -static CompositionFunction functionForMode_C[] = { - comp_func_SourceOver, - comp_func_DestinationOver, - comp_func_Clear, - comp_func_Source, - comp_func_Destination, - comp_func_SourceIn, - comp_func_DestinationIn, - comp_func_SourceOut, - comp_func_DestinationOut, - comp_func_SourceAtop, - comp_func_DestinationAtop, - comp_func_XOR, - comp_func_Plus, - comp_func_Multiply, - comp_func_Screen, - comp_func_Overlay, - comp_func_Darken, - comp_func_Lighten, - comp_func_ColorDodge, - comp_func_ColorBurn, - comp_func_HardLight, - comp_func_SoftLight, - comp_func_Difference, - comp_func_Exclusion, - rasterop_SourceOrDestination, - rasterop_SourceAndDestination, - rasterop_SourceXorDestination, - rasterop_NotSourceAndNotDestination, - rasterop_NotSourceOrNotDestination, - rasterop_NotSourceXorDestination, - rasterop_NotSource, - rasterop_NotSourceAndDestination, - rasterop_SourceAndNotDestination, - rasterop_NotSourceOrDestination, - rasterop_SourceOrNotDestination, - rasterop_ClearDestination, - rasterop_SetDestination, - rasterop_NotDestination -}; +extern CompositionFunction qt_functionForMode_C[]; +extern CompositionFunction64 qt_functionForMode64_C[]; -static const CompositionFunction *functionForMode = functionForMode_C; +static const CompositionFunction *functionForMode = qt_functionForMode_C; +static const CompositionFunction64 *functionForMode64 = qt_functionForMode64_C; static TextureBlendType getBlendType(const QSpanData *data) { @@ -4280,26 +3714,34 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in switch(data->type) { case QSpanData::Solid: - solidSource = (qAlpha(data->solid.color) == 255); + solidSource = data->solid.color.isOpaque(); + op.srcFetch = 0; + op.srcFetch64 = 0; break; case QSpanData::LinearGradient: solidSource = !data->gradient.alphaColor; getLinearGradientValues(&op.linear, data); - op.src_fetch = qt_fetch_linear_gradient; + op.srcFetch = qt_fetch_linear_gradient; + op.srcFetch64 = qt_fetch_linear_gradient_rgb64; break; case QSpanData::RadialGradient: solidSource = !data->gradient.alphaColor; getRadialGradientValues(&op.radial, data); - op.src_fetch = qt_fetch_radial_gradient; + op.srcFetch = qt_fetch_radial_gradient; + op.srcFetch64 = qt_fetch_radial_gradient_rgb64; break; case QSpanData::ConicalGradient: solidSource = !data->gradient.alphaColor; - op.src_fetch = qt_fetch_conical_gradient; + op.srcFetch = qt_fetch_conical_gradient; + op.srcFetch64 = qt_fetch_conical_gradient_rgb64; break; case QSpanData::Texture: - op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format]; solidSource = !data->texture.hasAlpha; + op.srcFetch = sourceFetch[getBlendType(data)][data->texture.format]; + op.srcFetch64 = sourceFetch64[getBlendType(data)][data->texture.format]; + break; default: + Q_UNREACHABLE(); break; } @@ -4307,12 +3749,13 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in if (op.mode == QPainter::CompositionMode_SourceOver && solidSource) op.mode = QPainter::CompositionMode_Source; - op.dest_fetch = destFetchProc[data->rasterBuffer->format]; + op.destFetch = destFetchProc[data->rasterBuffer->format]; + op.destFetch64 = destFetchProc64[data->rasterBuffer->format]; if (op.mode == QPainter::CompositionMode_Source) { switch (data->rasterBuffer->format) { case QImage::Format_RGB32: case QImage::Format_ARGB32_Premultiplied: - // don't clear dest_fetch as it sets up the pointer correctly to save one copy + // don't clear destFetch as it sets up the pointer correctly to save one copy break; default: { if (data->type == QSpanData::Texture && data->texture.const_alpha != 256) @@ -4327,15 +3770,18 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in ++spans; } if (!alphaSpans) - op.dest_fetch = 0; + op.destFetch = 0; } } } - op.dest_store = destStoreProc[data->rasterBuffer->format]; + op.destStore = destStoreProc[data->rasterBuffer->format]; + op.destStore64 = destStoreProc64[data->rasterBuffer->format]; op.funcSolid = functionForModeSolid[op.mode]; + op.funcSolid64 = functionForModeSolid64[op.mode]; op.func = functionForMode[op.mode]; + op.func64 = functionForMode64[op.mode]; return op; } @@ -4352,16 +3798,17 @@ void blend_color_generic(int count, const QSpan *spans, void *userData) QSpanData *data = reinterpret_cast<QSpanData *>(userData); uint buffer[buffer_size]; Operator op = getOperator(data, spans, count); + const uint color = data->solid.color.toArgb32(); while (count--) { int x = spans->x; int length = spans->len; while (length) { int l = qMin(buffer_size, length); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; - op.funcSolid(dest, l, data->solid.color, spans->coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + op.funcSolid(dest, l, color, spans->coverage); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); length -= l; x += l; } @@ -4374,15 +3821,16 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) QSpanData *data = reinterpret_cast<QSpanData *>(userData); Operator op = getOperator(data, spans, count); + const uint color = data->solid.color.toArgb32(); if (op.mode == QPainter::CompositionMode_Source) { // inline for performance while (count--) { uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { - QT_MEMFILL_UINT(target, spans->len, data->solid.color); + QT_MEMFILL_UINT(target, spans->len, color); } else { - uint c = BYTE_MUL(data->solid.color, spans->coverage); + uint c = BYTE_MUL(color, spans->coverage); int ialpha = 255 - spans->coverage; for (int i = 0; i < spans->len; ++i) target[i] = c + BYTE_MUL(target[i], ialpha); @@ -4394,7 +3842,34 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) while (count--) { uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; - op.funcSolid(target, spans->len, data->solid.color, spans->coverage); + op.funcSolid(target, spans->len, color, spans->coverage); + ++spans; + } +} + +void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + Operator op = getOperator(data, spans, count); + if (!op.funcSolid64) { + qDebug() << Q_FUNC_INFO << "unsupported 64bit blend attempted"; + return blend_color_generic(count, spans, userData); + } + + QRgba64 buffer[buffer_size]; + const QRgba64 color = data->solid.color; + + while (count--) { + int x = spans->x; + int length = spans->len; + while (length) { + int l = qMin(buffer_size, length); + QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l); + op.funcSolid64(dest, l, color, spans->coverage); + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); + length -= l; + x += l; + } ++spans; } } @@ -4409,13 +3884,12 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) from qt_gradient_quint16 with minimal overhead. */ QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - if (mode == QPainter::CompositionMode_SourceOver && - qAlpha(data->solid.color) == 255) + if (mode == QPainter::CompositionMode_SourceOver && data->solid.color.isOpaque()) mode = QPainter::CompositionMode_Source; if (mode == QPainter::CompositionMode_Source) { // inline for performance - ushort c = qConvertRgb32To16(data->solid.color); + ushort c = data->solid.color.toRgb16(); while (count--) { ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { @@ -4436,7 +3910,7 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) if (mode == QPainter::CompositionMode_SourceOver) { while (count--) { - uint color = BYTE_MUL(data->solid.color, spans->coverage); + uint color = BYTE_MUL(data->solid.color.toArgb32(), spans->coverage); int ialpha = qAlpha(~color); ushort c = qConvertRgb32To16(color); ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; @@ -4500,7 +3974,7 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle int process_length = l; int process_x = x; - const uint *src = handler.fetch(process_x, y, process_length); + const typename T::BlendType *src = handler.fetch(process_x, y, process_length); int offset = 0; while (l > 0) { if (x == spans->x) // new span? @@ -4525,8 +3999,10 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle } } +template<typename T> struct QBlendBase { + typedef T BlendType; QBlendBase(QSpanData *d, Operator o) : data(d) , op(o) @@ -4537,24 +4013,24 @@ struct QBlendBase QSpanData *data; Operator op; - uint *dest; + BlendType *dest; - uint buffer[buffer_size]; - uint src_buffer[buffer_size]; + BlendType buffer[buffer_size]; + BlendType src_buffer[buffer_size]; }; -class BlendSrcGeneric : public QBlendBase +class BlendSrcGeneric : public QBlendBase<uint> { public: BlendSrcGeneric(QSpanData *d, Operator o) - : QBlendBase(d, o) + : QBlendBase<uint>(d, o) { } const uint *fetch(int x, int y, int len) { - dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer; - return op.src_fetch(src_buffer, &op, data, y, x, len); + dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, y, len) : buffer; + return op.srcFetch(src_buffer, &op, data, y, x, len); } void process(int, int, int len, int coverage, const uint *src, int offset) @@ -4564,8 +4040,38 @@ public: void store(int x, int y, int len) { - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, y, dest, len); + if (op.destStore) + op.destStore(data->rasterBuffer, x, y, dest, len); + } +}; + +class BlendSrcGenericRGB64 : public QBlendBase<QRgba64> +{ +public: + BlendSrcGenericRGB64(QSpanData *d, Operator o) + : QBlendBase<QRgba64>(d, o) + { + } + + bool isSupported() const + { + return op.func64 && op.destFetch64 && op.destStore64; + } + + const QRgba64 *fetch(int x, int y, int len) + { + dest = op.destFetch64(buffer, data->rasterBuffer, x, y, len); + return op.srcFetch64(src_buffer, &op, data, y, x, len); + } + + void process(int, int, int len, int coverage, const QRgba64 *src, int offset) + { + op.func64(dest + offset, src + offset, len, coverage); + } + + void store(int x, int y, int len) + { + op.destStore64(data->rasterBuffer, x, y, dest, len); } }; @@ -4576,6 +4082,20 @@ static void blend_src_generic(int count, const QSpan *spans, void *userData) handleSpans(count, spans, data, blend); } +static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + Operator op = getOperator(data, spans, count); + BlendSrcGenericRGB64 blend64(data, op); + if (blend64.isSupported()) + handleSpans(count, spans, data, blend64); + else { + qDebug("blend_src_generic_rgb64: unsupported 64-bit blend attempted"); + BlendSrcGeneric blend32(data, op); + handleSpans(count, spans, data, blend32); + } +} + static void blend_untransformed_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -4606,11 +4126,59 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { int l = qMin(buffer_size, length); - const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); + x += l; + sx += l; + length -= l; + } + } + } + ++spans; + } +} + +static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + Operator op = getOperator(data, spans, count); + if (!op.func64) { + qWarning() << Q_FUNC_INFO << "Unsupported blend"; + return blend_untransformed_generic(count, spans, userData); + } + QRgba64 buffer[buffer_size]; + QRgba64 src_buffer[buffer_size]; + + const int image_width = data->texture.width; + const int image_height = data->texture.height; + int xoff = -qRound(-data->dx); + int yoff = -qRound(-data->dy); + + while (count--) { + int x = spans->x; + int length = spans->len; + int sx = xoff + x; + int sy = yoff + spans->y; + if (sy >= 0 && sy < image_height && sx < image_width) { + if (sx < 0) { + x -= sx; + length += sx; + sx = 0; + } + if (sx + length > image_width) + length = image_width - sx; + if (length > 0) { + const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; + while (length) { + int l = qMin(buffer_size, length); + const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l); + QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l); + op.func64(dest, src, l, coverage); + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); x += l; sx += l; length -= l; @@ -4799,11 +4367,62 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData) int l = qMin(image_width - sx, length); if (buffer_size < l) l = buffer_size; - const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); + x += l; + sx += l; + length -= l; + if (sx >= image_width) + sx = 0; + } + ++spans; + } +} + +static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + Operator op = getOperator(data, spans, count); + if (!op.func64) { + qDebug("unsupported rgb64 blend"); + return blend_tiled_generic(count, spans, userData); + } + QRgba64 buffer[buffer_size]; + QRgba64 src_buffer[buffer_size]; + + const int image_width = data->texture.width; + const int image_height = data->texture.height; + int xoff = -qRound(-data->dx) % image_width; + int yoff = -qRound(-data->dy) % image_height; + + if (xoff < 0) + xoff += image_width; + if (yoff < 0) + yoff += image_height; + + while (count--) { + int x = spans->x; + int length = spans->len; + int sx = (xoff + spans->x) % image_width; + int sy = (spans->y + yoff) % image_height; + if (sx < 0) + sx += image_width; + if (sy < 0) + sy += image_height; + + const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l); + QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l); + op.func64(dest, src, l, coverage); + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); x += l; sx += l; length -= l; @@ -5684,10 +5303,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_untransformed_generic, blend_untransformed_generic, blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, blend_untransformed_generic, blend_untransformed_generic, }, @@ -5712,10 +5331,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_tiled_generic, blend_tiled_generic, blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, blend_tiled_generic, blend_tiled_generic, }, @@ -5740,10 +5359,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, }, @@ -5767,12 +5386,12 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic }, // Bilinear { @@ -5795,10 +5414,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, }, @@ -5823,10 +5442,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, // RGBX8888 blend_src_generic, // RGBA8888 blend_src_generic, // RGBA8888_Premultiplied - blend_src_generic, // BGR30 - blend_src_generic, // A2BGR30_Premultiplied - blend_src_generic, // RGB30 - blend_src_generic, // A2RGB30_Premultiplied + blend_src_generic_rgb64, // BGR30 + blend_src_generic_rgb64, // A2BGR30_Premultiplied + blend_src_generic_rgb64, // RGB30 + blend_src_generic_rgb64, // A2RGB30_Premultiplied blend_src_generic, // Alpha8 blend_src_generic, // Grayscale8 } @@ -5982,13 +5601,11 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE)); - uint oldColor = data->solid.color; + QRgba64 oldColor = data->solid.color; while (count--) { int y = spans->y; - quint32 color = qt_gradient_pixel_fixed(&data->gradient, yinc * y + off); - - data->solid.color = color; + data->solid.color = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&data->gradient, yinc * y + off)); blend_color_rgb16(1, spans, userData); ++spans; } @@ -6000,39 +5617,49 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) } inline static void qt_bitmapblit_argb32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color, + qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride); } inline static void qt_bitmapblit_rgba8888(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint32>(rasterBuffer, x, y, ARGB2RGBA(color), + qt_bitmapblit_template<quint32>(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), + map, mapWidth, mapHeight, mapStride); +} + +template<QtPixelOrder PixelOrder> +inline static void qt_bitmapblit_rgb30(QRasterBuffer *rasterBuffer, + int x, int y, const QRgba64 &color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride) +{ + qt_bitmapblit_template<quint32>(rasterBuffer, x, y, qConvertRgb64ToRgb30<PixelOrder>(color), map, mapWidth, mapHeight, mapStride); } inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint16>(rasterBuffer, x, y, qConvertRgb32To16(color), + qt_bitmapblit_template<quint16>(rasterBuffer, x, y, color.toRgb16(), map, mapWidth, mapHeight, mapStride); } static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride, const QClipData *) { - const quint16 c = qConvertRgb32To16(color); + const quint16 c = color.toRgb16(); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); @@ -6130,7 +5757,7 @@ static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, in } #endif -static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, +static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, int mapWidth, int mapHeight, int mapStride, @@ -6226,28 +5853,38 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, } } + +static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, + int x, int y, const QRgba64 &color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride, + const QClipData *clip) +{ + qt_alphamapblit_uint32(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride, clip); +} + #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride, const QClipData *clip) { - qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip); + qt_alphamapblit_uint32(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride, clip); } #endif static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uint *src, int mapWidth, int mapHeight, int srcStride, const QClipData *clip) { - const quint32 c = color; + const quint32 c = color.toArgb32(); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - int sa = qAlpha(color); + int sr = qRed(c); + int sg = qGreen(c); + int sb = qBlue(c); + int sa = qAlpha(c); const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables(); if (!tables) @@ -6314,58 +5951,67 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, static void qt_rectfill_argb32(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - color, x, y, width, height, rasterBuffer->bytesPerLine()); + color.toArgb32(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_quint16(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint16>(reinterpret_cast<quint16 *>(rasterBuffer->buffer()), - qConvertRgb32To16(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.toRgb16(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - qUnpremultiply(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.unpremultiplied().toArgb32(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_rgba(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - ARGB2RGBA(color), x, y, width, height, rasterBuffer->bytesPerLine()); + ARGB2RGBA(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_nonpremul_rgba(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) +{ + qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), + ARGB2RGBA(color.unpremultiplied().toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); +} + +template<QtPixelOrder PixelOrder> +static void qt_rectfill_rgb30(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - ARGB2RGBA(qUnpremultiply(color)), x, y, width, height, rasterBuffer->bytesPerLine()); + qConvertRgb64ToRgb30<PixelOrder>(color), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_alpha(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint8>(reinterpret_cast<quint8 *>(rasterBuffer->buffer()), - qAlpha(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.alpha() >> 8, x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_gray(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint8>(reinterpret_cast<quint8 *>(rasterBuffer->buffer()), - qGray(color), x, y, width, height, rasterBuffer->bytesPerLine()); + qGray(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); } // Map table for destination image format. Contains function pointers @@ -6518,39 +6164,39 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = }, // Format_BGR30 { - blend_color_generic, - blend_src_generic, - 0, + blend_color_generic_rgb64, + blend_src_generic_rgb64, + qt_bitmapblit_rgb30<PixelOrderBGR>, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied { - blend_color_generic, - blend_src_generic, - 0, + blend_color_generic_rgb64, + blend_src_generic_rgb64, + qt_bitmapblit_rgb30<PixelOrderBGR>, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderBGR> }, // Format_RGB30 { - blend_color_generic, - blend_src_generic, - 0, + blend_color_generic_rgb64, + blend_src_generic_rgb64, + qt_bitmapblit_rgb30<PixelOrderRGB>, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied { - blend_color_generic, - blend_src_generic, - 0, + blend_color_generic_rgb64, + blend_src_generic_rgb64, + qt_bitmapblit_rgb30<PixelOrderRGB>, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderRGB> }, // Format_Alpha8 { @@ -6619,6 +6265,11 @@ inline void qt_memfill_template(quint16 *dest, quint16 value, int count) } #endif +void qt_memfill64(quint64 *dest, quint64 color, int count) +{ + qt_memfill_template<quint64>(dest, color, count); +} + #if !defined(__SSE2__) void qt_memfill16(quint16 *dest, quint16 color, int count) { @@ -6646,9 +6297,6 @@ template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4 void qInitDrawhelperAsm() { - CompositionFunction *functionForModeAsm = 0; - CompositionFunctionSolid *functionForModeSolidAsm = 0; - const uint features = qCpuFeatures(); Q_UNUSED(features); #ifdef __SSE2__ @@ -6735,9 +6383,15 @@ void qInitDrawhelperAsm() qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_avx2; } #endif + extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); + extern void QT_FASTCALL comp_func_Source_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_Plus_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_sse2; + qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_sse2; + qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_sse2; + qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2; - functionForModeAsm = qt_functionForMode_SSE2; - functionForModeSolidAsm = qt_functionForModeSolid_SSE2; #endif // SSE2 #if defined(__ARM_NEON__) && !defined(Q_OS_IOS) @@ -6763,9 +6417,9 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon; - functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon; - functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon; - functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon; + qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon; + qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon; + qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon; destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon; destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon; @@ -6785,25 +6439,25 @@ void qInitDrawhelperAsm() #if defined(QT_COMPILER_SUPPORTS_MIPS_DSP) || defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2) if (features & (DSP | DSPR2)) { // Composition functions are all DSP r1 - functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp; - functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp; - functionForMode_C[QPainter::CompositionMode_DestinationOver] = comp_func_DestinationOver_mips_dsp; - functionForMode_C[QPainter::CompositionMode_SourceIn] = comp_func_SourceIn_mips_dsp; - functionForMode_C[QPainter::CompositionMode_DestinationIn] = comp_func_DestinationIn_mips_dsp; - functionForMode_C[QPainter::CompositionMode_DestinationOut] = comp_func_DestinationOut_mips_dsp; - functionForMode_C[QPainter::CompositionMode_SourceAtop] = comp_func_SourceAtop_mips_dsp; - functionForMode_C[QPainter::CompositionMode_DestinationAtop] = comp_func_DestinationAtop_mips_dsp; - functionForMode_C[QPainter::CompositionMode_Xor] = comp_func_XOR_mips_dsp; - functionForMode_C[QPainter::CompositionMode_SourceOut] = comp_func_SourceOut_mips_dsp; - - functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_mips_dsp; - functionForModeSolid_C[QPainter::CompositionMode_DestinationOver] = comp_func_solid_DestinationOver_mips_dsp; - functionForModeSolid_C[QPainter::CompositionMode_SourceIn] = comp_func_solid_SourceIn_mips_dsp; - functionForModeSolid_C[QPainter::CompositionMode_DestinationIn] = comp_func_solid_DestinationIn_mips_dsp; - functionForModeSolid_C[QPainter::CompositionMode_SourceAtop] = comp_func_solid_SourceAtop_mips_dsp; - functionForModeSolid_C[QPainter::CompositionMode_DestinationAtop] = comp_func_solid_DestinationAtop_mips_dsp; - functionForModeSolid_C[QPainter::CompositionMode_Xor] = comp_func_solid_XOR_mips_dsp; - functionForModeSolid_C[QPainter::CompositionMode_SourceOut] = comp_func_solid_SourceOut_mips_dsp; + 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; @@ -6830,20 +6484,6 @@ void qInitDrawhelperAsm() #endif // QT_COMPILER_SUPPORTS_MIPS_DSPR2 } #endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2 - - if (functionForModeSolidAsm) { - const int destinationMode = QPainter::CompositionMode_Destination; - functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode]; - - // use the default qdrawhelper implementation for the - // extended composition modes - for (int mode = 12; mode < 24; ++mode) - functionForModeSolidAsm[mode] = functionForModeSolid_C[mode]; - - functionForModeSolid = functionForModeSolidAsm; - } - if (functionForModeAsm) - functionForMode = functionForModeAsm; } QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 7e12e62151..08e564f017 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -466,7 +466,7 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl, } void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *) @@ -475,8 +475,9 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); uchar *mask = const_cast<uchar *>(bitmap); + const uint c = color.toArgb32(); - pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, color, 0, mask, mapStride); + pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, c, 0, mask, mapStride); } extern "C" void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha); @@ -985,7 +986,7 @@ public: const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data, int y, int x, int length) { - return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon> >(buffer, op, data, y, x, length); + return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon>,uint>(buffer, op, data, y, x, length); } QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h index bd030a8bf3..37e060f147 100644 --- a/src/gui/painting/qdrawhelper_neon_p.h +++ b/src/gui/painting/qdrawhelper_neon_p.h @@ -82,7 +82,7 @@ void qt_blend_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl, int const_alpha); void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 73ff21812a..2c222b97c2 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -50,6 +50,7 @@ #include "QtGui/qcolor.h" #include "QtGui/qpainter.h" #include "QtGui/qimage.h" +#include "QtGui/qrgba64.h" #ifndef QT_FT_BEGIN_HEADER #define QT_FT_BEGIN_HEADER #define QT_FT_END_HEADER @@ -99,25 +100,25 @@ class QRasterPaintEngineState; typedef QT_FT_SpanFunc ProcessSpans; typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride); typedef void (*AlphamapBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); typedef void (*AlphaRGBBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uint *rgbmask, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); typedef void (*RectFillFunc)(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color); + const QRgba64 &color); typedef void (*SrcOverBlendFunc)(uchar *destPixels, int dbpl, const uchar *src, int spbl, @@ -158,11 +159,14 @@ extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3]; extern DrawHelper qDrawHelper[QImage::NImageFormats]; void qBlendTexture(int count, const QSpan *spans, void *userData); +extern void qt_memfill64(quint64 *dest, quint64 value, int count); extern void qt_memfill32(quint32 *dest, quint32 value, int count); extern void qt_memfill16(quint16 *dest, quint16 value, int count); typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunction64)(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha); typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunctionSolid64)(QRgba64 *dest, int length, QRgba64 color, uint const_alpha); struct LinearGradientValues { @@ -185,17 +189,27 @@ struct RadialGradientValues struct Operator; typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); +typedef QRgba64* (QT_FASTCALL *DestFetchProc64)(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); +typedef void (QT_FASTCALL *DestStoreProc64)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length); typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); +typedef const QRgba64* (QT_FASTCALL *SourceFetchProc64)(QRgba64 *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); struct Operator { QPainter::CompositionMode mode; - DestFetchProc dest_fetch; - DestStoreProc dest_store; - SourceFetchProc src_fetch; + DestFetchProc destFetch; + DestStoreProc destStore; + SourceFetchProc srcFetch; CompositionFunctionSolid funcSolid; CompositionFunction func; + + DestFetchProc64 destFetch64; + DestStoreProc64 destStore64; + SourceFetchProc64 srcFetch64; + CompositionFunctionSolid64 funcSolid64; + CompositionFunction64 func64; + union { LinearGradientValues linear; RadialGradientValues radial; @@ -208,7 +222,7 @@ class QRasterPaintEngine; struct QSolidData { - uint color; + QRgba64 color; }; struct QLinearGradientData @@ -259,7 +273,7 @@ struct QGradientData #define GRADIENT_STOPTABLE_SIZE 1024 #define GRADIENT_STOPTABLE_SIZE_SHIFT 10 - uint* colorTable; //[GRADIENT_STOPTABLE_SIZE]; + QRgba64* colorTable; //[GRADIENT_STOPTABLE_SIZE]; uint alphaColor : 1; }; @@ -367,6 +381,12 @@ static inline uint qt_gradient_clamp(const QGradientData *data, int ipos) static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos) { int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); + return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); +} + +static inline const QRgba64& qt_gradient_pixel64(const QGradientData *data, qreal pos) +{ + int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); return data->colorTable[qt_gradient_clamp(data, ipos)]; } @@ -375,24 +395,24 @@ static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c) return (b * b) - (4 * a * c); } -template <class RadialFetchFunc> Q_STATIC_TEMPLATE_FUNCTION -const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const Operator *op, const QSpanData *data, - int y, int x, int length) +template <class RadialFetchFunc, typename BlendType> static +const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffer, const Operator *op, + const QSpanData *data, int y, int x, int length) { // avoid division by zero if (qFuzzyIsNull(op->radial.a)) { - qt_memfill32(buffer, 0, length); + RadialFetchFunc::memfill(buffer, RadialFetchFunc::null(), length); return buffer; } - const uint *b = buffer; + const BlendType *b = buffer; qreal rx = data->m21 * (y + qreal(0.5)) + data->dx + data->m11 * (x + qreal(0.5)); qreal ry = data->m22 * (y + qreal(0.5)) + data->dy + data->m12 * (x + qreal(0.5)); bool affine = !data->m13 && !data->m23; - uint *end = buffer + length; + BlendType *end = buffer + length; if (affine) { rx -= data->gradient.radial.focal.x; ry -= data->gradient.radial.focal.y; @@ -439,7 +459,7 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const O qreal b = 2*(op->radial.dr*data->gradient.radial.focal.radius + gx*op->radial.dx + gy*op->radial.dy); qreal det = qRadialDeterminant(op->radial.a, b, op->radial.sqrfr - (gx*gx + gy*gy)); - quint32 result = 0; + BlendType result = RadialFetchFunc::null(); if (det >= 0) { qreal detSqrt = qSqrt(det); @@ -449,7 +469,7 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const O qreal s = qMax(s0, s1); if (data->gradient.radial.focal.radius + op->radial.dr * s >= 0) - result = qt_gradient_pixel(&data->gradient, s); + result = RadialFetchFunc::fetchSingle(data->gradient, s); } *buffer = result; @@ -470,6 +490,15 @@ template <class Simd> class QRadialFetchSimd { public: + static uint null() { return 0; } + static uint fetchSingle(const QGradientData& gradient, qreal v) + { + return qt_gradient_pixel(&gradient, v); + } + static void memfill(uint *buffer, uint fill, int length) + { + qt_memfill32(buffer, fill, length); + } static void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det, qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b) { @@ -526,7 +555,7 @@ public: delta_det4_vec.v = Simd::v_add(delta_det4_vec.v, v_delta_delta_det16); \ b_vec.v = Simd::v_add(b_vec.v, v_delta_b4); \ for (int i = 0; i < 4; ++i) \ - *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]]; \ + *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]].toArgb32(); \ } #define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \ @@ -680,7 +709,8 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) { return t; } -static Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } static Q_ALWAYS_INLINE uint BYTE_MUL_RGB30(uint x, uint a) { uint xa = x >> 30; @@ -723,6 +753,11 @@ inline quint24::operator uint() const template <class T> Q_STATIC_TEMPLATE_FUNCTION void qt_memfill(T *dest, T value, int count); +template<> inline void qt_memfill(quint64 *dest, quint64 color, int count) +{ + qt_memfill64(dest, color, count); +} + template<> inline void qt_memfill(quint32 *dest, quint32 color, int count) { qt_memfill32(dest, color, count); @@ -924,6 +959,64 @@ inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c) | ((c >> 2) & 0x000000ff); } +template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb); + +template<> +inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb) +{ + quint16 alpha = rgb >> 30; + quint16 blue = (rgb >> 20) & 0x3ff; + quint16 green = (rgb >> 10) & 0x3ff; + quint16 red = rgb & 0x3ff; + // Expand the range. + alpha |= (alpha << 2); + alpha |= (alpha << 4); + alpha |= (alpha << 8); + red = (red << 6) | (red >> 4); + green = (green << 6) | (green >> 4); + blue = (blue << 6) | (blue >> 4); + return qRgba64(red, green, blue, alpha); +} + +template<> +inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb) +{ + quint16 alpha = rgb >> 30; + quint16 red = (rgb >> 20) & 0x3ff; + quint16 green = (rgb >> 10) & 0x3ff; + quint16 blue = rgb & 0x3ff; + // Expand the range. + alpha |= (alpha << 2); + alpha |= (alpha << 4); + alpha |= (alpha << 8); + red = (red << 6) | (red >> 4); + green = (green << 6) | (green >> 4); + blue = (blue << 6) | (blue >> 4); + return qRgba64(red, green, blue, alpha); +} + +template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64); + +template<> +inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c) +{ + const uint a = c.alpha() >> 14; + const uint r = c.red() >> 6; + const uint g = c.green() >> 6; + const uint b = c.blue() >> 6; + return (a << 30) | (b << 20) | (g << 10) | r; +} + +template<> +inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c) +{ + const uint a = c.alpha() >> 14; + const uint r = c.red() >> 6; + const uint g = c.green() >> 6; + const uint b = c.blue() >> 6; + return (a << 30) | (r << 20) | (g << 10) | b; +} + inline uint qRgbSwapRgb30(uint c) { const uint ag = c & 0xc00ffc00; @@ -1025,89 +1118,11 @@ inline int comp_func_Plus_one_pixel(uint d, const uint s) #undef MIX #undef AMIX -// prototypes of all the composition functions -void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha); -void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint); -void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_SourceOrDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_SourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_SourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_NotSourceOrDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_SourceOrNotDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_ClearDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_SetDestination(uint *dest, const uint *src, int length, uint const_alpha); -void QT_FASTCALL rasterop_NotDestination(uint *dest, const uint *src, int length, uint const_alpha); -// prototypes of all the solid composition functions -void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Destination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_ClearDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_SetDestination(uint *dest, int length, uint color, uint const_alpha); -void QT_FASTCALL rasterop_solid_NotDestination(uint *dest, int length, uint color, uint const_alpha); - - struct QPixelLayout; typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count, const QPixelLayout *layout, const QRgb *clut); +typedef const QRgba64 *(QT_FASTCALL *ConvertFunc64)(QRgba64 *buffer, const uint *src, int count, + const QPixelLayout *layout, const QRgb *clut); struct QPixelLayout { @@ -1137,6 +1152,7 @@ struct QPixelLayout ConvertFunc convertToARGB32PM; ConvertFunc convertFromARGB32PM; ConvertFunc convertFromRGB32; + ConvertFunc64 convertToARGB64PM; }; typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count); diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 84eb3b7909..d7f3686e54 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -311,90 +311,6 @@ void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, u } } -#ifndef QDRAWHELPER_AVX -CompositionFunctionSolid qt_functionForModeSolid_SSE2[numCompositionFunctions] = { - comp_func_solid_SourceOver_sse2, - comp_func_solid_DestinationOver, - comp_func_solid_Clear, - comp_func_solid_Source, - comp_func_solid_Destination, - comp_func_solid_SourceIn, - comp_func_solid_DestinationIn, - comp_func_solid_SourceOut, - comp_func_solid_DestinationOut, - comp_func_solid_SourceAtop, - comp_func_solid_DestinationAtop, - comp_func_solid_XOR, - comp_func_solid_Plus, - comp_func_solid_Multiply, - comp_func_solid_Screen, - comp_func_solid_Overlay, - comp_func_solid_Darken, - comp_func_solid_Lighten, - comp_func_solid_ColorDodge, - comp_func_solid_ColorBurn, - comp_func_solid_HardLight, - comp_func_solid_SoftLight, - comp_func_solid_Difference, - comp_func_solid_Exclusion, - rasterop_solid_SourceOrDestination, - rasterop_solid_SourceAndDestination, - rasterop_solid_SourceXorDestination, - rasterop_solid_NotSourceAndNotDestination, - rasterop_solid_NotSourceOrNotDestination, - rasterop_solid_NotSourceXorDestination, - rasterop_solid_NotSource, - rasterop_solid_NotSourceAndDestination, - rasterop_solid_SourceAndNotDestination, - rasterop_solid_NotSourceOrDestination, - rasterop_solid_SourceOrNotDestination, - rasterop_solid_ClearDestination, - rasterop_solid_SetDestination, - rasterop_solid_NotDestination -}; - -CompositionFunction qt_functionForMode_SSE2[numCompositionFunctions] = { - comp_func_SourceOver_sse2, - comp_func_DestinationOver, - comp_func_Clear, - comp_func_Source_sse2, - comp_func_Destination, - comp_func_SourceIn, - comp_func_DestinationIn, - comp_func_SourceOut, - comp_func_DestinationOut, - comp_func_SourceAtop, - comp_func_DestinationAtop, - comp_func_XOR, - comp_func_Plus_sse2, - comp_func_Multiply, - comp_func_Screen, - comp_func_Overlay, - comp_func_Darken, - comp_func_Lighten, - comp_func_ColorDodge, - comp_func_ColorBurn, - comp_func_HardLight, - comp_func_SoftLight, - comp_func_Difference, - comp_func_Exclusion, - rasterop_SourceOrDestination, - rasterop_SourceAndDestination, - rasterop_SourceXorDestination, - rasterop_NotSourceAndNotDestination, - rasterop_NotSourceOrNotDestination, - rasterop_NotSourceXorDestination, - rasterop_NotSource, - rasterop_NotSourceAndDestination, - rasterop_SourceAndNotDestination, - rasterop_NotSourceOrDestination, - rasterop_SourceOrNotDestination, - rasterop_ClearDestination, - rasterop_SetDestination, - rasterop_NotDestination -}; -#endif - void qt_memfill16(quint16 *dest, quint16 value, int count) { if (count < 3) { @@ -417,7 +333,7 @@ void qt_memfill16(quint16 *dest, quint16 value, int count) dest[count - 1] = value; } -void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, +void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride) { @@ -468,18 +384,25 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, } } +void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, + const QRgba64 &color, + const uchar *src, int width, int height, int stride) +{ + qt_bitmapblit32_sse2_base(rasterBuffer, x, y, color.toArgb32(), src, width, height, stride); +} + void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride) { - qt_bitmapblit32_sse2(rasterBuffer, x, y, ARGB2RGBA(color), src, width, height, stride); + qt_bitmapblit32_sse2_base(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), src, width, height, stride); } void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride) { - const quint16 c = qConvertRgb32To16(color); + const quint16 c = qConvertRgb32To16(color.toArgb32()); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); @@ -543,7 +466,7 @@ public: const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data, int y, int x, int length) { - return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdSse2> >(buffer, op, data, y, x, length); + return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdSse2>,uint>(buffer, op, data, y, x, length); } void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index 4d203c4f9d..50ee83aa2c 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -53,13 +53,13 @@ QT_BEGIN_NAMESPACE void qt_memfill32(quint32 *dest, quint32 value, int count); void qt_memfill16(quint16 *dest, quint16 value, int count); void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp index 867c64c5e0..7b6a71737d 100644 --- a/src/gui/painting/qimagescale.cpp +++ b/src/gui/painting/qimagescale.cpp @@ -77,8 +77,9 @@ QT_BEGIN_NAMESPACE * * Changes include formatting, namespaces and other C++'ings, removal of old * #ifdef'ed code, and removal of unneeded border calculation code. - * Later the code has been refactored and an SSE4.1 optimizated path have been - * added instead of the removed MMX assembler. + * Later the code has been refactored, an SSE4.1 optimizated path have been + * added instead of the removed MMX assembler, and scaling of clipped area + * removed. * * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code * is by Willem Monsuwe <willem@stack.nl>. All other modifications are @@ -256,34 +257,27 @@ QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img, static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow); + int dw, int dh, int dow, int sow); #if defined(QT_COMPILER_SUPPORTS_SSE4_1) template<bool RGB> void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); template<bool RGB> void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); template<bool RGB> void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); #endif static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; @@ -291,15 +285,14 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; /* go through every scanline in the output buffer */ for (int y = 0; y < dh; y++) { /* calculate the source line we'll scan from */ - const unsigned int *sptr = ypoints[dyy + y]; - unsigned int *dptr = dest + dx + ((y + dy) * dow); - const int yap = yapoints[dyy + y]; + const unsigned int *sptr = ypoints[y]; + unsigned int *dptr = dest + (y * dow); + const int yap = yapoints[y]; if (yap > 0) { - for (int x = dxx; x < end; x++) { + for (int x = 0; x < dw; x++) { const unsigned int *pix = sptr + xpoints[x]; const int xap = xapoints[x]; if (xap > 0) @@ -309,7 +302,7 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, dptr++; } } else { - for (int x = dxx; x < end; x++) { + for (int x = 0; x < dw; x++) { const unsigned int *pix = sptr + xpoints[x]; const int xap = xapoints[x]; *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap); @@ -321,39 +314,38 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, /* scale by area sampling */ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow) + int dw, int dh, int dow, int sow) { /* scaling up both ways */ if (isi->xup_yup == 3) { - qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_up_xy(isi, dest, dw, dh, dow, sow); } /* if we're scaling down vertically */ else if (isi->xup_yup == 1) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(isi, dest, dw, dh, dow, sow); else #endif - qt_qimageScaleAARGBA_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_up_x_down_y(isi, dest, dw, dh, dow, sow); } /* if we're scaling down horizontally */ else if (isi->xup_yup == 2) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dw, dh, dow, sow); else #endif - qt_qimageScaleAARGBA_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_down_x_up_y(isi, dest, dw, dh, dow, sow); } /* if we're scaling down horizontally & vertically */ else { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - qt_qimageScaleAARGBA_down_xy_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_down_xy_sse4<false>(isi, dest, dw, dh, dow, sow); else #endif - qt_qimageScaleAARGBA_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_down_xy(isi, dest, dw, dh, dow, sow); } } @@ -379,7 +371,6 @@ inline static void qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap } static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; @@ -387,16 +378,14 @@ static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - /* go through every scanline in the output buffer */ for (int y = 0; y < dh; y++) { - int Cy = (yapoints[dyy + y]) >> 16; - int yap = (yapoints[dyy + y]) & 0xffff; + int Cy = yapoints[y] >> 16; + int yap = yapoints[y] & 0xffff; - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { + const unsigned int *sptr = ypoints[y] + xpoints[x]; int r, g, b, a; qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, r, g, b, a); @@ -420,7 +409,6 @@ static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int } static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; @@ -428,20 +416,18 @@ static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - /* go through every scanline in the output buffer */ for (int y = 0; y < dh; y++) { - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { int Cx = xapoints[x] >> 16; int xap = xapoints[x] & 0xffff; - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + const unsigned int *sptr = ypoints[y] + xpoints[x]; int r, g, b, a; qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, r, g, b, a); - int yap = yapoints[dyy + y]; + int yap = yapoints[y]; if (yap > 0) { int rr, gg, bb, aa; qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa); @@ -462,26 +448,23 @@ static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int } static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow) + int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; int *xpoints = isi->xpoints; int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - for (int y = 0; y < dh; y++) { - int Cy = (yapoints[dyy + y]) >> 16; - int yap = (yapoints[dyy + y]) & 0xffff; + int Cy = (yapoints[y]) >> 16; + int yap = (yapoints[y]) & 0xffff; - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { int Cx = xapoints[x] >> 16; int xap = xapoints[x] & 0xffff; - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + const unsigned int *sptr = ypoints[y] + xpoints[x]; int rx, gx, bx, ax; qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax); @@ -514,52 +497,48 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des } static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow); + int dw, int dh, int dow, int sow); static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow); + int dw, int dh, int dow, int sow); static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow); + int dw, int dh, int dow, int sow); /* scale by area sampling - IGNORE the ALPHA byte*/ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow) { /* scaling up both ways */ if (isi->xup_yup == 3) { - qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_up_xy(isi, dest, dw, dh, dow, sow); } /* if we're scaling down vertically */ else if (isi->xup_yup == 1) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(isi, dest, dw, dh, dow, sow); else #endif - qt_qimageScaleAARGB_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGB_up_x_down_y(isi, dest, dw, dh, dow, sow); } /* if we're scaling down horizontally */ else if (isi->xup_yup == 2) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(isi, dest, dw, dh, dow, sow); else #endif - qt_qimageScaleAARGB_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGB_down_x_up_y(isi, dest, dw, dh, dow, sow); } /* if we're scaling down horizontally & vertically */ else { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - qt_qimageScaleAARGBA_down_xy_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGBA_down_xy_sse4<true>(isi, dest, dw, dh, dow, sow); else #endif - qt_qimageScaleAARGB_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow); + qt_qimageScaleAARGB_down_xy(isi, dest, dw, dh, dow, sow); } } @@ -583,24 +562,21 @@ inline static void qt_qimageScaleAARGB_helper(const unsigned int *pix, int xyap, } static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow) + int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; int *xpoints = isi->xpoints; int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - /* go through every scanline in the output buffer */ for (int y = 0; y < dh; y++) { - int Cy = (yapoints[dyy + y]) >> 16; - int yap = (yapoints[dyy + y]) & 0xffff; + int Cy = yapoints[y] >> 16; + int yap = yapoints[y] & 0xffff; - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { + const unsigned int *sptr = ypoints[y] + xpoints[x]; int r, g, b; qt_qimageScaleAARGB_helper(sptr, yap, Cy, sow, r, g, b); @@ -622,28 +598,25 @@ static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int * } static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow) + int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; int *xpoints = isi->xpoints; int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - /* go through every scanline in the output buffer */ for (int y = 0; y < dh; y++) { - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { int Cx = xapoints[x] >> 16; int xap = xapoints[x] & 0xffff; - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + const unsigned int *sptr = ypoints[y] + xpoints[x]; int r, g, b; qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, r, g, b); - int yap = yapoints[dyy + y]; + int yap = yapoints[y]; if (yap > 0) { int rr, bb, gg; qt_qimageScaleAARGB_helper(sptr + sow, xap, Cx, 1, rr, gg, bb); @@ -661,26 +634,23 @@ static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int * } static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, - int dh, int dow, int sow) + int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; int *xpoints = isi->xpoints; int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - for (int y = 0; y < dh; y++) { - int Cy = (yapoints[dyy + y]) >> 16; - int yap = (yapoints[dyy + y]) & 0xffff; + int Cy = yapoints[y] >> 16; + int yap = yapoints[y] & 0xffff; - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { int Cx = xapoints[x] >> 16; int xap = xapoints[x] & 0xffff; - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + const unsigned int *sptr = ypoints[y] + xpoints[x]; int rx, gx, bx; qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx); @@ -732,10 +702,10 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh) if (src.hasAlphaChannel()) qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0), - 0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4); + dw, dh, dw, src.bytesPerLine() / 4); else qt_qimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0), - 0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4); + dw, dh, dw, src.bytesPerLine() / 4); qimageFreeScaleInfo(scaleinfo); return buffer; diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp index 303e0fd980..8712b5d324 100644 --- a/src/gui/painting/qimagescale_sse4.cpp +++ b/src/gui/painting/qimagescale_sse4.cpp @@ -59,7 +59,6 @@ inline static __m128i qt_qimageScaleAARGBA_helper(const unsigned int *pix, int x template<bool RGB> void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; @@ -67,20 +66,18 @@ void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *d int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - const __m128i v256 = _mm_set1_epi32(256); /* go through every scanline in the output buffer */ for (int y = 0; y < dh; y++) { - int Cy = (yapoints[dyy + y]) >> 16; - int yap = (yapoints[dyy + y]) & 0xffff; + int Cy = yapoints[y] >> 16; + int yap = yapoints[y] & 0xffff; const __m128i vCy = _mm_set1_epi32(Cy); const __m128i vyap = _mm_set1_epi32(yap); - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { + const unsigned int *sptr = ypoints[y] + xpoints[x]; __m128i vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, vyap, vCy); int xap = xapoints[x]; @@ -107,7 +104,6 @@ void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *d template<bool RGB> void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; @@ -115,23 +111,21 @@ void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *d int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; - int end = dxx + dw; - const __m128i v256 = _mm_set1_epi32(256); /* go through every scanline in the output buffer */ for (int y = 0; y < dh; y++) { - unsigned int *dptr = dest + dx + ((y + dy) * dow); - for (int x = dxx; x < end; x++) { + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { int Cx = xapoints[x] >> 16; int xap = xapoints[x] & 0xffff; const __m128i vCx = _mm_set1_epi32(Cx); const __m128i vxap = _mm_set1_epi32(xap); - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + const unsigned int *sptr = ypoints[y] + xpoints[x]; __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx); - int yap = yapoints[dyy + y]; + int yap = yapoints[y]; if (yap > 0) { const __m128i vyap = _mm_set1_epi32(yap); const __m128i vinvyap = _mm_sub_epi32(v256, vyap); @@ -155,7 +149,6 @@ void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *d template<bool RGB> void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow) { const unsigned int **ypoints = isi->ypoints; @@ -164,20 +157,19 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest, int *yapoints = isi->yapoints; for (int y = 0; y < dh; y++) { - int Cy = (yapoints[dyy + y]) >> 16; - int yap = (yapoints[dyy + y]) & 0xffff; + int Cy = yapoints[y] >> 16; + int yap = yapoints[y] & 0xffff; const __m128i vCy = _mm_set1_epi32(Cy); const __m128i vyap = _mm_set1_epi32(yap); - unsigned int *dptr = dest + dx + ((y + dy) * dow); - int end = dxx + dw; - for (int x = dxx; x < end; x++) { + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { const int Cx = xapoints[x] >> 16; const int xap = xapoints[x] & 0xffff; const __m128i vCx = _mm_set1_epi32(Cx); const __m128i vxap = _mm_set1_epi32(xap); - const unsigned int *sptr = ypoints[dyy + y] + xpoints[x]; + const unsigned int *sptr = ypoints[y] + xpoints[x]; __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx); __m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap); @@ -203,27 +195,21 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest, } template void qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); template void qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); template void qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); template void qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); template void qt_qimageScaleAARGBA_down_xy_sse4<false>(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); template void qt_qimageScaleAARGBA_down_xy_sse4<true>(QImageScaleInfo *isi, unsigned int *dest, - int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow); QT_END_NAMESPACE diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index acedc6a7ba..e4d756c18d 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -31,9 +31,11 @@ ** ****************************************************************************/ +#include "qmatrix.h" + #include "qdatastream.h" #include "qdebug.h" -#include "qmatrix.h" +#include "qhashfunctions.h" #include "qregion.h" #include "qpainterpath.h" #include "qpainterpath_p.h" @@ -972,6 +974,26 @@ bool QMatrix::operator==(const QMatrix &m) const _dy == m._dy; } + +/*! + \since 5.6 + \relates QMatrix + + Returns the hash value for \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QMatrix &key, uint seed) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(key.m11(), seed); + seed = hash(key.m12(), seed); + seed = hash(key.m21(), seed); + seed = hash(key.m22(), seed); + seed = hash(key.dx(), seed); + seed = hash(key.dy(), seed); + return seed; +} + /*! \fn bool QMatrix::operator!=(const QMatrix &matrix) const diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h index ddffa8a8b9..c036e4df93 100644 --- a/src/gui/painting/qmatrix.h +++ b/src/gui/painting/qmatrix.h @@ -126,6 +126,8 @@ private: }; Q_DECLARE_TYPEINFO(QMatrix, Q_MOVABLE_TYPE); +Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QMatrix &key, uint seed = 0) Q_DECL_NOTHROW; + // mathematical semantics inline QPoint operator*(const QPoint &p, const QMatrix &m) { return m.map(p); } diff --git a/src/gui/painting/qpagedpaintdevice.cpp b/src/gui/painting/qpagedpaintdevice.cpp index 3adc5e9411..547cedf51f 100644 --- a/src/gui/painting/qpagedpaintdevice.cpp +++ b/src/gui/painting/qpagedpaintdevice.cpp @@ -36,6 +36,10 @@ QT_BEGIN_NAMESPACE +QPagedPaintDevicePrivate::~QPagedPaintDevicePrivate() +{ +} + /*! \class QPagedPaintDevice \inmodule QtGui diff --git a/src/gui/painting/qpagedpaintdevice_p.h b/src/gui/painting/qpagedpaintdevice_p.h index 62f69747db..30b1c0a1e6 100644 --- a/src/gui/painting/qpagedpaintdevice_p.h +++ b/src/gui/painting/qpagedpaintdevice_p.h @@ -61,9 +61,7 @@ public: { } - virtual ~QPagedPaintDevicePrivate() - { - } + virtual ~QPagedPaintDevicePrivate(); // ### Qt6 Remove these and make public class methods virtual virtual bool setPageLayout(const QPageLayout &newPageLayout) diff --git a/src/gui/painting/qpagelayout.h b/src/gui/painting/qpagelayout.h index 17e5eeece2..7eac348c43 100644 --- a/src/gui/painting/qpagelayout.h +++ b/src/gui/painting/qpagelayout.h @@ -75,14 +75,13 @@ public: const QMarginsF &margins, Unit units = Point, const QMarginsF &minMargins = QMarginsF(0, 0, 0, 0)); QPageLayout(const QPageLayout &other); - ~QPageLayout(); - - QPageLayout &operator=(const QPageLayout &other); - #ifdef Q_COMPILER_RVALUE_REFS - QPageLayout &operator=(QPageLayout &&other) { swap(other); return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + QPageLayout &operator=(QPageLayout &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif + QPageLayout &operator=(const QPageLayout &other); + ~QPageLayout(); - void swap(QPageLayout &other) { d.swap(other.d); } + void swap(QPageLayout &other) Q_DECL_NOTHROW { qSwap(d, other.d); } friend Q_GUI_EXPORT bool operator==(const QPageLayout &lhs, const QPageLayout &rhs); bool isEquivalentTo(const QPageLayout &other) const; diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h index 00e22a243f..9119a582ac 100644 --- a/src/gui/painting/qpagesize.h +++ b/src/gui/painting/qpagesize.h @@ -229,14 +229,14 @@ public: const QString &name = QString(), SizeMatchPolicy matchPolicy = FuzzyMatch); QPageSize(const QPageSize &other); - ~QPageSize(); - - QPageSize &operator=(const QPageSize &other); #ifdef Q_COMPILER_RVALUE_REFS - QPageSize &operator=(QPageSize &&other) { swap(other); return *this; } + QPageSize &operator=(QPageSize &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif + QPageSize &operator=(const QPageSize &other); + ~QPageSize(); + - void swap(QPageSize &other) { d.swap(other.d); } + void swap(QPageSize &other) Q_DECL_NOTHROW { qSwap(d, other.d); } friend Q_GUI_EXPORT bool operator==(const QPageSize &lhs, const QPageSize &rhs); bool isEquivalentTo(const QPageSize &other) const; diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index 6ba26df3b4..ef93094387 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -968,6 +968,10 @@ QRect QPaintEngine::systemRect() const return d_func()->systemRect; } +QPaintEnginePrivate::~QPaintEnginePrivate() +{ +} + void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti) { if (!ti.glyphs.numGlyphs) diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index c58662ede4..918c98997b 100644 --- a/src/gui/painting/qpaintengine_p.h +++ b/src/gui/painting/qpaintengine_p.h @@ -60,7 +60,8 @@ class Q_GUI_EXPORT QPaintEnginePrivate public: QPaintEnginePrivate() : pdev(0), q_ptr(0), currentClipDevice(0), hasSystemTransform(0), hasSystemViewport(0) {} - virtual ~QPaintEnginePrivate() { } + virtual ~QPaintEnginePrivate(); + QPaintDevice *pdev; QPaintEngine *q_ptr; QRegion systemClip; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 18522cb6d0..f55dddfb6a 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -42,7 +42,6 @@ #include <qpainterpath.h> #include <qdebug.h> -#include <qhash.h> #include <qbitmap.h> #include <qmath.h> @@ -57,6 +56,7 @@ #include <private/qstatictext_p.h> #include <private/qcosmeticstroker_p.h> #include "qmemrotate_p.h" +#include "qrgba64_p.h" #include "qpaintengine_raster_p.h" // #include "qbezier_p.h" @@ -830,7 +830,7 @@ void QRasterPaintEngine::updateRasterState() && s->intOpacity == 256 && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(s->penData.solid.color) == 255)); + && s->penData.solid.color.isOpaque())); } s->dirty = 0; @@ -1412,10 +1412,9 @@ static void fillRect_normalized(const QRect &r, QSpanData *data, if (data->fillRect && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(data->solid.color) == 255))) + && data->solid.color.isOpaque()))) { - data->fillRect(data->rasterBuffer, x1, y1, width, height, - data->solid.color); + data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solid.color); return; } } @@ -1773,8 +1772,9 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(color.rgba64(), s->intOpacity)); + + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) { return; } @@ -2219,19 +2219,15 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe case QImage::Format_A2BGR30_Premultiplied: case QImage::Format_A2RGB30_Premultiplied: // Combine premultiplied color with the opacity set on the painter. - d->solid_color_filler.solid.color = - ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff) - | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); + d->solid_color_filler.solid.color = multiplyAlpha256(QRgba64::fromArgb32(color), s->intOpacity); break; default: - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color, s->intOpacity)); + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(QRgba64::fromArgb32(color), s->intOpacity)); break; } - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 - && s->composition_mode == QPainter::CompositionMode_SourceOver) { + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) return; - } d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); @@ -2756,12 +2752,12 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, QFixed spp = fontEngine->subPixelPositionForX(positions[i].x); QPoint offset; - QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, - &offset); + const QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, + &offset); if (alphaMap == 0 || alphaMap->isNull()) continue; - alphaPenBlt(alphaMap->bits(), alphaMap->bytesPerLine(), alphaMap->depth(), + alphaPenBlt(alphaMap->constBits(), alphaMap->bytesPerLine(), alphaMap->depth(), qFloor(positions[i].x) + offset.x(), qRound(positions[i].y) + offset.y(), alphaMap->width(), alphaMap->height()); @@ -4137,7 +4133,7 @@ class QGradientCache { inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) : stops(s), opacity(op), interpolationMode(mode) {} - uint buffer[GRADIENT_STOPTABLE_SIZE]; + QRgba64 buffer[GRADIENT_STOPTABLE_SIZE]; QGradientStops stops; int opacity; QGradient::InterpolationMode interpolationMode; @@ -4146,12 +4142,12 @@ class QGradientCache typedef QMultiHash<quint64, CacheInfo> QGradientColorTableHash; public: - inline const uint *getBuffer(const QGradient &gradient, int opacity) { + inline const QRgba64 *getBuffer(const QGradient &gradient, int opacity) { quint64 hash_val = 0; QGradientStops stops = gradient.stops(); for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); + hash_val += stops[i].second.rgba64(); QMutexLocker lock(&mutex); QGradientColorTableHash::const_iterator it = cache.constFind(hash_val); @@ -4174,9 +4170,9 @@ public: protected: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& g, - uint *colorTable, + QRgba64 *colorTable, int size, int opacity) const; - uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { + QRgba64 *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { // may remove more than 1, but OK cache.erase(cache.begin() + (qrand() % maxCacheSize())); @@ -4190,7 +4186,7 @@ protected: QMutex mutex; }; -void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, int opacity) const +void QGradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, int opacity) const { QGradientStops stops = gradient.stops(); int stopCount = stops.count(); @@ -4199,14 +4195,16 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); if (stopCount == 2) { - uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); - uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity); + QRgba64 first_color = combineAlpha256(stops[0].second.rgba64(), opacity); + QRgba64 second_color = combineAlpha256(stops[1].second.rgba64(), opacity); qreal first_stop = stops[0].first; qreal second_stop = stops[1].first; if (second_stop < first_stop) { - qSwap(first_color, second_color); + quint64 tmp = first_color; + first_color = second_color; + second_color = tmp; qSwap(first_stop, second_stop); } @@ -4218,15 +4216,15 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1)); int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1)); - uint red_first = qRed(first_color) << 16; - uint green_first = qGreen(first_color) << 16; - uint blue_first = qBlue(first_color) << 16; - uint alpha_first = qAlpha(first_color) << 16; + uint red_first = uint(first_color.red()) << 16; + uint green_first = uint(first_color.green()) << 16; + uint blue_first = uint(first_color.blue()) << 16; + uint alpha_first = uint(first_color.alpha()) << 16; - uint red_second = qRed(second_color) << 16; - uint green_second = qGreen(second_color) << 16; - uint blue_second = qBlue(second_color) << 16; - uint alpha_second = qAlpha(second_color) << 16; + uint red_second = uint(second_color.red()) << 16; + uint green_second = uint(second_color.green()) << 16; + uint blue_second = uint(second_color.blue()) << 16; + uint alpha_second = uint(second_color.alpha()) << 16; int i = 0; for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) { @@ -4239,10 +4237,10 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (i < second_index) { qreal reciprocal = qreal(1) / (second_index - first_index); - int red_delta = qRound(int(red_second - red_first) * reciprocal); - int green_delta = qRound(int(green_second - green_first) * reciprocal); - int blue_delta = qRound(int(blue_second - blue_first) * reciprocal); - int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal); + int red_delta = qRound((qreal(red_second) - red_first) * reciprocal); + int green_delta = qRound((qreal(green_second) - green_first) * reciprocal); + int blue_delta = qRound((qreal(blue_second) - blue_first) * reciprocal); + int alpha_delta = qRound((qreal(alpha_second) - alpha_first) * reciprocal); // rounding red_first += 1 << 15; @@ -4256,8 +4254,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint blue_first += blue_delta; alpha_first += alpha_delta; - const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000) - | ((green_first >> 8) & 0xff00) | (blue_first >> 16); + const QRgba64 color = qRgba64(red_first >> 16, green_first >> 16, blue_first >> 16, alpha_first >> 16); if (colorInterpolation) colorTable[i] = color; @@ -4276,7 +4273,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint return; } - uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); + QRgba64 current_color = combineAlpha256(stops[0].second.rgba64(), opacity); if (stopCount == 1) { current_color = qPremultiply(current_color); for (int i = 0; i < size; ++i) @@ -4289,7 +4286,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint qreal end_pos = stops[stopCount-1].first; int pos = 0; // The position in the color table. - uint next_color; + QRgba64 next_color; qreal incr = 1 / qreal(size); // the double increment. qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1) @@ -4313,8 +4310,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint ++current_stop; if (current_stop != 0) - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { current_color = qPremultiply(current_color); @@ -4333,9 +4330,9 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int idist = 256 - dist; if (colorInterpolation) - colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); + colorTable[pos] = interpolate256(current_color, idist, next_color, dist); else - colorTable[pos] = qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist)); ++pos; dpos += incr; @@ -4354,8 +4351,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (skip == 1) current_color = next_color; else - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { if (skip != 1) @@ -4372,7 +4369,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint } // After last point - current_color = qPremultiply(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity)); + current_color = qPremultiply(combineAlpha256(stops[stopCount - 1].second.rgba64(), opacity)); while (pos < size - 1) { colorTable[pos] = current_color; ++pos; @@ -4405,12 +4402,9 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode case Qt::SolidPattern: { type = Solid; QColor c = qbrush_color(brush); - QRgb rgba = c.rgba(); - solid.color = qPremultiply(ARGB_COMBINE_ALPHA(rgba, alpha)); - if ((solid.color & 0xff000000) == 0 - && compositionMode == QPainter::CompositionMode_SourceOver) { + solid.color = qPremultiply(combineAlpha256(c.rgba64(), alpha)); + if (solid.color.isTransparent() && compositionMode == QPainter::CompositionMode_SourceOver) type = None; - } break; } @@ -4419,7 +4413,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = LinearGradient; const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QLinearGradientData &linearData = gradient.linear; @@ -4436,7 +4430,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = RadialGradient; const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QRadialGradientData &radialData = gradient.radial; @@ -4457,7 +4451,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = ConicalGradient; const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = QGradient::RepeatSpread; QConicalGradientData &conicalData = gradient.conical; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 20608e5aee..1726bbe71f 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7470,7 +7470,7 @@ start_lengthVariant: } } - QList<QTextLayout::FormatRange> underlineFormats; + QVector<QTextLayout::FormatRange> underlineFormats; int length = offset - old_offset; if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) { QChar *cout = text.data() + old_offset; @@ -7526,6 +7526,7 @@ start_lengthVariant: if (engine.option.tabs().isEmpty() && ta) { QList<qreal> tabs; + tabs.reserve(tabarraylen); for (int i = 0; i < tabarraylen; i++) tabs.append(qreal(ta[i])); engine.option.setTabArray(tabs); @@ -7544,7 +7545,7 @@ start_lengthVariant: engine.forceJustification = true; QTextLayout textLayout(&engine); textLayout.setCacheEnabled(true); - textLayout.setAdditionalFormats(underlineFormats); + textLayout.setFormats(underlineFormats); if (finalText.isEmpty()) { height = fm.height(); diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 7c32dc1694..3ea4e35b8d 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -53,7 +53,6 @@ #include "QtGui/qpainter.h" #include "QtGui/qpainterpath.h" #include "QtGui/qpaintengine.h" -#include <QtCore/qhash.h> #include <private/qpen_p.h> diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 0798418c17..513fdfa2b6 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -1889,10 +1889,10 @@ bool QPathClipper::handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode m namespace { -QList<QPainterPath> toSubpaths(const QPainterPath &path) +QVector<QPainterPath> toSubpaths(const QPainterPath &path) { - QList<QPainterPath> subpaths; + QVector<QPainterPath> subpaths; if (path.isEmpty()) return subpaths; @@ -2092,7 +2092,7 @@ QPainterPath clip(const QPainterPath &path, qreal t) QPainterPath intersectPath(const QPainterPath &path, const QRectF &rect) { - QList<QPainterPath> subpaths = toSubpaths(path); + QVector<QPainterPath> subpaths = toSubpaths(path); QPainterPath result; result.setFillRule(path.fillRule()); diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 6ea0800538..1389112462 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1952,7 +1952,9 @@ int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from stops.append(QGradientStop(1, stops.at(stops.size() - 1).second)); QVector<int> functions; - for (int i = 0; i < stops.size() - 1; ++i) { + const int numStops = stops.size(); + functions.reserve(numStops - 1); + for (int i = 0; i < numStops - 1; ++i) { int f = addXrefEntry(-1); QByteArray data; QPdf::ByteStream s(&data); diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h index 94e74f30b9..2b50cdc6f7 100644 --- a/src/gui/painting/qpdf_p.h +++ b/src/gui/painting/qpdf_p.h @@ -243,7 +243,7 @@ public: QPointF brushOrigin; QBrush brush; QPen pen; - QList<QPainterPath> clips; + QVector<QPainterPath> clips; bool clipEnabled; bool allClipped; bool hasPen; diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index 6263d18b01..073d254b49 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -980,6 +980,7 @@ QDataStream &operator>>(QDataStream &s, QPen &p) quint32 numDashes; s >> numDashes; double dash; + dashPattern.reserve(numDashes); for (quint32 i = 0; i < numDashes; ++i) { s >> dash; dashPattern << dash; diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 62492980de..c1737e7746 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -220,7 +220,9 @@ static QRegion deviceRegion(const QRegion ®ion, QWindow *window) return region; QVector<QRect> rects; - foreach (QRect rect, region.rects()) + const QVector<QRect> regionRects = region.rects(); + rects.reserve(regionRects.count()); + foreach (const QRect &rect, regionRects) rects.append(deviceRect(rect, window)); QRegion deviceRegion; diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h index 1549ebe2b5..3890715f32 100644 --- a/src/gui/painting/qpolygon.h +++ b/src/gui/painting/qpolygon.h @@ -56,7 +56,11 @@ public: inline /*implicit*/ QPolygon(const QVector<QPoint> &v) : QVector<QPoint>(v) {} QPolygon(const QRect &r, bool closed=false); QPolygon(int nPoints, const int *points); - inline void swap(QPolygon &other) { QVector<QPoint>::swap(other); } // prevent QVector<QPoint><->QPolygon swaps +#ifdef Q_COMPILER_RVALUE_REFS + QPolygon &operator=(QPolygon &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif + QPolygon &operator=(const QPolygon &other) { QVector<QPoint>::operator=(other); return *this; } + void swap(QPolygon &other) Q_DECL_NOTHROW { QVector<QPoint>::swap(other); } // prevent QVector<QPoint><->QPolygon swaps operator QVariant() const; @@ -130,6 +134,10 @@ public: inline /*implicit*/ QPolygonF(const QVector<QPointF> &v) : QVector<QPointF>(v) {} QPolygonF(const QRectF &r); /*implicit*/ QPolygonF(const QPolygon &a); +#ifdef Q_COMPILER_RVALUE_REFS + QPolygonF &operator=(QPolygonF &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif + QPolygonF &operator=(const QPolygonF &other) { QVector<QPointF>::operator=(other); return *this; } inline void swap(QPolygonF &other) { QVector<QPointF>::swap(other); } // prevent QVector<QPointF><->QPolygonF swaps operator QVariant() const; diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h new file mode 100644 index 0000000000..290501047d --- /dev/null +++ b/src/gui/painting/qrgba64.h @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRGBA64_H +#define QRGBA64_H + +#include <QtCore/qglobal.h> +#include <QtCore/qprocessordetection.h> + +QT_BEGIN_NAMESPACE + +class QRgba64 { + struct qrgba_t { + quint16 red; + quint16 green; + quint16 blue; + quint16 alpha; + }; + + union { + struct qrgba_t c; + quint64 rgba; + }; +public: + // No constructors are allowed, since this needs to be usable in a union in no-c++11 mode. + // When c++11 is mandatory, we can add all but a copy constructor. + Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha) + { + QRgba64 rgba64 +#ifdef Q_COMPILER_UNIFORM_INIT + = {} +#endif + ; + + rgba64.c.red = red; + rgba64.c.green = green; + rgba64.c.blue = blue; + rgba64.c.alpha = alpha; + return rgba64; + } + Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba64(quint64 c) + { + QRgba64 rgba64 +#ifdef Q_COMPILER_UNIFORM_INIT + = {} +#endif + ; + rgba64.rgba = c; + return rgba64; + } + Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha) + { + QRgba64 rgb64 = fromRgba64(red, green, blue, alpha); + // Expand the range so that 0x00 maps to 0x0000 and 0xff maps to 0xffff. + rgb64.rgba |= rgb64.rgba << 8; + return rgb64; + } + Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromArgb32(uint rgb) + { + return fromRgba(rgb >> 16, rgb >> 8, rgb, rgb >> 24); + } + + Q_DECL_CONSTEXPR bool isOpaque() const { return c.alpha == 0xffff; } + Q_DECL_CONSTEXPR bool isTransparent() const { return c.alpha == 0; } + + Q_DECL_CONSTEXPR quint16 red() const { return c.red; } + Q_DECL_CONSTEXPR quint16 green() const { return c.green; } + Q_DECL_CONSTEXPR quint16 blue() const { return c.blue; } + Q_DECL_CONSTEXPR quint16 alpha() const { return c.alpha; } + void setRed(quint16 _red) { c.red = _red; } + void setGreen(quint16 _green) { c.green = _green; } + void setBlue(quint16 _blue) { c.blue = _blue; } + void setAlpha(quint16 _alpha) { c.alpha = _alpha; } + + Q_DECL_CONSTEXPR quint8 red8() const { return div_257(c.red); } + Q_DECL_CONSTEXPR quint8 green8() const { return div_257(c.green); } + Q_DECL_CONSTEXPR quint8 blue8() const { return div_257(c.blue); } + Q_DECL_CONSTEXPR quint8 alpha8() const { return div_257(c.alpha); } + Q_DECL_CONSTEXPR uint toArgb32() const + { + return (alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8(); + } + Q_DECL_CONSTEXPR ushort toRgb16() const + { + return (c.red & 0xf800) | ((c.green >> 10) << 5) | (c.blue >> 11); + } + + Q_DECL_RELAXED_CONSTEXPR QRgba64 premultiplied() const + { + const quint32 a = c.alpha; + const quint16 r = div_65535(c.red * a); + const quint16 g = div_65535(c.green * a); + const quint16 b = div_65535(c.blue * a); + return fromRgba64(r, g, b, a); + } + + Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied() const + { +#if Q_PROCESSOR_WORDSIZE < 8 + return unpremultiplied_32bit(); +#else + return unpremultiplied_64bit(); +#endif + } + + Q_DECL_CONSTEXPR operator quint64() const + { + return rgba; + } + + QRgba64 operator=(quint64 _rgba) + { + rgba = _rgba; + return *this; + } + +private: + static Q_DECL_CONSTEXPR uint div_257_floor(uint x) { return (x - (x >> 8)) >> 8; } + static Q_DECL_CONSTEXPR uint div_257(uint x) { return div_257_floor(x + 128); } + static Q_DECL_CONSTEXPR uint div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } + Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_32bit() const + { + if (c.alpha == 0xffff || c.alpha == 0) + return *this; + const quint16 r = (quint32(c.red) * 0xffff + c.alpha/2) / c.alpha; + const quint16 g = (quint32(c.green) * 0xffff + c.alpha/2) / c.alpha; + const quint16 b = (quint32(c.blue) * 0xffff + c.alpha/2) / c.alpha; + return fromRgba64(r, g, b, c.alpha); + } + Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_64bit() const + { + if (c.alpha == 0xffff || c.alpha == 0) + return *this; + const quint64 fa = (Q_UINT64_C(0xffff00008000) + c.alpha/2) / c.alpha; + const quint16 r = (c.red * fa + 0x80000000) >> 32; + const quint16 g = (c.green * fa + 0x80000000) >> 32; + const quint16 b = (c.blue * fa + 0x80000000) >> 32; + return fromRgba64(r, g, b, c.alpha); + } +}; + +Q_DECLARE_TYPEINFO(QRgba64, Q_PRIMITIVE_TYPE); + +Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a) +{ + return QRgba64::fromRgba64(r, g, b, a); +} + +Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qRgba64(quint64 c) +{ + return QRgba64::fromRgba64(c); +} + +Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qPremultiply(QRgba64 c) +{ + return c.premultiplied(); +} + +Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qUnpremultiply(QRgba64 c) +{ + return c.unpremultiplied(); +} + +inline Q_DECL_CONSTEXPR uint qRed(QRgba64 rgb) +{ return rgb.red8(); } + +inline Q_DECL_CONSTEXPR uint qGreen(QRgba64 rgb) +{ return rgb.green8(); } + +inline Q_DECL_CONSTEXPR uint qBlue(QRgba64 rgb) +{ return rgb.blue8(); } + +inline Q_DECL_CONSTEXPR uint qAlpha(QRgba64 rgb) +{ return rgb.alpha8(); } + +QT_END_NAMESPACE + +#endif // QRGBA64_H diff --git a/src/gui/painting/qrgba64.qdoc b/src/gui/painting/qrgba64.qdoc new file mode 100644 index 0000000000..29da0aa390 --- /dev/null +++ b/src/gui/painting/qrgba64.qdoc @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QRgba64 + \brief The QRgba64 struct contains a 64-bit RGB color. + \since 5.6 + + \ingroup painting + \inmodule QtGui + + QRgba64 is a 64-bit data-structure containing four 16-bit color channels: Red, green, blue and alpha. + + QRgba64 can be used a replacement for QRgb when higher precision is needed. In particular a + premultiplied QRgba64 can operate on unpremultipled QRgb without loss of precision except + for alpha 0. + + \sa QRgb, QColor +*/ + +/*! + \fn static QRgba64 QRgba64::fromRgba64(quint16 r, quint16 g, quint16 b, quint16 a) + + Returns the QRgba64 quadruplet (\a{r}, \a{g}, \a{b}, \a{a}). + + \sa fromRgba() +*/ + +/*! + \fn static QRgba64 QRgba64::fromRgba64(quint64 c) + + Returns \a c as a QRgba64 struct. + + \sa fromArgb32() +*/ + +/*! + \fn static QRgba64 QRgba64::fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha) + + Constructs a QRgba64 value from the four 8-bit color channels \a red, \a green, \a blue and \a alpha. + + \sa fromArgb32() +*/ + +/*! + \fn static QRgba64 QRgba64::fromArgb32(uint rgb) + + Constructs a QRgba64 value from the 32bit ARGB value \a rgb. + + \sa fromRgba() +*/ + +/*! + \fn quint16 QRgba64::red() const + + Returns the 16-bit red color component. +*/ + +/*! + \fn quint16 QRgba64::green() const + + Returns the 16-bit green color component. +*/ + +/*! + \fn quint16 QRgba64::blue() const + + Returns the 16-bit blue color component. +*/ + +/*! + \fn quint16 QRgba64::alpha() const + + Returns the 16-bit alpha channel. +*/ + +/*! + \fn quint8 QRgba64::red8() const + + Returns the red color component as an 8-bit. +*/ + +/*! + \fn quint8 QRgba64::green8() const + + Returns the green color component as an 8-bit. +*/ + +/*! + \fn quint8 QRgba64::blue8() const + + Returns the blue color component as an 8-bit. +*/ + +/*! + \fn quint8 QRgba64::alpha8() const + + Returns the alpha channel as an 8-bit. +*/ + +/*! + \fn uint QRgba64::toArgb32() const + + Returns the color as a 32-bit ARGB value. + + \sa fromArgb32() +*/ + +/*! + \fn ushort QRgba64::toRgb16() const + + Returns the color as a 16-bit RGB value. + + \sa toArgb32() +*/ + +/*! + \fn QRgba64 QRgba64::premultiplied() const + + Returns the color with the alpha premultiplied. + + \sa unpremultiplied() +*/ + +/*! + \fn QRgba64 QRgba64::unpremultiplied() const + + Returns the color with the alpha unpremultiplied. + + \sa premultiplied() +*/ + +/*! + \fn QRgba64::operator quint64() const + + Returns the color as a 64bit unsigned integer +*/ + +/*! + \fn QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a) + \relates QColor + \since 5.6 + + Returns the QRgba64 quadruplet (\a{r}, \a{g}, \a{b}, \a{a}). + + \sa qRgba() +*/ + +/*! + \fn QRgba64 qRgba64(quint64 c) + \relates QColor + \since 5.6 + + Returns \a c as a QRgba64 struct. + + \sa qRgba() +*/ + +/*! + \fn QRgba64 qPremultiply(QRgba64 rgba64) + \since 5.6 + \relates QColor + + Converts an unpremultiplied QRgba64 quadruplet \a rgba64 into a premultiplied QRgba64 quadruplet. + + \sa QRgba64::premultiplied(), qUnpremultiply() +*/ + +/*! + \fn QRgba64 qUnpremultiply(QRgba64 rgba64) + \since 5.6 + \relates QColor + + Converts a premultiplied QRgba64 quadruplet \a rgba64 into an unpremultiplied QRgba64 quadruplet. + + \sa QRgba64::unpremultiplied(), qPremultiply() +*/ + +/*! + \fn uint qRed(QRgba64 rgba64) + \since 5.6 + \relates QColor + + Returns the red component of \a rgba64 as an 8-bit value. + + \sa QRgba64::red8(), QColor::red() +*/ + +/*! + \fn uint qGreen(QRgba64 rgba64) + \since 5.6 + \relates QColor + + Returns the green component of \a rgba64 as an 8-bit value. + + \sa QRgba64::green8(), QColor::green() +*/ + +/*! + \fn uint qBlue(QRgba64 rgba64) + \since 5.6 + \relates QColor + + Returns the blue component of \a rgba64 as an 8-bit value. + + \sa QRgba64::blue8(), QColor::blue() +*/ + +/*! + \fn uint qAlpha(QRgba64 rgba64) + \since 5.6 + \relates QColor + + Returns the alpha component of \a rgba64 as an 8-bit value. + + \sa QRgba64::alpha8(), QColor::alpha() +*/ diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h new file mode 100644 index 0000000000..c6cbe666ac --- /dev/null +++ b/src/gui/painting/qrgba64_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRGBA64_P_H +#define QRGBA64_P_H + +#include <QtGui/qrgba64.h> +#include <QtGui/private/qdrawhelper_p.h> +#include <private/qsimd_p.h> + +QT_BEGIN_NAMESPACE + +inline QRgba64 combineAlpha256(QRgba64 rgba64, uint alpha256) +{ + return QRgba64::fromRgba64(rgba64.red(), rgba64.green(), rgba64.blue(), (rgba64.alpha() * alpha256) >> 8); +} + +inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256) +{ + return QRgba64::fromRgba64((rgba64.red() * alpha256) >> 8, + (rgba64.green() * alpha256) >> 8, + (rgba64.blue() * alpha256) >> 8, + (rgba64.alpha() * alpha256) >> 8); +} + +inline QRgba64 multiplyAlpha65535(QRgba64 rgba64, uint alpha65535) +{ +#ifdef __SSE2__ + const __m128i va = _mm_shufflelo_epi16(_mm_cvtsi32_si128(alpha65535), _MM_SHUFFLE(0, 0, 0, 0)); + __m128i vs = _mm_loadl_epi64((__m128i*)&rgba64); + vs = _mm_unpacklo_epi16(_mm_mullo_epi16(vs, va), _mm_mulhi_epu16(vs, va)); + vs = _mm_add_epi32(vs, _mm_srli_epi32(vs, 16)); + vs = _mm_add_epi32(vs, _mm_set1_epi32(0x8000)); + vs = _mm_srai_epi32(vs, 16); + vs = _mm_packs_epi32(vs, _mm_setzero_si128()); + _mm_storel_epi64((__m128i*)&rgba64, vs); + return rgba64; +#else + return QRgba64::fromRgba64(qt_div_65535(rgba64.red() * alpha65535), + qt_div_65535(rgba64.green() * alpha65535), + qt_div_65535(rgba64.blue() * alpha65535), + qt_div_65535(rgba64.alpha() * alpha65535)); +#endif +} + +inline QRgba64 multiplyAlpha255(QRgba64 rgba64, uint alpha255) +{ +#ifdef __SSE2__ + return multiplyAlpha65535(rgba64, alpha255 * 257); +#else + return QRgba64::fromRgba64(qt_div_255(rgba64.red() * alpha255), + qt_div_255(rgba64.green() * alpha255), + qt_div_255(rgba64.blue() * alpha255), + qt_div_255(rgba64.alpha() * alpha255)); +#endif +} + +inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2) +{ + return QRgba64::fromRgba64(multiplyAlpha256(x, alpha1) + multiplyAlpha256(y, alpha2)); +} + +inline QRgba64 interpolate255(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2) +{ + return QRgba64::fromRgba64(multiplyAlpha255(x, alpha1) + multiplyAlpha255(y, alpha2)); +} + +inline QRgba64 interpolate65535(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2) +{ + return QRgba64::fromRgba64(multiplyAlpha65535(x, alpha1) + multiplyAlpha65535(y, alpha2)); +} + +inline QRgba64 addWithSaturation(QRgba64 a, QRgba64 b) +{ +#if defined(__SSE2__) && defined(Q_PROCESSOR_X86_64) + __m128i va = _mm_cvtsi64_si128((quint64)a); + __m128i vb = _mm_cvtsi64_si128((quint64)b); + va = _mm_adds_epu16(va, vb); + return QRgba64::fromRgba64(_mm_cvtsi128_si64(va)); +#else + return QRgba64::fromRgba64(qMin(a.red() + b.red(), 65535), + qMin(a.green() + b.green(), 65535), + qMin(a.blue() + b.blue(), 65535), + qMin(a.alpha() + b.alpha(), 65535)); +#endif +} + +QT_END_NAMESPACE + +#endif // QRGBA64_P_H diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 4c879cf05d..44e14f656d 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -42,16 +42,24 @@ QT_BEGIN_NAMESPACE // #define CACHE_DEBUG +// out-of-line to avoid vtable duplication, breaking e.g. RTTI +QTextureGlyphCache::~QTextureGlyphCache() +{ +} + int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const { // Test 12 different subpixel positions since it factors into 3*4 so it gives // the coverage we need. - QList<QImage> images; - for (int i=0; i<12; ++i) { + const int NumSubpixelPositions = 12; + + QImage images[NumSubpixelPositions]; + int numImages = 0; + for (int i = 0; i < NumSubpixelPositions; ++i) { QImage img = textureMapForGlyph(glyph, QFixed::fromReal(i / 12.0)); - if (images.isEmpty()) { + if (numImages == 0) { QPainterPath path; QFixedPoint point; m_current_fontengine->addGlyphsToPath(&glyph, &point, 1, &path, QTextItem::RenderFlags()); @@ -60,21 +68,21 @@ int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const if (path.isEmpty()) break; - images.append(img); + images[numImages++] = qMove(img); } else { bool found = false; - for (int j=0; j<images.size(); ++j) { - if (images.at(j) == img) { + for (int j = 0; j < numImages; ++j) { + if (images[j] == img) { found = true; break; } } if (!found) - images.append(img); + images[numImages++] = qMove(img); } } - return images.size(); + return numImages; } bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, @@ -262,6 +270,11 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition * QImageTextureGlyphCache */ +// out-of-line to avoid vtable duplication, breaking e.g. RTTI +QImageTextureGlyphCache::~QImageTextureGlyphCache() +{ +} + void QImageTextureGlyphCache::resizeTextureData(int width, int height) { m_image = m_image.copy(0, 0, width, height); diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index c9e7060b0d..7dd8277a45 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -72,7 +72,7 @@ public: m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0) { } - virtual ~QTextureGlyphCache() { } + ~QTextureGlyphCache(); struct GlyphAndSubPixelPosition { @@ -158,6 +158,8 @@ class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache public: QImageTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) : QTextureGlyphCache(format, matrix) { } + ~QImageTextureGlyphCache(); + virtual void createTextureData(int width, int height) Q_DECL_OVERRIDE; virtual void resizeTextureData(int width, int height) Q_DECL_OVERRIDE; virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE; diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index a3e9db2057..a23aabe559 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -34,6 +34,7 @@ #include "qdatastream.h" #include "qdebug.h" +#include "qhashfunctions.h" #include "qmatrix.h" #include "qregion.h" #include "qpainterpath.h" @@ -776,6 +777,29 @@ bool QTransform::operator==(const QTransform &o) const } /*! + \since 5.6 + \relates QTransform + + Returns the hash value for \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QTransform &key, uint seed) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(key.m11(), seed); + seed = hash(key.m12(), seed); + seed = hash(key.m21(), seed); + seed = hash(key.m22(), seed); + seed = hash(key.dx(), seed); + seed = hash(key.dy(), seed); + seed = hash(key.m13(), seed); + seed = hash(key.m23(), seed); + seed = hash(key.m33(), seed); + return seed; +} + + +/*! \fn bool QTransform::operator!=(const QTransform &matrix) const Returns \c true if this matrix is not equal to the given \a matrix, otherwise returns \c false. @@ -1357,7 +1381,9 @@ static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &pol path = transform.map(path); QPolygonF result; - for (int i = 0; i < path.elementCount(); ++i) + const int elementCount = path.elementCount(); + result.reserve(elementCount); + for (int i = 0; i < elementCount; ++i) result << path.elementAt(i); return result; } diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index cf8d4d1970..65f543144d 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -180,6 +180,8 @@ private: }; Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE); +Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QTransform &key, uint seed = 0) Q_DECL_NOTHROW; + /******* inlines *****/ inline QTransform::TransformationType QTransform::inline_type() const { diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp index 70be92535d..7735fd6b46 100644 --- a/src/gui/text/qabstracttextdocumentlayout.cpp +++ b/src/gui/text/qabstracttextdocumentlayout.cpp @@ -40,6 +40,15 @@ QT_BEGIN_NAMESPACE +QAbstractTextDocumentLayoutPrivate::~QAbstractTextDocumentLayoutPrivate() +{ +} + +QTextObjectInterface::~QTextObjectInterface() +{ + // must be empty until ### Qt 6 +} + /*! \class QAbstractTextDocumentLayout \reentrant diff --git a/src/gui/text/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h index 27135b0476..68e7a0e4e9 100644 --- a/src/gui/text/qabstracttextdocumentlayout.h +++ b/src/gui/text/qabstracttextdocumentlayout.h @@ -126,7 +126,7 @@ private: class Q_GUI_EXPORT QTextObjectInterface { public: - virtual ~QTextObjectInterface() {} + virtual ~QTextObjectInterface(); virtual QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0; virtual void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0; }; diff --git a/src/gui/text/qabstracttextdocumentlayout_p.h b/src/gui/text/qabstracttextdocumentlayout_p.h index 505135fa4b..a7f28ebf96 100644 --- a/src/gui/text/qabstracttextdocumentlayout_p.h +++ b/src/gui/text/qabstracttextdocumentlayout_p.h @@ -58,13 +58,14 @@ struct QTextObjectHandler }; typedef QHash<int, QTextObjectHandler> HandlerHash; -class QAbstractTextDocumentLayoutPrivate : public QObjectPrivate +class Q_GUI_EXPORT QAbstractTextDocumentLayoutPrivate : public QObjectPrivate { public: Q_DECLARE_PUBLIC(QAbstractTextDocumentLayout) inline QAbstractTextDocumentLayoutPrivate() : paintDevice(0) {} + ~QAbstractTextDocumentLayoutPrivate(); inline void setDocument(QTextDocument *doc) { document = doc; diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 3c98cb568d..adbb3df3bf 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -461,6 +461,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m) } QList<QVariant> v; + v.reserve(4); for (i = 0; i < 4; i++) { v += QVariant::fromValue<LengthData>(datas[i]); m[i] = lengthValueFromData(datas[i], f); diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 3c6709e685..796f223797 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -1860,14 +1860,9 @@ void QFont::removeSubstitutions(const QString &familyName) */ QStringList QFont::substitutions() { - typedef QFontSubst::const_iterator QFontSubstConstIterator; - QFontSubst *fontSubst = globalFontSubst(); Q_ASSERT(fontSubst != 0); - QStringList ret; - const QFontSubstConstIterator cend = fontSubst->constEnd(); - for (QFontSubstConstIterator it = fontSubst->constBegin(); it != cend; ++it) - ret.append(it.key()); + QStringList ret = fontSubst->keys(); ret.sort(); return ret; diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 6b7a9837cb..0b0940855d 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -1369,22 +1369,30 @@ QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const QT_PREPEND_NAMESPACE(load)(); - QList<WritingSystem> list; + quint64 writingSystemsFound = 0; + Q_STATIC_ASSERT(WritingSystemsCount < 64); + for (int i = 0; i < d->count; ++i) { QtFontFamily *family = d->families[i]; family->ensurePopulated(); if (family->count == 0) continue; - for (int x = Latin; x < WritingSystemsCount; ++x) { - const WritingSystem writingSystem = WritingSystem(x); - if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported)) - continue; - if (!list.contains(writingSystem)) - list.append(writingSystem); + for (uint x = Latin; x < uint(WritingSystemsCount); ++x) { + if (family->writingSystems[x] & QtFontFamily::Supported) + writingSystemsFound |= quint64(1) << x; } } - std::sort(list.begin(), list.end()); + + // mutex protection no longer needed - just working on local data now: + locker.unlock(); + + QList<WritingSystem> list; + list.reserve(qPopulationCount(writingSystemsFound)); + for (uint x = Latin ; x < uint(WritingSystemsCount); ++x) { + if (writingSystemsFound & (quint64(1) << x)) + list.push_back(WritingSystem(x)); + } return list; } diff --git a/src/gui/text/qfontengineglyphcache.cpp b/src/gui/text/qfontengineglyphcache.cpp new file mode 100644 index 0000000000..f6fdfa3ce3 --- /dev/null +++ b/src/gui/text/qfontengineglyphcache.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qfontengineglyphcache_p.h> + +QT_BEGIN_NAMESPACE + +// out-of-line to avoid vtable duplication, breaking e.g. RTTI +QFontEngineGlyphCache::~QFontEngineGlyphCache() +{ +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h index 6cf4d2f1ba..def42c22a3 100644 --- a/src/gui/text/qfontengineglyphcache_p.h +++ b/src/gui/text/qfontengineglyphcache_p.h @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE -class QFontEngineGlyphCache: public QSharedData +class Q_GUI_EXPORT QFontEngineGlyphCache: public QSharedData { public: QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) : m_format(format), m_transform(matrix) @@ -64,7 +64,7 @@ public: Q_ASSERT(m_format != QFontEngine::Format_None); } - virtual ~QFontEngineGlyphCache() { } + virtual ~QFontEngineGlyphCache(); QFontEngine::GlyphFormat glyphFormat() const { return m_format; } const QTransform &transform() const { return m_transform; } diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp index 9f652084be..dc32405f36 100644 --- a/src/gui/text/qfontsubset.cpp +++ b/src/gui/text/qfontsubset.cpp @@ -350,6 +350,7 @@ struct qttf_head_table { quint16 macStyle; qint16 indexToLocFormat; }; +Q_DECLARE_TYPEINFO(qttf_head_table, Q_PRIMITIVE_TYPE); struct qttf_hhea_table { @@ -362,6 +363,7 @@ struct qttf_hhea_table { qint16 xMaxExtent; quint16 numberOfHMetrics; }; +Q_DECLARE_TYPEINFO(qttf_hhea_table, Q_PRIMITIVE_TYPE); struct qttf_maxp_table { @@ -373,6 +375,7 @@ struct qttf_maxp_table { quint16 maxComponentElements; quint16 maxComponentDepth; }; +Q_DECLARE_TYPEINFO(qttf_maxp_table, Q_PRIMITIVE_TYPE); struct qttf_name_table { QString copyright; @@ -380,6 +383,7 @@ struct qttf_name_table { QString subfamily; QString postscript_name; }; +Q_DECLARE_TYPEINFO(qttf_name_table, Q_MOVABLE_TYPE); static QTtfTable generateHead(const qttf_head_table &head); @@ -411,9 +415,9 @@ Q_DECLARE_TYPEINFO(QTtfGlyph, Q_MOVABLE_TYPE); static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem); // generates glyf, loca and hmtx -static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs); +static QVector<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QVector<QTtfGlyph> &_glyphs); -static QByteArray bindFont(const QList<QTtfTable>& _tables); +static QByteArray bindFont(const QVector<QTtfTable>& _tables); static quint32 checksum(const QByteArray &table) @@ -607,12 +611,13 @@ struct QTtfNameRecord { quint16 nameId; QString value; }; +Q_DECLARE_TYPEINFO(QTtfNameRecord, Q_MOVABLE_TYPE); -static QTtfTable generateName(const QList<QTtfNameRecord> &name); +static QTtfTable generateName(const QVector<QTtfNameRecord> &name); static QTtfTable generateName(const qttf_name_table &name) { - QList<QTtfNameRecord> list; + QVector<QTtfNameRecord> list; QTtfNameRecord rec; rec.nameId = 0; rec.value = name.copyright; @@ -636,7 +641,7 @@ static QTtfTable generateName(const qttf_name_table &name) } // ####### should probably generate Macintosh/Roman name entries as well -static QTtfTable generateName(const QList<QTtfNameRecord> &name) +static QTtfTable generateName(const QVector<QTtfNameRecord> &name) { const int char_size = 2; @@ -707,7 +712,7 @@ struct TTF_POINT { }; Q_DECLARE_TYPEINFO(TTF_POINT, Q_PRIMITIVE_TYPE); -static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QList<int> *endPoints, qreal ppem) +static void convertPath(const QPainterPath &path, QVector<TTF_POINT> *points, QVector<int> *endPoints, qreal ppem) { int numElements = path.elementCount(); for (int i = 0; i < numElements - 1; ++i) { @@ -829,7 +834,7 @@ static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QLis endPoints->append(points->size() - 1); } -static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax) +static void getBounds(const QVector<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax) { *xmin = points.at(0).x; *xmax = *xmin; @@ -844,7 +849,7 @@ static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax } } -static int convertToRelative(QList<TTF_POINT> *points) +static int convertToRelative(QVector<TTF_POINT> *points) { // convert points to relative and setup flags // qDebug() << "relative points:"; @@ -897,7 +902,7 @@ static int convertToRelative(QList<TTF_POINT> *points) return point_array_size; } -static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const QList<int> &endPoints, int point_array_size) +static void getGlyphData(QTtfGlyph *glyph, const QVector<TTF_POINT> &points, const QVector<int> &endPoints, int point_array_size) { const int max_size = 5*sizeof(qint16) // header + endPoints.size()*sizeof(quint16) // end points of contours @@ -947,8 +952,8 @@ static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem) { - QList<TTF_POINT> points; - QList<int> endPoints; + QVector<TTF_POINT> points; + QVector<int> endPoints; QTtfGlyph glyph; glyph.index = index; glyph.advanceWidth = qRound(advance * 2048. / ppem); @@ -983,10 +988,10 @@ static bool operator <(const QTtfGlyph &g1, const QTtfGlyph &g2) return g1.index < g2.index; } -static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs) +static QVector<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QVector<QTtfGlyph> &_glyphs) { const int max_size_small = 65536*2; - QList<QTtfGlyph> glyphs = _glyphs; + QVector<QTtfGlyph> glyphs = _glyphs; std::sort(glyphs.begin(), glyphs.end()); Q_ASSERT(tables.maxp.numGlyphs == glyphs.at(glyphs.size()-1).index + 1); @@ -1049,7 +1054,7 @@ static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QLis Q_ASSERT(loca.data.size() == ls.offset()); Q_ASSERT(hmtx.data.size() == hs.offset()); - QList<QTtfTable> list; + QVector<QTtfTable> list; list.append(glyf); list.append(loca); list.append(hmtx); @@ -1061,9 +1066,9 @@ static bool operator <(const QTtfTable &t1, const QTtfTable &t2) return t1.tag < t2.tag; } -static QByteArray bindFont(const QList<QTtfTable>& _tables) +static QByteArray bindFont(const QVector<QTtfTable>& _tables) { - QList<QTtfTable> tables = _tables; + QVector<QTtfTable> tables = _tables; std::sort(tables.begin(), tables.end()); @@ -1154,7 +1159,7 @@ QByteArray QFontSubset::toTruetype() const qreal ppem = fontEngine->fontDef.pixelSize; #define TO_TTF(x) qRound(x * 2048. / ppem) - QList<QTtfGlyph> glyphs; + QVector<QTtfGlyph> glyphs; QFontEngine::Properties properties = fontEngine->properties(); // initialize some stuff needed in createWidthArray @@ -1225,7 +1230,7 @@ QByteArray QFontSubset::toTruetype() const } - QList<QTtfTable> tables = generateGlyphTables(font, glyphs); + QVector<QTtfTable> tables = generateGlyphTables(font, glyphs); tables.append(generateHead(font.head)); tables.append(generateHhea(font.hhea)); tables.append(generateMaxp(font.maxp)); diff --git a/src/gui/text/qfontsubset_p.h b/src/gui/text/qfontsubset_p.h index da8589de3f..4abdb48c0d 100644 --- a/src/gui/text/qfontsubset_p.h +++ b/src/gui/text/qfontsubset_p.h @@ -79,7 +79,7 @@ public: const int object_id; bool noEmbed; QFontEngine *fontEngine; - QList<int> glyph_indices; + QVector<int> glyph_indices; mutable int downloaded_glyphs; mutable bool standard_font; int nGlyphs() const { return glyph_indices.size(); } diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp index e6d6863134..642313d340 100644 --- a/src/gui/text/qglyphrun.cpp +++ b/src/gui/text/qglyphrun.cpp @@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE \ingroup text \ingroup shared - \mainclass When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h index d3034b7546..9f51a49a6d 100644 --- a/src/gui/text/qglyphrun.h +++ b/src/gui/text/qglyphrun.h @@ -59,9 +59,13 @@ public: QGlyphRun(); QGlyphRun(const QGlyphRun &other); +#ifdef Q_COMPILER_RVALUE_REFS + QGlyphRun &operator=(QGlyphRun &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif + QGlyphRun &operator=(const QGlyphRun &other); ~QGlyphRun(); - void swap(QGlyphRun &other) { qSwap(d, other.d); } + void swap(QGlyphRun &other) Q_DECL_NOTHROW { qSwap(d, other.d); } QRawFont rawFont() const; void setRawFont(const QRawFont &rawFont); @@ -78,8 +82,6 @@ public: void clear(); - QGlyphRun &operator=(const QGlyphRun &other); - bool operator==(const QGlyphRun &other) const; inline bool operator!=(const QGlyphRun &other) const { return !operator==(other); } diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index 0615df65d6..3331d96f8b 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -47,7 +47,9 @@ #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QList> +#if QT_DEPRECATED_SINCE(5, 5) #include <QtCore/QHash> +#endif #include <QtGui/QFontDatabase> #include <QtGui/private/qfontengine_p.h> #include <QtGui/private/qfont_p.h> diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index fedf58872b..0fd5f510c7 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE \ingroup text \ingroup shared - \mainclass \note QRawFont is a low level class. For most purposes QFont is a more appropriate class. diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index 3798555de5..d710658a9b 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -72,13 +72,15 @@ public: qreal pixelSize, QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting); QRawFont(const QRawFont &other); +#ifdef Q_COMPILER_RVALUE_REFS + QRawFont &operator=(QRawFont &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif + QRawFont &operator=(const QRawFont &other); ~QRawFont(); - bool isValid() const; + void swap(QRawFont &other) Q_DECL_NOTHROW { qSwap(d, other.d); } - QRawFont &operator=(const QRawFont &other); - - void swap(QRawFont &other) { qSwap(d, other.d); } + bool isValid() const; bool operator==(const QRawFont &other) const; inline bool operator!=(const QRawFont &other) const diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index fc95a859e7..5d31ab9711 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -39,6 +39,10 @@ QT_BEGIN_NAMESPACE +QStaticTextUserData::~QStaticTextUserData() +{ +} + /*! \class QStaticText \brief The QStaticText class enables optimized drawing of text when the text and its layout @@ -49,7 +53,6 @@ QT_BEGIN_NAMESPACE \ingroup multimedia \ingroup text \ingroup shared - \mainclass QStaticText provides a way to cache layout data for a block of text so that it can be drawn more efficiently than by using QPainter::drawText() in which the layout information is diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h index d2825e73ac..0a1d9429b4 100644 --- a/src/gui/text/qstatictext.h +++ b/src/gui/text/qstatictext.h @@ -57,9 +57,13 @@ public: QStaticText(); QStaticText(const QString &text); QStaticText(const QStaticText &other); +#ifdef Q_COMPILER_RVALUE_REFS + QStaticText &operator=(QStaticText &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif + QStaticText &operator=(const QStaticText &); ~QStaticText(); - void swap(QStaticText &other) { qSwap(data, other.data); } + void swap(QStaticText &other) Q_DECL_NOTHROW { qSwap(data, other.data); } void setText(const QString &text); QString text() const; @@ -80,7 +84,6 @@ public: void setPerformanceHint(PerformanceHint performanceHint); PerformanceHint performanceHint() const; - QStaticText &operator=(const QStaticText &); bool operator==(const QStaticText &) const; bool operator!=(const QStaticText &) const; diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h index 088e49e2fc..49ca24d51c 100644 --- a/src/gui/text/qstatictext_p.h +++ b/src/gui/text/qstatictext_p.h @@ -52,7 +52,8 @@ QT_BEGIN_NAMESPACE -class QStaticTextUserData +// ### Qt 6: Unexport again, if QOpenGLStaticTextUserData (the one from QtOpenGL) is gone by then +class Q_GUI_EXPORT QStaticTextUserData { public: enum Type { @@ -61,7 +62,7 @@ public: }; QStaticTextUserData(Type t) : ref(0), type(t) {} - virtual ~QStaticTextUserData() {} + virtual ~QStaticTextUserData(); QAtomicInt ref; Type type; diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp index 162c646a98..f180a839b7 100644 --- a/src/gui/text/qsyntaxhighlighter.cpp +++ b/src/gui/text/qsyntaxhighlighter.cpp @@ -90,13 +90,13 @@ void QSyntaxHighlighterPrivate::applyFormatChanges() QTextLayout *layout = currentBlock.layout(); - QList<QTextLayout::FormatRange> ranges = layout->additionalFormats(); + QVector<QTextLayout::FormatRange> ranges = layout->formats(); const int preeditAreaStart = layout->preeditAreaPosition(); const int preeditAreaLength = layout->preeditAreaText().length(); if (preeditAreaLength != 0) { - QList<QTextLayout::FormatRange>::Iterator it = ranges.begin(); + QVector<QTextLayout::FormatRange>::Iterator it = ranges.begin(); while (it != ranges.end()) { if (it->start >= preeditAreaStart && it->start + it->length <= preeditAreaStart + preeditAreaLength) { @@ -142,7 +142,7 @@ void QSyntaxHighlighterPrivate::applyFormatChanges() } if (formatsChanged) { - layout->setAdditionalFormats(ranges); + layout->setFormats(ranges); doc->markContentsDirty(currentBlock.position(), currentBlock.length()); } } @@ -329,7 +329,7 @@ void QSyntaxHighlighter::setDocument(QTextDocument *doc) QTextCursor cursor(d->doc); cursor.beginEditBlock(); for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next()) - blk.layout()->clearAdditionalFormats(); + blk.layout()->clearFormats(); cursor.endEditBlock(); } d->doc = doc; diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h index f04055603c..350f38cd02 100644 --- a/src/gui/text/qtextcursor.h +++ b/src/gui/text/qtextcursor.h @@ -66,10 +66,13 @@ public: explicit QTextCursor(const QTextBlock &block); explicit QTextCursor(QTextCursorPrivate *d); QTextCursor(const QTextCursor &cursor); +#ifdef Q_COMPILER_RVALUE_REFS + QTextCursor &operator=(QTextCursor &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QTextCursor &operator=(const QTextCursor &other); ~QTextCursor(); - void swap(QTextCursor &other) { qSwap(d, other.d); } + void swap(QTextCursor &other) Q_DECL_NOTHROW { qSwap(d, other.d); } bool isNull() const; diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index d3b70aaf26..3d248f4afc 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1949,7 +1949,7 @@ void QTextDocument::print(QPagedPaintDevice *printer) const for (QTextBlock srcBlock = firstBlock(), dstBlock = clonedDoc->firstBlock(); srcBlock.isValid() && dstBlock.isValid(); srcBlock = srcBlock.next(), dstBlock = dstBlock.next()) { - dstBlock.layout()->setAdditionalFormats(srcBlock.layout()->additionalFormats()); + dstBlock.layout()->setFormats(srcBlock.layout()->formats()); } QAbstractTextDocumentLayout *layout = doc->documentLayout(); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index 5864ca0b1a..7d75e649b0 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -106,7 +106,7 @@ public: bool sizeDirty; bool layoutDirty; - QList<QPointer<QTextFrame> > floats; + QVector<QPointer<QTextFrame> > floats; }; QTextFrameData::QTextFrameData() @@ -1071,7 +1071,9 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain it = frameIteratorForYPosition(QFixed::fromReal(context.clip.top())); QList<QTextFrame *> floats; - for (int i = 0; i < fd->floats.count(); ++i) + const int numFloats = fd->floats.count(); + floats.reserve(numFloats); + for (int i = 0; i < numFloats; ++i) floats.append(fd->floats.at(i)); drawFlow(off, painter, context, it, floats, &cursorBlockNeedingRepaint); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 67a19804a3..e87711ef99 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2571,7 +2571,7 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText) clearLineData(); } -void QTextEngine::setFormats(const QList<QTextLayout::FormatRange> &formats) +void QTextEngine::setFormats(const QVector<QTextLayout::FormatRange> &formats) { if (formats.isEmpty()) { if (!specialData) @@ -2863,6 +2863,7 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const if (!tabArray.isEmpty()) { if (isRightToLeft()) { // rebase the tabArray positions. QList<QTextOption::Tab> newTabs; + newTabs.reserve(tabArray.count()); QList<QTextOption::Tab>::Iterator iter = tabArray.begin(); while(iter != tabArray.end()) { QTextOption::Tab tab = *iter; @@ -2946,17 +2947,17 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const namespace { class FormatRangeComparatorByStart { - const QList<QTextLayout::FormatRange> &list; + const QVector<QTextLayout::FormatRange> &list; public: - FormatRangeComparatorByStart(const QList<QTextLayout::FormatRange> &list) : list(list) { } + FormatRangeComparatorByStart(const QVector<QTextLayout::FormatRange> &list) : list(list) { } bool operator()(int a, int b) { return list.at(a).start < list.at(b).start; } }; class FormatRangeComparatorByEnd { - const QList<QTextLayout::FormatRange> &list; + const QVector<QTextLayout::FormatRange> &list; public: - FormatRangeComparatorByEnd(const QList<QTextLayout::FormatRange> &list) : list(list) { } + FormatRangeComparatorByEnd(const QVector<QTextLayout::FormatRange> &list) : list(list) { } bool operator()(int a, int b) { return list.at(a).start + list.at(a).length < list.at(b).start + list.at(b).length; } diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 39b9e0cb5a..3590c6da07 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -570,9 +570,9 @@ public: inline bool hasFormats() const { return block.docHandle() || (specialData && !specialData->formats.isEmpty()); } - inline QList<QTextLayout::FormatRange> formats() const - { return specialData ? specialData->formats : QList<QTextLayout::FormatRange>(); } - void setFormats(const QList<QTextLayout::FormatRange> &formats); + inline QVector<QTextLayout::FormatRange> formats() const + { return specialData ? specialData->formats : QVector<QTextLayout::FormatRange>(); } + void setFormats(const QVector<QTextLayout::FormatRange> &formats); private: static void init(QTextEngine *e); @@ -580,7 +580,7 @@ private: struct SpecialData { int preeditPosition; QString preeditText; - QList<QTextLayout::FormatRange> formats; + QVector<QTextLayout::FormatRange> formats; QVector<QTextCharFormat> resolvedFormats; // only used when no docHandle is available QScopedPointer<QTextFormatCollection> formatCollection; diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index ba4bdcc5ad..7dcd060ba1 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -38,7 +38,7 @@ #include <qdatastream.h> #include <qdebug.h> #include <qmap.h> -#include <qhash.h> +#include <qhashfunctions.h> QT_BEGIN_NAMESPACE @@ -1115,7 +1115,9 @@ void QTextFormat::setProperty(int propertyId, const QVector<QTextLength> &value) if (!d) d = new QTextFormatPrivate; QVariantList list; - for (int i=0; i<value.size(); ++i) + const int numValues = value.size(); + list.reserve(numValues); + for (int i = 0; i < numValues; ++i) list << value.at(i); d->insertProperty(propertyId, list); } @@ -2041,6 +2043,7 @@ QTextBlockFormat::QTextBlockFormat(const QTextFormat &fmt) void QTextBlockFormat::setTabPositions(const QList<QTextOption::Tab> &tabs) { QList<QVariant> list; + list.reserve(tabs.count()); QList<QTextOption::Tab>::ConstIterator iter = tabs.constBegin(); while (iter != tabs.constEnd()) { QVariant v; @@ -2065,6 +2068,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const QList<QTextOption::Tab> answer; QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant); QList<QVariant>::Iterator iter = variantsList.begin(); + answer.reserve(variantsList.count()); while(iter != variantsList.end()) { answer.append( qvariant_cast<QTextOption::Tab>(*iter)); ++iter; diff --git a/src/gui/text/qtextformat_p.h b/src/gui/text/qtextformat_p.h index 29656bbafe..928cef6488 100644 --- a/src/gui/text/qtextformat_p.h +++ b/src/gui/text/qtextformat_p.h @@ -47,7 +47,6 @@ #include "QtGui/qtextformat.h" #include "QtCore/qvector.h" -#include "QtCore/qhash.h" QT_BEGIN_NAMESPACE diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 7da3e84041..c42054c07c 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE for a specified area in the text layout's content. \inmodule QtGui - \sa QTextLayout::setAdditionalFormats(), QTextLayout::draw() + \sa QTextLayout::setFormats(), QTextLayout::draw() */ /*! @@ -485,7 +485,6 @@ QString QTextLayout::preeditAreaText() const return d->preeditAreaText(); } - /*! Sets the additional formats supported by the text layout to \a formatList. The formats are applied with preedit area text in place. @@ -494,7 +493,20 @@ QString QTextLayout::preeditAreaText() const */ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) { - d->setFormats(formatList); + setFormats(formatList.toVector()); +} + +/*! + \since 5.6 + + Sets the additional formats supported by the text layout to \a formats. + The formats are applied with preedit area text in place. + + \sa formats(), clearFormats() +*/ +void QTextLayout::setFormats(const QVector<FormatRange> &formats) +{ + d->setFormats(formats); if (d->block.docHandle()) d->block.docHandle()->documentChange(d->block.position(), d->block.length()); @@ -507,6 +519,18 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) */ QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const { + return formats().toList(); +} + +/*! + \since 5.6 + + Returns the list of additional formats supported by the text layout. + + \sa setFormats(), clearFormats() +*/ +QVector<QTextLayout::FormatRange> QTextLayout::formats() const +{ return d->formats(); } @@ -517,7 +541,19 @@ QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const */ void QTextLayout::clearAdditionalFormats() { - setAdditionalFormats(QList<FormatRange>()); + clearFormats(); +} + +/*! + \since 5.6 + + Clears the list of additional formats supported by the text layout. + + \sa formats(), setFormats() +*/ +void QTextLayout::clearFormats() +{ + setFormats(QVector<FormatRange>()); } /*! diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index 47dcd388e2..9709af4fd1 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -125,10 +125,18 @@ public: int start; int length; QTextCharFormat format; + + friend bool operator==(const FormatRange &lhs, const FormatRange &rhs) + { return lhs.start == rhs.start && lhs.length == rhs.length && lhs.format == rhs.format; } + friend bool operator!=(const FormatRange &lhs, const FormatRange &rhs) + { return !operator==(lhs, rhs); } }; void setAdditionalFormats(const QList<FormatRange> &overrides); QList<FormatRange> additionalFormats() const; void clearAdditionalFormats(); + void setFormats(const QVector<FormatRange> &overrides); + QVector<FormatRange> formats() const; + void clearFormats(); void setCacheEnabled(bool enable); bool cacheEnabled() const; diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp index dbafcfd58e..5a4f6b7954 100644 --- a/src/gui/text/qtextoption.cpp +++ b/src/gui/text/qtextoption.cpp @@ -146,6 +146,7 @@ void QTextOption::setTabArray(const QList<qreal> &tabStops) d = new QTextOptionPrivate; QList<QTextOption::Tab> tabs; QTextOption::Tab tab; + tabs.reserve(tabStops.count()); foreach (qreal pos, tabStops) { tab.position = pos; tabs.append(tab); @@ -174,10 +175,11 @@ void QTextOption::setTabs(const QList<QTextOption::Tab> &tabStops) */ QList<qreal> QTextOption::tabArray() const { + QList<qreal> answer; if (!d) - return QList<qreal>(); + return answer; - QList<qreal> answer; + answer.reserve(d->tabStops.count()); QList<QTextOption::Tab>::ConstIterator iter = d->tabStops.constBegin(); while(iter != d->tabStops.constEnd()) { answer.append( (*iter).position); diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp index 1d621db0e6..40088d573a 100644 --- a/src/gui/text/qzip.cpp +++ b/src/gui/text/qzip.cpp @@ -303,6 +303,7 @@ enum HostOS { HostOS400 = 18, HostOSX = 19 }; +Q_DECLARE_TYPEINFO(HostOS, Q_PRIMITIVE_TYPE); enum GeneralPurposeFlag { Encrypted = 0x01, @@ -314,6 +315,7 @@ enum GeneralPurposeFlag { Utf8Names = 0x0800, CentralDirectoryEncrypted = 0x2000 }; +Q_DECLARE_TYPEINFO(GeneralPurposeFlag, Q_PRIMITIVE_TYPE); enum CompressionMethod { CompressionMethodStored = 0, @@ -340,6 +342,7 @@ enum CompressionMethod { CompressionMethodPPMd = 98, CompressionMethodWzAES = 99 }; +Q_DECLARE_TYPEINFO(CompressionMethod, Q_PRIMITIVE_TYPE); struct LocalFileHeader { @@ -354,6 +357,7 @@ struct LocalFileHeader uchar file_name_length[2]; uchar extra_field_length[2]; }; +Q_DECLARE_TYPEINFO(LocalFileHeader, Q_PRIMITIVE_TYPE); struct DataDescriptor { @@ -361,6 +365,7 @@ struct DataDescriptor uchar compressed_size[4]; uchar uncompressed_size[4]; }; +Q_DECLARE_TYPEINFO(DataDescriptor, Q_PRIMITIVE_TYPE); struct CentralFileHeader { @@ -382,6 +387,7 @@ struct CentralFileHeader uchar offset_local_header[4]; LocalFileHeader toLocalHeader() const; }; +Q_DECLARE_TYPEINFO(CentralFileHeader, Q_PRIMITIVE_TYPE); struct EndOfDirectory { @@ -394,6 +400,7 @@ struct EndOfDirectory uchar dir_start_offset[4]; uchar comment_length[2]; }; +Q_DECLARE_TYPEINFO(EndOfDirectory, Q_PRIMITIVE_TYPE); struct FileHeader { @@ -402,6 +409,7 @@ struct FileHeader QByteArray extra_field; QByteArray file_comment; }; +Q_DECLARE_TYPEINFO(FileHeader, Q_MOVABLE_TYPE); QZipReader::FileInfo::FileInfo() : isDir(false), isFile(false), isSymLink(false), crc(0), size(0) @@ -917,7 +925,9 @@ QList<QZipReader::FileInfo> QZipReader::fileInfoList() const { d->scanFiles(); QList<QZipReader::FileInfo> files; - for (int i = 0; i < d->fileHeaders.size(); ++i) { + const int numFileHeaders = d->fileHeaders.size(); + files.reserve(numFileHeaders); + for (int i = 0; i < numFileHeaders; ++i) { QZipReader::FileInfo fi; d->fillFileInfo(i, fi); files.append(fi); diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h index df7e2d26e9..7a18dc7340 100644 --- a/src/gui/text/qzipreader_p.h +++ b/src/gui/text/qzipreader_p.h @@ -111,6 +111,8 @@ private: QZipReaderPrivate *d; Q_DISABLE_COPY(QZipReader) }; +Q_DECLARE_TYPEINFO(QZipReader::FileInfo, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QZipReader::Status, Q_PRIMITIVE_TYPE); QT_END_NAMESPACE diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index 61e239f678..be60ba72cc 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -21,6 +21,7 @@ HEADERS += \ text/qtextdocument_p.h \ text/qtexthtmlparser_p.h \ text/qabstracttextdocumentlayout.h \ + text/qabstracttextdocumentlayout_p.h \ text/qtextdocumentlayout_p.h \ text/qtextcursor.h \ text/qtextcursor_p.h \ @@ -47,6 +48,7 @@ HEADERS += \ SOURCES += \ text/qfont.cpp \ text/qfontengine.cpp \ + text/qfontengineglyphcache.cpp \ text/qfontsubset.cpp \ text/qfontmetrics.cpp \ text/qfontdatabase.cpp \ |