summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/qaccessible.cpp126
-rw-r--r--src/gui/accessible/qaccessible.h38
-rw-r--r--src/gui/image/qicon.cpp4
-rw-r--r--src/gui/image/qiconloader.cpp1
-rw-r--r--src/gui/image/qimage.cpp117
-rw-r--r--src/gui/image/qimage.h13
-rw-r--r--src/gui/image/qimagereader.cpp33
-rw-r--r--src/gui/image/qimagereader.h3
-rw-r--r--src/gui/image/qpaintengine_pic.cpp1
-rw-r--r--src/gui/image/qpicture.cpp4
-rw-r--r--src/gui/image/qpicture_p.h5
-rw-r--r--src/gui/image/qpixmapcache.cpp38
-rw-r--r--src/gui/image/qpixmapcache.h11
-rw-r--r--src/gui/image/qpnghandler.cpp22
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.cpp82
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.h16
-rw-r--r--src/gui/kernel/qdnd.cpp8
-rw-r--r--src/gui/kernel/qevent.cpp35
-rw-r--r--src/gui/kernel/qevent.h5
-rw-r--r--src/gui/kernel/qguiapplication.cpp21
-rw-r--r--src/gui/kernel/qkeymapper_p.h1
-rw-r--r--src/gui/kernel/qkeysequence.cpp29
-rw-r--r--src/gui/kernel/qkeysequence.h12
-rw-r--r--src/gui/kernel/qopenglcontext.cpp10
-rw-r--r--src/gui/kernel/qopenglcontext.h3
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp1
-rw-r--r--src/gui/kernel/qplatformintegrationfactory.cpp7
-rw-r--r--src/gui/kernel/qplatformthemefactory.cpp4
-rw-r--r--src/gui/kernel/qscreen.cpp39
-rw-r--r--src/gui/kernel/qscreen.h7
-rw-r--r--src/gui/kernel/qtouchdevice.cpp14
-rw-r--r--src/gui/kernel/qtouchdevice_p.h5
-rw-r--r--src/gui/kernel/qwindow.cpp39
-rw-r--r--src/gui/kernel/qwindow.h7
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp118
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h2
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h15
-rw-r--r--src/gui/opengl/qopengl.cpp120
-rw-r--r--src/gui/opengl/qopengl_p.h10
-rw-r--r--src/gui/opengl/qopengldebug.h8
-rw-r--r--src/gui/opengl/qopenglextensions_p.h6
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp16
-rw-r--r--src/gui/opengl/qopenglgradientcache.cpp78
-rw-r--r--src/gui/opengl/qopenglgradientcache_p.h4
-rw-r--r--src/gui/opengl/qopenglpaintdevice.cpp4
-rw-r--r--src/gui/opengl/qopenglpaintdevice_p.h2
-rw-r--r--src/gui/opengl/qopenglpixeltransferoptions.h9
-rw-r--r--src/gui/opengl/qopenglversionfunctions.h3
-rw-r--r--src/gui/painting/painting.pri3
-rw-r--r--src/gui/painting/qbrush.cpp1
-rw-r--r--src/gui/painting/qcolor.cpp88
-rw-r--r--src/gui/painting/qcolor.h8
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp2197
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp3
-rw-r--r--src/gui/painting/qdrawhelper.cpp3546
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp7
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h2
-rw-r--r--src/gui/painting/qdrawhelper_p.h214
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp103
-rw-r--r--src/gui/painting/qdrawhelper_x86_p.h6
-rw-r--r--src/gui/painting/qimagescale.cpp152
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp42
-rw-r--r--src/gui/painting/qmatrix.cpp24
-rw-r--r--src/gui/painting/qmatrix.h2
-rw-r--r--src/gui/painting/qpagedpaintdevice.cpp4
-rw-r--r--src/gui/painting/qpagedpaintdevice_p.h4
-rw-r--r--src/gui/painting/qpagelayout.h11
-rw-r--r--src/gui/painting/qpagesize.h10
-rw-r--r--src/gui/painting/qpaintengine.cpp4
-rw-r--r--src/gui/painting/qpaintengine_p.h3
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp108
-rw-r--r--src/gui/painting/qpainter.cpp5
-rw-r--r--src/gui/painting/qpainter_p.h1
-rw-r--r--src/gui/painting/qpathclipper.cpp6
-rw-r--r--src/gui/painting/qpdf.cpp4
-rw-r--r--src/gui/painting/qpdf_p.h2
-rw-r--r--src/gui/painting/qpen.cpp1
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp4
-rw-r--r--src/gui/painting/qpolygon.h10
-rw-r--r--src/gui/painting/qrgba64.h208
-rw-r--r--src/gui/painting/qrgba64.qdoc241
-rw-r--r--src/gui/painting/qrgba64_p.h120
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp29
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h4
-rw-r--r--src/gui/painting/qtransform.cpp28
-rw-r--r--src/gui/painting/qtransform.h2
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.cpp9
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.h2
-rw-r--r--src/gui/text/qabstracttextdocumentlayout_p.h3
-rw-r--r--src/gui/text/qcssparser.cpp1
-rw-r--r--src/gui/text/qfont.cpp7
-rw-r--r--src/gui/text/qfontdatabase.cpp24
-rw-r--r--src/gui/text/qfontengineglyphcache.cpp43
-rw-r--r--src/gui/text/qfontengineglyphcache_p.h4
-rw-r--r--src/gui/text/qfontsubset.cpp41
-rw-r--r--src/gui/text/qfontsubset_p.h2
-rw-r--r--src/gui/text/qglyphrun.cpp1
-rw-r--r--src/gui/text/qglyphrun.h8
-rw-r--r--src/gui/text/qplatformfontdatabase.h2
-rw-r--r--src/gui/text/qrawfont.cpp1
-rw-r--r--src/gui/text/qrawfont.h10
-rw-r--r--src/gui/text/qstatictext.cpp5
-rw-r--r--src/gui/text/qstatictext.h7
-rw-r--r--src/gui/text/qstatictext_p.h5
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp8
-rw-r--r--src/gui/text/qtextcursor.h5
-rw-r--r--src/gui/text/qtextdocument.cpp2
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp6
-rw-r--r--src/gui/text/qtextengine.cpp11
-rw-r--r--src/gui/text/qtextengine_p.h8
-rw-r--r--src/gui/text/qtextformat.cpp8
-rw-r--r--src/gui/text/qtextformat_p.h1
-rw-r--r--src/gui/text/qtextlayout.cpp44
-rw-r--r--src/gui/text/qtextlayout.h8
-rw-r--r--src/gui/text/qtextoption.cpp6
-rw-r--r--src/gui/text/qzip.cpp12
-rw-r--r--src/gui/text/qzipreader_p.h2
-rw-r--r--src/gui/text/text.pri2
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 &region, 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 \