summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/qaccessible.cpp16
-rw-r--r--src/gui/image/qbmphandler.cpp13
-rw-r--r--src/gui/image/qgifhandler.cpp2
-rw-r--r--src/gui/image/qimage.cpp4
-rw-r--r--src/gui/image/qimage_conversions.cpp8
-rw-r--r--src/gui/image/qjpeghandler.cpp21
-rw-r--r--src/gui/kernel/qcursor.cpp3
-rw-r--r--src/gui/kernel/qevent.cpp124
-rw-r--r--src/gui/kernel/qguiapplication.cpp26
-rw-r--r--src/gui/kernel/qguiapplication_p.h2
-rw-r--r--src/gui/kernel/qkeysequence.cpp3
-rw-r--r--src/gui/kernel/qopenglcontext.cpp49
-rw-r--r--src/gui/kernel/qopenglcontext.h2
-rw-r--r--src/gui/kernel/qopenglcontext_p.h3
-rw-r--r--src/gui/kernel/qpalette.cpp3
-rw-r--r--src/gui/kernel/qplatformintegration.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.h3
-rw-r--r--src/gui/kernel/qshortcutmap.cpp6
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp3
-rw-r--r--src/gui/kernel/qwindow.cpp9
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp6
-rw-r--r--src/gui/math3d/qgenericmatrix.h3
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp3
-rw-r--r--src/gui/math3d/qquaternion.cpp33
-rw-r--r--src/gui/math3d/qquaternion.h2
-rw-r--r--src/gui/math3d/qvector2d.cpp3
-rw-r--r--src/gui/math3d/qvector3d.cpp3
-rw-r--r--src/gui/math3d/qvector4d.cpp3
-rw-r--r--src/gui/opengl/qopengldebug.cpp20
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp6
-rw-r--r--src/gui/opengl/qopenglgradientcache.cpp43
-rw-r--r--src/gui/opengl/qopenglgradientcache_p.h3
-rw-r--r--src/gui/opengl/qopengltexture.cpp2
-rw-r--r--src/gui/opengl/qopenglversionfunctions.cpp26
-rw-r--r--src/gui/opengl/qopenglversionfunctions.h13
-rw-r--r--src/gui/opengl/qopenglvertexarrayobject.cpp13
-rw-r--r--src/gui/painting/painting.pri1
-rw-r--r--src/gui/painting/qbrush.cpp3
-rw-r--r--src/gui/painting/qcolor.cpp3
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp23
-rw-r--r--src/gui/painting/qdrawhelper.cpp909
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp5
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h2
-rw-r--r--src/gui/painting/qdrawhelper_p.h106
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp17
-rw-r--r--src/gui/painting/qdrawhelper_x86_p.h6
-rw-r--r--src/gui/painting/qmatrix.cpp3
-rw-r--r--src/gui/painting/qpagelayout.cpp3
-rw-r--r--src/gui/painting/qpagesize.cpp3
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp101
-rw-r--r--src/gui/painting/qpainter.cpp2
-rw-r--r--src/gui/painting/qpen.cpp3
-rw-r--r--src/gui/painting/qpolygon.cpp6
-rw-r--r--src/gui/painting/qrgba64.h9
-rw-r--r--src/gui/painting/qrgba64_p.h83
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp11
-rw-r--r--src/gui/painting/qtransform.cpp3
-rw-r--r--src/gui/text/qcssparser.cpp24
-rw-r--r--src/gui/text/qcssparser_p.h5
-rw-r--r--src/gui/text/qfontengine_ft.cpp253
-rw-r--r--src/gui/text/qfontengine_ft_p.h1
-rw-r--r--src/gui/text/qharfbuzzng.cpp41
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp14
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp2
-rw-r--r--src/gui/text/qtextengine.cpp50
-rw-r--r--src/gui/text/qtextformat.cpp6
-rw-r--r--src/gui/text/qtexthtmlparser.cpp270
-rw-r--r--src/gui/util/qdesktopservices.cpp12
-rw-r--r--src/gui/util/qlayoutpolicy.cpp3
69 files changed, 1803 insertions, 664 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index fb30b5f8ee..cc9d789c6a 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -1713,6 +1713,7 @@ bool operator==(const QAccessible::State &first, const QAccessible::State &secon
/*! \internal */
Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
{
+ QDebugStateSaver saver(d);
if (!iface) {
d << "QAccessibleInterface(null)";
return d;
@@ -1720,10 +1721,10 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
d.nospace();
d << "QAccessibleInterface(" << hex << (const void *) iface << dec;
if (iface->isValid()) {
- d << " name=" << iface->text(QAccessible::Name) << " ";
- d << "role=" << qAccessibleRoleString(iface->role()) << " ";
+ d << " name=" << iface->text(QAccessible::Name) << ' ';
+ d << "role=" << qAccessibleRoleString(iface->role()) << ' ';
if (iface->childCount())
- d << "childc=" << iface->childCount() << " ";
+ d << "childc=" << iface->childCount() << ' ';
if (iface->object()) {
d << "obj=" << iface->object();
}
@@ -1747,13 +1748,14 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
} else {
d << " invalid";
}
- d << ")";
- return d.space();
+ d << ')';
+ return d;
}
/*! \internal */
QDebug operator<<(QDebug d, const QAccessibleEvent &ev)
{
+ QDebugStateSaver saver(d);
d.nospace() << "QAccessibleEvent(";
if (ev.object()) {
d.nospace() << "object=" << hex << ev.object() << dec;
@@ -1806,8 +1808,8 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev)
if (changed.supportsAutoCompletion) d << "supportsAutoCompletion";
}
- d.nospace() << ")";
- return d.space();
+ d << ')';
+ return d;
}
#endif // QT_NO_DEBUGSTREAM
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index 7a491d8736..f124cede36 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -484,12 +484,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
p = data + (h-y-1)*bpl;
break;
case 2: // delta (jump)
- // Protection
- if ((uint)x >= (uint)w)
- x = w-1;
- if ((uint)y >= (uint)h)
- y = h-1;
-
{
quint8 tmp;
d->getChar((char *)&tmp);
@@ -497,6 +491,13 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
d->getChar((char *)&tmp);
y += tmp;
}
+
+ // Protection
+ if ((uint)x >= (uint)w)
+ x = w-1;
+ if ((uint)y >= (uint)h)
+ y = h-1;
+
p = data + (h-y-1)*bpl + x;
break;
default: // absolute mode
diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp
index 0a451e5ea3..7ba6b123e8 100644
--- a/src/gui/image/qgifhandler.cpp
+++ b/src/gui/image/qgifhandler.cpp
@@ -936,6 +936,8 @@ void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb co
void QGIFFormat::nextY(unsigned char *bits, int bpl)
{
+ if (out_of_bounds)
+ return;
int my;
switch (interlace) {
case 0: // Non-interlaced
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 57c290492c..00eb80ba1a 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1766,11 +1766,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()));
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 417c185c78..28e3a48689 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -681,6 +681,8 @@ static bool convert_BGR30_to_RGB30_inplace(QImageData *data, Qt::ImageConversion
static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
+ if (!data->own_data)
+ return false;
const int depth = 32;
const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
@@ -733,6 +735,8 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve
static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
+ if (!data->own_data)
+ return false;
const int depth = 32;
const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
@@ -782,6 +786,8 @@ static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversio
static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
+ if (!data->own_data)
+ return false;
const int depth = 16;
const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
@@ -837,6 +843,8 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers
static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_RGB32);
+ if (!data->own_data)
+ return false;
const int depth = 16;
const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index aff7b79807..839f90f17c 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -72,8 +72,6 @@ QT_BEGIN_NAMESPACE
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dst, const uchar *src, int len);
typedef void (QT_FASTCALL *Rgb888ToRgb32Converter)(quint32 *dst, const uchar *src, int len);
-static Rgb888ToRgb32Converter rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32;
-
struct my_error_mgr : public jpeg_error_mgr {
jmp_buf setjmp_buffer;
};
@@ -242,7 +240,9 @@ static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info,
static bool read_jpeg_image(QImage *outImage,
QSize scaledSize, QRect scaledClipRect,
- QRect clipRect, volatile int inQuality, j_decompress_ptr info, struct my_error_mgr* err )
+ QRect clipRect, volatile int inQuality,
+ Rgb888ToRgb32Converter converter,
+ j_decompress_ptr info, struct my_error_mgr* err )
{
if (!setjmp(err->setjmp_buffer)) {
// -1 means default quality.
@@ -383,7 +383,7 @@ static bool read_jpeg_image(QImage *outImage,
if (info->output_components == 3) {
uchar *in = rows[0] + clip.x() * 3;
QRgb *out = (QRgb*)outImage->scanLine(y);
- rgb888ToRgb32ConverterPtr(out, in, clip.width());
+ converter(out, in, clip.width());
} else if (info->out_color_space == JCS_CMYK) {
// Convert CMYK->RGB.
uchar *in = rows[0] + clip.x() * 4;
@@ -714,7 +714,8 @@ public:
};
QJpegHandlerPrivate(QJpegHandler *qq)
- : quality(75), exifOrientation(1), iod_src(0), state(Ready), optimize(false), progressive(false), q(qq)
+ : quality(75), exifOrientation(1), iod_src(0),
+ rgb888ToRgb32ConverterPtr(qt_convert_rgb888_to_rgb32), state(Ready), optimize(false), progressive(false), q(qq)
{}
~QJpegHandlerPrivate()
@@ -745,6 +746,8 @@ public:
struct my_jpeg_source_mgr * iod_src;
struct my_error_mgr err;
+ Rgb888ToRgb32Converter rgb888ToRgb32ConverterPtr;
+
State state;
bool optimize;
@@ -968,7 +971,7 @@ bool QJpegHandlerPrivate::read(QImage *image)
if(state == ReadHeader)
{
- bool success = read_jpeg_image(image, scaledSize, scaledClipRect, clipRect, quality, &info, &err);
+ bool success = read_jpeg_image(image, scaledSize, scaledClipRect, clipRect, quality, rgb888ToRgb32ConverterPtr, &info, &err);
if (success) {
for (int i = 0; i < readTexts.size()-1; i+=2)
image->setText(readTexts.at(i), readTexts.at(i+1));
@@ -996,18 +999,18 @@ QJpegHandler::QJpegHandler()
// from qimage_neon.cpp
if (qCpuHasFeature(NEON))
- rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon;
+ d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon;
#endif
#if defined(QT_COMPILER_SUPPORTS_SSSE3)
// from qimage_ssse3.cpps
if (qCpuHasFeature(SSSE3)) {
- rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_ssse3;
+ d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_ssse3;
}
#endif // QT_COMPILER_SUPPORTS_SSSE3
#if defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
if (qCpuHasFeature(DSPR2)) {
- rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_mips_dspr2_asm;
+ d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_mips_dspr2_asm;
}
#endif // QT_COMPILER_SUPPORTS_DSPR2
}
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index e6bf2b0be9..547c32b2b4 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -602,8 +602,9 @@ QCursor::operator QVariant() const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QCursor &c)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QCursor(Qt::CursorShape(" << c.shape() << "))";
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 7b75a31847..11f7f13552 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -37,13 +37,13 @@
#include "qpa/qplatformintegration.h"
#include "qpa/qplatformdrag.h"
#include "private/qevent_p.h"
-#include "qdebug.h"
#include "qmetaobject.h"
#include "qmimedata.h"
#include "private/qdnd_p.h"
#include "qevent_p.h"
#include "qmath.h"
+#include <private/qdebug_p.h>
QT_BEGIN_NAMESPACE
@@ -3463,7 +3463,10 @@ QShortcutEvent::~QShortcutEvent()
static inline void formatTouchEvent(QDebug d, const QTouchEvent &t)
{
- d << "QTouchEvent(" << t.type() << " states: " << t.touchPointStates();
+ d << "QTouchEvent(";
+ QtDebugUtils::formatQEnum(d, t.type());
+ d << " states: ";
+ QtDebugUtils::formatQFlags(d, t.touchPointStates());
d << ", " << t.touchPoints().size() << " points: " << t.touchPoints() << ')';
}
@@ -3644,15 +3647,20 @@ static const char *eventClassName(QEvent::Type t)
static void formatDropEvent(QDebug d, const QDropEvent *e)
{
const QEvent::Type type = e->type();
- d << eventClassName(type) << "(dropAction=" << e->dropAction() << ", proposedAction="
- << e->proposedAction() << ", possibleActions=" << e->possibleActions()
- << ", posF=" << e->posF();
+ d << eventClassName(type) << "(dropAction=";
+ QtDebugUtils::formatQEnum(d, e->dropAction());
+ d << ", proposedAction=";
+ QtDebugUtils::formatQEnum(d, e->proposedAction());
+ d << ", possibleActions=";
+ QtDebugUtils::formatQFlags(d, e->possibleActions());
+ d << ", posF=";
+ QtDebugUtils::formatQPoint(d, e->posF());
if (type == QEvent::DragMove || type == QEvent::DragEnter)
d << ", answerRect=" << static_cast<const QDragMoveEvent *>(e)->answerRect();
d << ", formats=" << e->mimeData()->formats();
- if (const Qt::KeyboardModifiers mods = e->keyboardModifiers())
- d << ", keyboardModifiers=" << mods;
- d << ", " << e->mouseButtons();
+ QtDebugUtils::formatNonNullQFlags(d, ", keyboardModifiers=", e->keyboardModifiers());
+ d << ", ";
+ QtDebugUtils::formatQFlags(d, e->mouseButtons());
}
# endif // !QT_NO_DRAGANDDROP
@@ -3663,15 +3671,19 @@ static void formatTabletEvent(QDebug d, const QTabletEvent *e)
{
const QEvent::Type type = e->type();
- d << eventClassName(type) << '(' << type
- << ", device=" << e->device()
- << ", pointerType=" << e->pointerType()
- << ", uniqueId=" << e->uniqueId()
+ d << eventClassName(type) << '(';
+ QtDebugUtils::formatQEnum(d, type);
+ d << ", device=";
+ QtDebugUtils::formatQEnum(d, e->device());
+ d << ", pointerType=";
+ QtDebugUtils::formatQEnum(d, e->pointerType());
+ d << ", uniqueId=" << e->uniqueId()
<< ", pos=" << e->posF()
<< ", z=" << e->z()
<< ", xTilt=" << e->xTilt()
<< ", yTilt=" << e->yTilt()
- << ", " << e->buttons();
+ << ", ";
+ QtDebugUtils::formatQFlags(d, e->buttons());
if (type == QEvent::TabletPress || type == QEvent::TabletMove)
d << ", pressure=" << e->pressure();
if (e->device() == QTabletEvent::RotationStylus || e->device() == QTabletEvent::FourDMouse)
@@ -3685,8 +3697,19 @@ static void formatTabletEvent(QDebug d, const QTabletEvent *e)
QDebug operator<<(QDebug dbg, const QTouchEvent::TouchPoint &tp)
{
QDebugStateSaver saver(dbg);
- dbg.nospace() << "TouchPoint(" << tp.id() << ' ' << tp.rect() << ' ' << tp.state() << " press " << tp.pressure()
- << " vel " << tp.velocity() << " start " << tp.startPos() << " last " << tp.lastPos() << " delta " << tp.pos() - tp.lastPos() << ')';
+ dbg.nospace();
+ dbg << "TouchPoint(" << tp.id() << " (";
+ QtDebugUtils::formatQRect(dbg, tp.rect());
+ dbg << ") ";
+ QtDebugUtils::formatQEnum(dbg, tp.state());
+ dbg << " press " << tp.pressure() << " vel " << tp.velocity()
+ << " start (";
+ QtDebugUtils::formatQPoint(dbg, tp.startPos());
+ dbg << ") last (";
+ QtDebugUtils::formatQPoint(dbg, tp.lastPos());
+ dbg << ") delta (";
+ QtDebugUtils::formatQPoint(dbg, tp.pos() - tp.lastPos());
+ dbg << ')';
return dbg;
}
@@ -3716,18 +3739,23 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
const QMouseEvent *me = static_cast<const QMouseEvent*>(e);
const Qt::MouseButton button = me->button();
const Qt::MouseButtons buttons = me->buttons();
- dbg << "QMouseEvent(" << type;
- if (type != QEvent::MouseMove && type != QEvent::NonClientAreaMouseMove)
- dbg << ", " << button;
- if (buttons && button != buttons)
- dbg << ", buttons=" << buttons;
- if (const int mods = int(me->modifiers()))
- dbg << ", modifiers=0x" << hex << mods << dec;
- dbg << ", localPos=" << me->localPos() << ", screenPos=" << me->screenPos();
- if (me->source())
- dbg << ", " << me->source();
- if (const Qt::MouseEventFlags flags = me->flags())
- dbg << ", flags = " << hex << int(flags) << dec;
+ dbg << "QMouseEvent(";
+ QtDebugUtils::formatQEnum(dbg, type);
+ if (type != QEvent::MouseMove && type != QEvent::NonClientAreaMouseMove) {
+ dbg << ", ";
+ QtDebugUtils::formatQEnum(dbg, button);
+ }
+ if (buttons && button != buttons) {
+ dbg << ", buttons=";
+ QtDebugUtils::formatQFlags(dbg, buttons);
+ }
+ QtDebugUtils::formatNonNullQFlags(dbg, ", ", me->modifiers());
+ dbg << ", localPos=";
+ QtDebugUtils::formatQPoint(dbg, me->localPos());
+ dbg << ", screenPos=";
+ QtDebugUtils::formatQPoint(dbg, me->screenPos());
+ QtDebugUtils::formatNonNullQEnum(dbg, ", ", me->source());
+ QtDebugUtils::formatNonNullQFlags(dbg, ", flags=", me->flags());
dbg << ')';
}
break;
@@ -3743,10 +3771,11 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
case QEvent::ShortcutOverride:
{
const QKeyEvent *ke = static_cast<const QKeyEvent *>(e);
- dbg << "QKeyEvent(" << type
- << ", key=0x" << hex << ke->key() << dec;
- if (const int mods = ke->modifiers())
- dbg << ", modifiers=0x" << hex << mods << dec;
+ dbg << "QKeyEvent(";
+ QtDebugUtils::formatQEnum(dbg, type);
+ dbg << ", ";
+ QtDebugUtils::formatQEnum(dbg, static_cast<Qt::Key>(ke->key()));
+ QtDebugUtils::formatNonNullQFlags(dbg, ", ", ke->modifiers());
if (!ke->text().isEmpty())
dbg << ", text=" << ke->text();
if (ke->isAutoRepeat())
@@ -3765,11 +3794,16 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
case QEvent::FocusAboutToChange:
case QEvent::FocusIn:
case QEvent::FocusOut:
- dbg << "QFocusEvent(" << type << ", " << static_cast<const QFocusEvent *>(e)->reason() << ')';
+ dbg << "QFocusEvent(";
+ QtDebugUtils::formatQEnum(dbg, type);
+ dbg << ", ";
+ QtDebugUtils::formatQEnum(dbg, static_cast<const QFocusEvent *>(e)->reason());
+ dbg << ')';
break;
case QEvent::Move: {
const QMoveEvent *me = static_cast<const QMoveEvent *>(e);
- dbg << "QMoveEvent(" << me->pos();
+ dbg << "QMoveEvent(";
+ QtDebugUtils::formatQPoint(dbg, me->pos());
if (!me->spontaneous())
dbg << ", non-spontaneous";
dbg << ')';
@@ -3777,7 +3811,8 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
break;
case QEvent::Resize: {
const QResizeEvent *re = static_cast<const QResizeEvent *>(e);
- dbg << "QResizeEvent(" << re->size();
+ dbg << "QResizeEvent(";
+ QtDebugUtils::formatQSize(dbg, re->size());
if (!re->spontaneous())
dbg << ", non-spontaneous";
dbg << ')';
@@ -3804,19 +3839,25 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
case QEvent::ChildAdded:
case QEvent::ChildPolished:
case QEvent::ChildRemoved:
- dbg << "QChildEvent(" << type << ", " << (static_cast<const QChildEvent*>(e))->child() << ')';
+ dbg << "QChildEvent(";
+ QtDebugUtils::formatQEnum(dbg, type);
+ dbg << ", " << (static_cast<const QChildEvent*>(e))->child() << ')';
break;
# ifndef QT_NO_GESTURES
case QEvent::NativeGesture: {
const QNativeGestureEvent *ne = static_cast<const QNativeGestureEvent *>(e);
- dbg << "QNativeGestureEvent(" << ne->gestureType()
- << "localPos=" << ne->localPos() << ", value=" << ne->value() << ')';
+ dbg << "QNativeGestureEvent(";
+ QtDebugUtils::formatQEnum(dbg, ne->gestureType());
+ dbg << "localPos=";
+ QtDebugUtils::formatQPoint(dbg, ne->localPos());
+ dbg << ", value=" << ne->value() << ')';
}
break;
# endif // !QT_NO_GESTURES
case QEvent::ApplicationStateChange:
- dbg << "QApplicationStateChangeEvent("
- << static_cast<const QApplicationStateChangeEvent *>(e)->applicationState() << ')';
+ dbg << "QApplicationStateChangeEvent(";
+ QtDebugUtils::formatQEnum(dbg, static_cast<const QApplicationStateChangeEvent *>(e)->applicationState());
+ dbg << ')';
break;
case QEvent::ContextMenu:
dbg << "QContextMenuEvent(" << static_cast<const QContextMenuEvent *>(e)->pos() << ')';
@@ -3849,8 +3890,9 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
dbg << ')';
break;
default:
- dbg << eventClassName(type) << '(' << type << ", "
- << (const void *)e << ", type = " << e->type() << ')';
+ dbg << eventClassName(type) << '(';
+ QtDebugUtils::formatQEnum(dbg, type);
+ dbg << ", " << (const void *)e << ')';
break;
}
return dbg;
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 7b8d5f823e..16db3e66da 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -236,9 +236,7 @@ struct QWindowGeometrySpecification
{
QWindowGeometrySpecification() : corner(Qt::TopLeftCorner), xOffset(-1), yOffset(-1), width(-1), height(-1) {}
static QWindowGeometrySpecification fromArgument(const QByteArray &a);
- QRect apply(const QRect &windowGeometry, const QSize &windowMinimumSize, const QSize &windowMaximumSize, const QRect &availableGeometry) const;
- inline QRect apply(const QRect &windowGeometry, const QWindow *window) const
- { return apply(windowGeometry, window->minimumSize(), window->maximumSize(), window->screen()->virtualGeometry()); }
+ void applyTo(QWindow *window) const;
Qt::Corner corner;
int xOffset;
@@ -300,32 +298,34 @@ QWindowGeometrySpecification QWindowGeometrySpecification::fromArgument(const QB
return result;
}
-QRect QWindowGeometrySpecification::apply(const QRect &windowGeometry, const QSize &windowMinimumSize, const QSize &windowMaximumSize, const QRect &availableGeometry) const
+void QWindowGeometrySpecification::applyTo(QWindow *window) const
{
- QRect result = windowGeometry;
+ QRect windowGeometry = window->frameGeometry();
+ QSize size = windowGeometry.size();
if (width >= 0 || height >= 0) {
- QSize size = windowGeometry.size();
+ const QSize windowMinimumSize = window->minimumSize();
+ const QSize windowMaximumSize = window->maximumSize();
if (width >= 0)
size.setWidth(qBound(windowMinimumSize.width(), width, windowMaximumSize.width()));
if (height >= 0)
size.setHeight(qBound(windowMinimumSize.height(), height, windowMaximumSize.height()));
- result.setSize(size);
+ window->resize(size);
}
if (xOffset >= 0 || yOffset >= 0) {
+ const QRect availableGeometry = window->screen()->virtualGeometry();
QPoint topLeft = windowGeometry.topLeft();
if (xOffset >= 0) {
topLeft.setX(corner == Qt::TopLeftCorner || corner == Qt::BottomLeftCorner ?
xOffset :
- qMax(availableGeometry.right() - result.width() - xOffset, availableGeometry.left()));
+ qMax(availableGeometry.right() - size.width() - xOffset, availableGeometry.left()));
}
if (yOffset >= 0) {
topLeft.setY(corner == Qt::TopLeftCorner || corner == Qt::TopRightCorner ?
yOffset :
- qMax(availableGeometry.bottom() - result.height() - yOffset, availableGeometry.top()));
+ qMax(availableGeometry.bottom() - size.height() - yOffset, availableGeometry.top()));
}
- result.moveTopLeft(topLeft);
+ window->setFramePosition(topLeft);
}
- return result;
}
static QWindowGeometrySpecification windowGeometrySpecification;
@@ -2758,9 +2758,9 @@ void QGuiApplication::setPalette(const QPalette &pal)
emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal);
}
-QRect QGuiApplicationPrivate::applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window)
+void QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(QWindow *window)
{
- return windowGeometrySpecification.apply(windowGeometry, window);
+ windowGeometrySpecification.applyTo(window);
}
/*!
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 7ae6e64b26..0559442049 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -279,7 +279,7 @@ public:
virtual void notifyWindowIconChanged();
- static QRect applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window);
+ static void applyWindowGeometrySpecificationTo(QWindow *window);
static void setApplicationState(Qt::ApplicationState state, bool forcePropagate = false);
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index bdf401aa2d..23d5f06aa2 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -1601,8 +1601,9 @@ QDataStream &operator>>(QDataStream &s, QKeySequence &keysequence)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QKeySequence &p)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QKeySequence(" << p.toString() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 90c54c4039..56a3729a4a 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -636,12 +636,21 @@ void QOpenGLContext::destroy()
d->platformGLContext = 0;
delete d->functions;
d->functions = 0;
+
+ foreach (QAbstractOpenGLFunctions *func, d->externalVersionFunctions) {
+ QAbstractOpenGLFunctionsPrivate *func_d = QAbstractOpenGLFunctionsPrivate::get(func);
+ func_d->owningContext = 0;
+ func_d->initialized = false;
+ }
+ d->externalVersionFunctions.clear();
qDeleteAll(d->versionFunctions);
d->versionFunctions.clear();
qDeleteAll(d->versionFunctionsBackend);
d->versionFunctionsBackend.clear();
+
delete d->textureFunctions;
d->textureFunctions = 0;
+
d->nativeHandle = QVariant();
}
@@ -719,7 +728,7 @@ QOpenGLFunctions *QOpenGLContext::functions() const
QAbstractOpenGLFunctions::initializeOpenGLFunctions() as long as this context
is current. It is also possible to call this function when the context is not
current, but in that case it is the caller's responsibility to ensure proper
- intiialization by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions()
+ initialization by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions()
afterwards.
Usually one would use the template version of this function to automatically
@@ -851,15 +860,26 @@ bool QOpenGLContext::hasExtension(const QByteArray &extension) const
/*!
Call this to get the default framebuffer object for the current surface.
- On some platforms the default framebuffer object depends on the surface
- being rendered to, and might be different from 0. Thus, instead of calling
- glBindFramebuffer(0), you should call
+ On some platforms (for instance, iOS) the default framebuffer object depends
+ on the surface being rendered to, and might be different from 0. Thus,
+ instead of calling glBindFramebuffer(0), you should call
glBindFramebuffer(ctx->defaultFramebufferObject()) if you want your
application to work across different Qt platforms.
If you use the glBindFramebuffer() in QOpenGLFunctions you do not have to
worry about this, as it automatically binds the current context's
defaultFramebufferObject() when 0 is passed.
+
+ \note Widgets that render via framebuffer objects, like QOpenGLWidget and
+ QQuickWidget, will override the value returned from this function when
+ painting is active, because at that time the correct "default" framebuffer
+ is the widget's associated backing framebuffer, not the platform-specific
+ one belonging to the top-level window's surface. This ensures the expected
+ behavior for this function and other classes relying on it (for example,
+ QOpenGLFramebufferObject::bindDefault() or
+ QOpenGLFramebufferObject::release()).
+
+ \sa QOpenGLFramebufferObject
*/
GLuint QOpenGLContext::defaultFramebufferObject() const
{
@@ -870,6 +890,9 @@ GLuint QOpenGLContext::defaultFramebufferObject() const
if (!d->surface || !d->surface->surfaceHandle())
return 0;
+ if (d->defaultFboRedirect)
+ return d->defaultFboRedirect;
+
return d->platformGLContext->defaultFramebufferObject(d->surface->surfaceHandle());
}
@@ -1259,6 +1282,24 @@ void QOpenGLContext::removeFunctionsBackend(const QOpenGLVersionStatus &v)
/*!
\internal
+ */
+void QOpenGLContext::insertExternalFunctions(QAbstractOpenGLFunctions *f)
+{
+ Q_D(QOpenGLContext);
+ d->externalVersionFunctions.insert(f);
+}
+
+/*!
+ \internal
+ */
+void QOpenGLContext::removeExternalFunctions(QAbstractOpenGLFunctions *f)
+{
+ Q_D(QOpenGLContext);
+ d->externalVersionFunctions.remove(f);
+}
+
+/*!
+ \internal
*/
QOpenGLTextureHelper* QOpenGLContext::textureFunctions() const
{
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 30a9bc3ad9..a529957ad6 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -229,6 +229,8 @@ private:
void insertFunctionsBackend(const QOpenGLVersionStatus &v,
QOpenGLVersionFunctionsBackend *backend);
void removeFunctionsBackend(const QOpenGLVersionStatus &v);
+ void insertExternalFunctions(QAbstractOpenGLFunctions *f);
+ void removeExternalFunctions(QAbstractOpenGLFunctions *f);
QOpenGLTextureHelper* textureFunctions() const;
void setTextureFunctions(QOpenGLTextureHelper* textureFuncs);
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index 446efa369c..f9f3ce2c5f 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -204,6 +204,7 @@ public:
, workaround_missingPrecisionQualifiers(false)
, active_engine(0)
, qgl_current_fbo_invalid(false)
+ , defaultFboRedirect(0)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
@@ -216,6 +217,7 @@ public:
mutable QHash<QOpenGLVersionProfile, QAbstractOpenGLFunctions *> versionFunctions;
mutable QHash<QOpenGLVersionStatus, QOpenGLVersionFunctionsBackend *> versionFunctionsBackend;
+ mutable QSet<QAbstractOpenGLFunctions *> externalVersionFunctions;
void *qGLContextHandle;
void (*qGLContextDeleteFunction)(void *handle);
@@ -241,6 +243,7 @@ public:
bool qgl_current_fbo_invalid;
QVariant nativeHandle;
+ GLuint defaultFboRedirect;
static QOpenGLContext *setCurrentContext(QOpenGLContext *context);
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 58bcc2cc5b..cf17e1b5aa 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -1152,6 +1152,7 @@ QDebug operator<<(QDebug dbg, const QPalette &p)
"BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight",
"HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole",
"ToolTipBase","ToolTipText" };
+ QDebugStateSaver saver(dbg);
QDebug nospace = dbg.nospace();
const uint mask = p.resolve();
nospace << "QPalette(resolve=" << hex << showbase << mask << ',';
@@ -1171,7 +1172,7 @@ QDebug operator<<(QDebug dbg, const QPalette &p)
}
}
nospace << ')' << noshowbase << dec;
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index 6147a2a53a..f2a92e10df 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -392,6 +392,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return QPlatformTheme::defaultThemeHint(QPlatformTheme::MousePressAndHoldInterval);
case TabFocusBehavior:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::TabFocusBehavior);
+ case ReplayMousePressOutsidePopup:
+ return true;
}
return 0;
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 24e19f68e6..34639e6929 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -145,7 +145,8 @@ public:
SetFocusOnTouchRelease,
ShowIsMaximized,
MousePressAndHoldInterval,
- TabFocusBehavior
+ TabFocusBehavior,
+ ReplayMousePressOutsidePopup
};
virtual QVariant styleHint(StyleHint hint) const;
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index 16d278b473..0ff5c36119 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -88,14 +88,16 @@ struct QShortcutEntry
/*! \internal
QDebug operator<< for easy debug output of the shortcut entries.
*/
-static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) {
+static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se)
+{
+ QDebugStateSaver saver(dbg);
if (!se)
return dbg << "QShortcutEntry(0x0)";
dbg.nospace()
<< "QShortcutEntry(" << se->keyseq
<< "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat
<< "), owner(" << se->owner << ')';
- return dbg.space();
+ return dbg;
}
#endif // QT_NO_DEBUGSTREAM
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp
index d5f5b358b3..d078336d73 100644
--- a/src/gui/kernel/qsurfaceformat.cpp
+++ b/src/gui/kernel/qsurfaceformat.cpp
@@ -812,6 +812,7 @@ bool operator!=(const QSurfaceFormat& a, const QSurfaceFormat& b)
QDebug operator<<(QDebug dbg, const QSurfaceFormat &f)
{
const QSurfaceFormatPrivate * const d = f.d;
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QSurfaceFormat("
<< "version " << d->major << '.' << d->minor
@@ -828,7 +829,7 @@ QDebug operator<<(QDebug dbg, const QSurfaceFormat &f)
<< ", profile " << d->profile
<< ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 0a732c2a52..c7493a8409 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -490,6 +490,13 @@ void QWindow::setVisible(bool visible)
}
if (!app_priv->forcedWindowIcon.isNull())
setIcon(app_priv->forcedWindowIcon);
+
+ // Handling of the -qwindowgeometry, -geometry command line arguments
+ static bool geometryApplied = false;
+ if (!geometryApplied) {
+ geometryApplied = true;
+ QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(this);
+ }
}
QShowEvent showEvent;
@@ -1503,10 +1510,10 @@ void QWindow::setFramePosition(const QPoint &point)
{
Q_D(QWindow);
d->positionPolicy = QWindowPrivate::WindowFrameInclusive;
+ d->positionAutomatic = false;
if (d->platformWindow) {
d->platformWindow->setGeometry(qHighDpiToDevicePixels(QRect(point, size()), this));
} else {
- d->positionAutomatic = false;
d->geometry.moveTopLeft(point);
}
}
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 808ef9fd66..26f17789f4 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -786,10 +786,12 @@ void QWindowSystemInterface::handleEnterWhatsThisEvent()
#endif
#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPoint &p) {
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPoint &p)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "TouchPoint(" << p.id << " @" << p.area << " normalized " << p.normalPosition
<< " press " << p.pressure << " vel " << p.velocity << " state " << (int)p.state;
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
index afce9d935e..89bc09f544 100644
--- a/src/gui/math3d/qgenericmatrix.h
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -341,6 +341,7 @@ typedef QGenericMatrix<4, 3, float> QMatrix4x3;
template <int N, int M, typename T>
QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T> &m)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QGenericMatrix<" << N << ", " << M
<< ", " << QTypeInfo<T>::name()
<< ">(" << endl << qSetFieldWidth(10);
@@ -350,7 +351,7 @@ QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T> &m)
dbg << endl;
}
dbg << qSetFieldWidth(0) << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 09b41ac570..eb7c7f4b7a 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -2010,6 +2010,7 @@ QMatrix4x4::operator QVariant() const
QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
{
+ QDebugStateSaver saver(dbg);
// Create a string that represents the matrix type.
QByteArray bits;
if (m.flagBits == QMatrix4x4::Identity) {
@@ -2039,7 +2040,7 @@ QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
<< m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl
<< m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl
<< qSetFieldWidth(0) << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
index 90d90448e0..4b35ee4e79 100644
--- a/src/gui/math3d/qquaternion.cpp
+++ b/src/gui/math3d/qquaternion.cpp
@@ -720,8 +720,38 @@ QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis
/*!
\since 5.5
+ Constructs the quaternion using specified forward direction \a direction
+ and upward direction \a up.
+ If the upward direction was not specified or the forward and upward
+ vectors are collinear, a new orthonormal upward direction will be generated.
+
+ \sa fromAxes(), rotationTo()
+*/
+QQuaternion QQuaternion::fromDirection(const QVector3D &direction, const QVector3D &up)
+{
+ if (qFuzzyIsNull(direction.x()) && qFuzzyIsNull(direction.y()) && qFuzzyIsNull(direction.z()))
+ return QQuaternion();
+
+ const QVector3D zAxis(direction.normalized());
+ QVector3D xAxis(QVector3D::crossProduct(up, zAxis));
+ if (qFuzzyIsNull(xAxis.lengthSquared())) {
+ // collinear or invalid up vector; derive shortest arc to new direction
+ return QQuaternion::rotationTo(QVector3D(0.0f, 0.0f, 1.0f), zAxis);
+ }
+
+ xAxis.normalize();
+ const QVector3D yAxis(QVector3D::crossProduct(zAxis, xAxis));
+
+ return QQuaternion::fromAxes(xAxis, yAxis, zAxis);
+}
+
+/*!
+ \since 5.5
+
Returns the shortest arc quaternion to rotate from the direction described by the vector \a from
to the direction described by the vector \a to.
+
+ \sa fromDirection()
*/
QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
{
@@ -950,10 +980,11 @@ QQuaternion::operator QVariant() const
QDebug operator<<(QDebug dbg, const QQuaternion &q)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QQuaternion(scalar:" << q.scalar()
<< ", vector:(" << q.x() << ", "
<< q.y() << ", " << q.z() << "))";
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
index c3918645d4..240e31a5c2 100644
--- a/src/gui/math3d/qquaternion.h
+++ b/src/gui/math3d/qquaternion.h
@@ -138,6 +138,8 @@ public:
void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const;
static QQuaternion fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis);
+ static QQuaternion fromDirection(const QVector3D &direction, const QVector3D &up);
+
static QQuaternion rotationTo(const QVector3D &from, const QVector3D &to);
#endif
diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp
index fe4c9f8cc2..2d8a1d3a0f 100644
--- a/src/gui/math3d/qvector2d.cpp
+++ b/src/gui/math3d/qvector2d.cpp
@@ -499,8 +499,9 @@ QVector2D::operator QVariant() const
QDebug operator<<(QDebug dbg, const QVector2D &vector)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QVector2D(" << vector.x() << ", " << vector.y() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp
index ced4ac9d73..19aa4facdb 100644
--- a/src/gui/math3d/qvector3d.cpp
+++ b/src/gui/math3d/qvector3d.cpp
@@ -697,9 +697,10 @@ float QVector3D::lengthSquared() const
QDebug operator<<(QDebug dbg, const QVector3D &vector)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QVector3D("
<< vector.x() << ", " << vector.y() << ", " << vector.z() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp
index 6afe9b8cad..494e6f97f0 100644
--- a/src/gui/math3d/qvector4d.cpp
+++ b/src/gui/math3d/qvector4d.cpp
@@ -573,10 +573,11 @@ QVector4D::operator QVariant() const
QDebug operator<<(QDebug dbg, const QVector4D &vector)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QVector4D("
<< vector.x() << ", " << vector.y() << ", "
<< vector.z() << ", " << vector.w() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/opengl/qopengldebug.cpp b/src/gui/opengl/qopengldebug.cpp
index 114f118989..e747372df9 100644
--- a/src/gui/opengl/qopengldebug.cpp
+++ b/src/gui/opengl/qopengldebug.cpp
@@ -1039,10 +1039,11 @@ bool QOpenGLDebugMessage::operator==(const QOpenGLDebugMessage &debugMessage) co
*/
QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source)
{
+ QDebugStateSaver saver(debug);
debug.nospace() << "QOpenGLDebugMessage::Source("
<< qt_messageSourceToString(source)
- << ")";
- return debug.space();
+ << ')';
+ return debug;
}
/*!
@@ -1053,10 +1054,11 @@ QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source)
*/
QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type)
{
+ QDebugStateSaver saver(debug);
debug.nospace() << "QOpenGLDebugMessage::Type("
<< qt_messageTypeToString(type)
- << ")";
- return debug.space();
+ << ')';
+ return debug;
}
/*!
@@ -1067,10 +1069,11 @@ QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type)
*/
QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity)
{
+ QDebugStateSaver saver(debug);
debug.nospace() << "QOpenGLDebugMessage::Severity("
<< qt_messageSeverityToString(severity)
- << ")";
- return debug.space();
+ << ')';
+ return debug;
}
/*!
@@ -1081,13 +1084,14 @@ QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity)
*/
QDebug operator<<(QDebug debug, const QOpenGLDebugMessage &message)
{
+ QDebugStateSaver saver(debug);
debug.nospace() << "QOpenGLDebugMessage("
<< qt_messageSourceToString(message.source()) << ", "
<< message.id() << ", "
<< message.message() << ", "
<< qt_messageSeverityToString(message.severity()) << ", "
- << qt_messageTypeToString(message.type()) << ")";
- return debug.space();
+ << qt_messageTypeToString(message.type()) << ')';
+ return debug;
}
#endif // QT_NO_DEBUG_STREAM
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index c4deeea4c9..8d298496df 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -1484,8 +1484,10 @@ void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target,
const int ty0 = targetRect.top();
const int ty1 = targetRect.top() + targetRect.height();
- extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
- extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
+ const GLuint defaultFboId = ctx->defaultFramebufferObject();
+
+ extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : defaultFboId);
+ extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : defaultFboId);
extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1,
tx0, ty0, tx1, ty1,
diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp
index ab493fa85c..6622d4805f 100644
--- a/src/gui/opengl/qopenglgradientcache.cpp
+++ b/src/gui/opengl/qopenglgradientcache.cpp
@@ -34,8 +34,18 @@
#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_RGBA8
+#define GL_RGBA8 0x8058
+#endif
+
+#ifndef GL_RGBA16
+#define GL_RGBA16 0x805B
+#endif
QT_BEGIN_NAMESPACE
@@ -137,33 +147,40 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient
}
CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());
- uint buffer[1024];
+ QRgba64 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);
+ GLenum internalFormat = GL_RGBA16;
+ if (QOpenGLContext::currentContext()->isOpenGLES()) {
+ if (static_cast<QOpenGLExtensions*>(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats))
+ internalFormat = GL_RGBA8;
+ else
+ internalFormat = GL_RGBA; // Let OpenGLES use whatever it prefers.
+ }
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, paletteSize(), 1,
+ 0, GL_RGBA, GL_UNSIGNED_SHORT, 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, uint *colorTable, int size, qreal opacity) const
+void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const
{
int pos = 0;
QGradientStops s = gradient.stops();
- QVector<uint> colors(s.size());
+ QVector<QRgba64> colors(s.size());
for (int i = 0; i < s.size(); ++i)
- colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian)
+ colors[i] = s[i].second.rgba64();
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
uint alpha = qRound(opacity * 256);
- uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha);
+ QRgba64 current_color = combineAlpha256(colors[0], alpha);
qreal incr = 1.0 / qreal(size);
qreal fpos = 1.5 * incr;
- colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color));
+ colorTable[pos++] = qPremultiply(current_color);
while (fpos <= s.first().first) {
colorTable[pos] = colorTable[pos - 1];
@@ -176,7 +193,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
for (int i = 0; i < s.size() - 1; ++i) {
qreal delta = 1/(s[i+1].first - s[i].first);
- uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
+ QRgba64 next_color = combineAlpha256(colors[i+1], alpha);
if (colorInterpolation)
next_color = qPremultiply(next_color);
@@ -184,9 +201,9 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
int dist = int(256 * ((fpos - s[i].first) * delta));
int idist = 256 - dist;
if (colorInterpolation)
- colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
+ colorTable[pos] = interpolate256(current_color, idist, next_color, dist);
else
- colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
+ colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist));
++pos;
fpos += incr;
}
@@ -195,7 +212,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
Q_ASSERT(s.size() > 0);
- uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
+ QRgba64 last_color = qPremultiply(combineAlpha256(colors[s.size() - 1], alpha));
for (;pos < size; ++pos)
colorTable[pos] = last_color;
diff --git a/src/gui/opengl/qopenglgradientcache_p.h b/src/gui/opengl/qopenglgradientcache_p.h
index bcdf3f4fcf..d368f4bcfc 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,7 +84,7 @@ public:
private:
inline int maxCacheSize() const { return 60; }
inline void generateGradientColorTable(const QGradient& gradient,
- uint *colorTable,
+ QRgba64 *colorTable,
int size, qreal opacity) const;
GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity);
void cleanCache();
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index fa4b6cdab0..9bc9926b70 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -3650,7 +3650,7 @@ QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const
}
/*!
- \enum ComparisonFunction
+ \enum QOpenGLTexture::ComparisonFunction
\since 5.5
This enum specifies which comparison operator is used when texture comparison
is enabled on this texture.
diff --git a/src/gui/opengl/qopenglversionfunctions.cpp b/src/gui/opengl/qopenglversionfunctions.cpp
index f3f709c3f0..346a526054 100644
--- a/src/gui/opengl/qopenglversionfunctions.cpp
+++ b/src/gui/opengl/qopenglversionfunctions.cpp
@@ -67,6 +67,17 @@ void QAbstractOpenGLFunctionsPrivate::removeFunctionsBackend(QOpenGLContext *con
context->removeFunctionsBackend(v);
}
+void QAbstractOpenGLFunctionsPrivate::insertExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f)
+{
+ Q_ASSERT(context);
+ context->insertExternalFunctions(f);
+}
+
+void QAbstractOpenGLFunctionsPrivate::removeExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f)
+{
+ Q_ASSERT(context);
+ context->removeExternalFunctions(f);
+}
/*!
\class QAbstractOpenGLFunctions
@@ -182,6 +193,9 @@ QAbstractOpenGLFunctions::QAbstractOpenGLFunctions()
QAbstractOpenGLFunctions::~QAbstractOpenGLFunctions()
{
+ Q_D(QAbstractOpenGLFunctions);
+ if (d->owningContext)
+ d->removeExternalFunctions(d->owningContext, this);
delete d_ptr;
}
@@ -191,6 +205,18 @@ bool QAbstractOpenGLFunctions::initializeOpenGLFunctions()
{
Q_D(QAbstractOpenGLFunctions);
d->initialized = true;
+
+ // For a subclass whose instance is not created via
+ // QOpenGLContext::versionFunctions() owningContext is not set. Set it now
+ // and register such instances to the context as external ones. These are
+ // not owned by the context but still need certain cleanup when the context
+ // is destroyed.
+ if (!d->owningContext) {
+ d->owningContext = QOpenGLContext::currentContext();
+ if (d->owningContext)
+ d->insertExternalFunctions(d->owningContext, this);
+ }
+
return true;
}
diff --git a/src/gui/opengl/qopenglversionfunctions.h b/src/gui/opengl/qopenglversionfunctions.h
index 2ae0f429e5..fcf665f97e 100644
--- a/src/gui/opengl/qopenglversionfunctions.h
+++ b/src/gui/opengl/qopenglversionfunctions.h
@@ -114,6 +114,8 @@ public:
QAtomicInt refs;
};
+class QAbstractOpenGLFunctions;
+
class QAbstractOpenGLFunctionsPrivate
{
public:
@@ -128,12 +130,16 @@ public:
const QOpenGLVersionStatus &v,
QOpenGLVersionFunctionsBackend *backend);
static void removeFunctionsBackend(QOpenGLContext *context, const QOpenGLVersionStatus &v);
+ static void insertExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f);
+ static void removeExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f);
+
+ static QAbstractOpenGLFunctionsPrivate *get(QAbstractOpenGLFunctions *q);
QOpenGLContext *owningContext;
bool initialized;
};
-class QAbstractOpenGLFunctions
+class Q_GUI_EXPORT QAbstractOpenGLFunctions
{
public:
virtual ~QAbstractOpenGLFunctions();
@@ -154,6 +160,11 @@ protected:
friend class QOpenGLContext;
};
+inline QAbstractOpenGLFunctionsPrivate *QAbstractOpenGLFunctionsPrivate::get(QAbstractOpenGLFunctions *q)
+{
+ return q->d_func();
+}
+
#if !defined(QT_OPENGL_ES_2)
class QOpenGLFunctions_1_0_CoreBackend : public QOpenGLVersionFunctionsBackend
diff --git a/src/gui/opengl/qopenglvertexarrayobject.cpp b/src/gui/opengl/qopenglvertexarrayobject.cpp
index 6b0f2fede7..2a1b7f4bf4 100644
--- a/src/gui/opengl/qopenglvertexarrayobject.cpp
+++ b/src/gui/opengl/qopenglvertexarrayobject.cpp
@@ -189,11 +189,16 @@ bool QOpenGLVertexArrayObjectPrivate::create()
void QOpenGLVertexArrayObjectPrivate::destroy()
{
+ Q_Q(QOpenGLVertexArrayObject);
+
+ if (context) {
+ QObject::disconnect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed()));
+ context = 0;
+ }
+
if (!vao)
return;
- Q_Q(QOpenGLVertexArrayObject);
-
switch (vaoFuncsType) {
#ifndef QT_OPENGL_ES_2
case Core_3_2:
@@ -212,10 +217,6 @@ void QOpenGLVertexArrayObjectPrivate::destroy()
break;
}
- Q_ASSERT(context);
- QObject::disconnect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed()));
- context = 0;
-
vao = 0;
}
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 3010d4052a..fafc67cf46 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -44,6 +44,7 @@ HEADERS += \
painting/qregion.h \
painting/qrgb.h \
painting/qrgba64.h \
+ painting/qrgba64_p.h \
painting/qstroker_p.h \
painting/qtextureglyphcache_p.h \
painting/qtransform.h \
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 27f28f7193..5bf8387400 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -1022,8 +1022,9 @@ QDebug operator<<(QDebug dbg, const QBrush &b)
"TexturePattern" // 24
};
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QBrush(" << b.color() << ',' << BRUSH_STYLES[b.style()] << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 806c9362ac..b33d7a74fc 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -2469,6 +2469,7 @@ void QColor::invalidate()
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QColor &c)
{
+ QDebugStateSaver saver(dbg);
if (!c.isValid())
dbg.nospace() << "QColor(Invalid)";
else if (c.spec() == QColor::Rgb)
@@ -2481,7 +2482,7 @@ QDebug operator<<(QDebug dbg, const QColor &c)
else if (c.spec() == QColor::Hsl)
dbg.nospace() << "QColor(AHSL " << c.alphaF() << ", " << c.hslHueF() << ", " << c.hslSaturationF() << ", " << c.lightnessF() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp
index f82b098012..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;
@@ -602,8 +603,7 @@ void QCosmeticStroker::drawPath(const QVectorPath &path)
if (!closed && drawCaps && points == end - 2)
caps |= CapEnd;
- QCosmeticStroker::Point last = this->lastPixel;
- bool unclipped = stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps);
+ bool moveNextStart = stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps);
/* fix for gaps in polylines with fastpen and aliased in a sequence
of points with small distances: if current point p2 has been dropped
@@ -613,14 +613,8 @@ void QCosmeticStroker::drawPath(const QVectorPath &path)
still need to update p to avoid drawing the line after this one from
a bad starting position.
*/
- if (fastPenAliased && unclipped) {
- if (last.x != lastPixel.x || last.y != lastPixel.y
- || points == begin + 2 || points == end - 2) {
- p = p2;
- }
- } else {
+ if (!fastPenAliased || moveNextStart || points == begin + 2 || points == end - 2)
p = p2;
- }
points += 2;
caps = NoCaps;
}
@@ -727,8 +721,9 @@ template<DrawPixel drawPixel, class Dasher>
static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)
{
if (stroker->clipLine(rx1, ry1, rx2, ry2))
- return false;
+ return true;
+ bool didDraw = false;
const int half = stroker->legacyRounding ? 31 : 0;
int x1 = toF26Dot6(rx1) + half;
int y1 = toF26Dot6(ry1) + half;
@@ -814,6 +809,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
dasher.adjust();
x += xinc;
} while (++y < ys);
+ didDraw = true;
}
} else {
// horizontal
@@ -889,10 +885,11 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
dasher.adjust();
y += yinc;
} while (++x < xs);
+ didDraw = true;
}
}
stroker->lastPixel = last;
- return true;
+ return didDraw;
}
@@ -900,7 +897,7 @@ template<DrawPixel drawPixel, class Dasher>
static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)
{
if (stroker->clipLine(rx1, ry1, rx2, ry2))
- return false;
+ return true;
int x1 = toF26Dot6(rx1);
int y1 = toF26Dot6(ry1);
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 538389f15f..b6f06135cd 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
@@ -758,6 +759,35 @@ 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);
+ ptr = const_cast<uint *>(layout->convertToARGB32PM(buffer32, ptr, length, layout, 0));
+
+ for (int i = 0; i < length; ++i) {
+ buffer[i] = QRgba64::fromArgb32(ptr[i]);
+ }
+ return buffer;
+}
+
+static QRgba64 *QT_FASTCALL destFetch64ARGB32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+{
+ const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x;
+ for (int i = 0; i < length; ++i)
+ buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied();
+ return buffer;
+}
+
+template<QtPixelOrder PixelOrder>
+static QRgba64 *QT_FASTCALL destFetch64RGB30(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+{
+ const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x;
+ for (int i = 0; i < length; ++i)
+ buffer[i] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]);
+ return buffer;
+}
static DestFetchProc destFetchProc[QImage::NImageFormats] =
{
@@ -788,6 +818,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
+ destFetch64, // Format_RGB32
+ destFetch64ARGB32, // Format_ARGB32,
+ destFetch64, // 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
+ destFetch64, // Format_RGBX8888
+ destFetch64, // Format_RGBA8888
+ destFetch64, // Format_RGBA8888_Premultiplied
+ destFetch64RGB30<PixelOrderBGR>, // Format_BGR30
+ destFetch64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied
+ destFetch64RGB30<PixelOrderRGB>, // Format_RGB30
+ destFetch64RGB30<PixelOrderRGB>, // 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 +963,51 @@ 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;
+ }
+}
+
+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();
+ }
+}
+
+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;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = qConvertRgb64ToRgb30<PixelOrder>(buffer[i]);
+ }
+}
+
static DestStoreProc destStoreProc[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -933,6 +1037,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
+ destStore64, // 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
@@ -1539,40 +1672,29 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
const __m128i v_256 = _mm_set1_epi16(256);
const __m128i v_disty = _mm_set1_epi16(disty);
- __m128i v_fdx = _mm_set1_epi32(fdx*4);
-
- ptrdiff_t secondLine = reinterpret_cast<const uint *>(s2) - reinterpret_cast<const uint *>(s1);
-
- union Vect_buffer { __m128i vect; quint32 i[4]; };
- Vect_buffer v_fx;
-
- for (int i = 0; i < 4; i++) {
- v_fx.i[i] = fx;
- 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);
while (b < boundedEnd) {
-
- Vect_buffer tl, tr, bl, br;
-
- for (int i = 0; i < 4; i++) {
- int x1 = v_fx.i[i] >> 16;
- const uint *addr_tl = reinterpret_cast<const uint *>(s1) + x1;
- const uint *addr_tr = addr_tl + 1;
- tl.i[i] = *addr_tl;
- tr.i[i] = *addr_tr;
- bl.i[i] = *(addr_tl+secondLine);
- br.i[i] = *(addr_tr+secondLine);
- }
- __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12);
+ __m128i offset = _mm_srli_epi32(v_fx, 16);
+ const int offset0 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4);
+ const int offset1 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4);
+ const int offset2 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4);
+ const int offset3 = _mm_cvtsi128_si32(offset);
+ const __m128i tl = _mm_setr_epi32(s1[offset0], s1[offset1], s1[offset2], s1[offset3]);
+ const __m128i tr = _mm_setr_epi32(s1[offset0 + 1], s1[offset1 + 1], s1[offset2 + 1], s1[offset3 + 1]);
+ const __m128i bl = _mm_setr_epi32(s2[offset0], s2[offset1], s2[offset2], s2[offset3]);
+ const __m128i br = _mm_setr_epi32(s2[offset0 + 1], s2[offset1 + 1], s2[offset2 + 1], s2[offset3 + 1]);
+
+ __m128i v_distx = _mm_srli_epi16(v_fx, 12);
v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
- interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b);
- b+=4;
- v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx);
+ interpolate_4_pixels_16_sse2(tl, tr, bl, br, v_distx, v_disty, colorMask, v_256, b);
+ b += 4;
+ v_fx = _mm_add_epi32(v_fx, v_fdx);
}
- fx = v_fx.i[0];
+ fx = _mm_cvtsi128_si32(v_fx);
#elif defined(__ARM_NEON__)
BILINEAR_DOWNSCALE_BOUNDS_PROLOG
@@ -1687,9 +1809,9 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
uint tr = s1[x2]; \
uint bl = s2[x1]; \
uint br = s2[x2]; \
- int distx = (fx & 0x0000ffff) >> 12; \
- int disty = (fy & 0x0000ffff) >> 12; \
- *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \
+ int distx = (fx & 0x0000ffff) >> 8; \
+ int disty = (fy & 0x0000ffff) >> 8; \
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); \
fx += fdx; \
fy += fdy; \
++b; \
@@ -1702,62 +1824,54 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
const __m128i v_256 = _mm_set1_epi16(256);
- __m128i v_fdx = _mm_set1_epi32(fdx*4);
- __m128i v_fdy = _mm_set1_epi32(fdy*4);
+ 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 uchar *textureData = data->texture.imageData;
const int bytesPerLine = data->texture.bytesPerLine;
-
- union Vect_buffer { __m128i vect; qint32 i[4]; };
- Vect_buffer v_fx, v_fy;
-
- for (int i = 0; i < 4; i++) {
- v_fx.i[i] = fx;
- v_fy.i[i] = fy;
- fx += fdx;
- fy += fdy;
- }
+ const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0));
while (b < boundedEnd) {
- if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
+ if (fdx > 0 && (short)_mm_extract_epi16(v_fx, 7) >= image_x2)
break;
- if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
+ if (fdx < 0 && (short)_mm_extract_epi16(v_fx, 7) < image_x1)
break;
- if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
+ if (fdy > 0 && (short)_mm_extract_epi16(v_fy, 7) >= image_y2)
break;
- if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
+ if (fdy < 0 && (short)_mm_extract_epi16(v_fy, 7) < image_y1)
break;
- Vect_buffer tl, tr, bl, br;
- Vect_buffer v_fx_shifted, v_fy_shifted;
- v_fx_shifted.vect = _mm_srli_epi32(v_fx.vect, 16);
- v_fy_shifted.vect = _mm_srli_epi32(v_fy.vect, 16);
-
- for (int i = 0; i < 4; i++) {
- const int x1 = v_fx_shifted.i[i];
- const int y1 = v_fy_shifted.i[i];
- const uchar *sl = textureData + bytesPerLine * y1;
- const uint *s1 = (const uint *)sl;
- const uint *s2 = (const uint *)(sl + bytesPerLine);
- tl.i[i] = s1[x1];
- tr.i[i] = s1[x1+1];
- bl.i[i] = s2[x1];
- br.i[i] = s2[x1+1];
- }
- __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12);
- __m128i v_disty = _mm_srli_epi16(v_fy.vect, 12);
+ const __m128i vy = _mm_packs_epi32(_mm_srli_epi32(v_fy, 16), _mm_setzero_si128());
+ // 4x16bit * 4x16bit -> 4x32bit
+ __m128i offset = _mm_unpacklo_epi16(_mm_mullo_epi16(vy, vbpl), _mm_mulhi_epi16(vy, vbpl));
+ offset = _mm_add_epi32(offset, _mm_srli_epi32(v_fx, 16));
+ const int offset0 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4);
+ const int offset1 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4);
+ const int offset2 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4);
+ const int offset3 = _mm_cvtsi128_si32(offset);
+ const uint *topData = (const uint *)(textureData);
+ const __m128i tl = _mm_setr_epi32(topData[offset0], topData[offset1], topData[offset2], topData[offset3]);
+ const __m128i tr = _mm_setr_epi32(topData[offset0 + 1], topData[offset1 + 1], topData[offset2 + 1], topData[offset3 + 1]);
+ const uint *bottomData = (const uint *)(textureData + bytesPerLine);
+ const __m128i bl = _mm_setr_epi32(bottomData[offset0], bottomData[offset1], bottomData[offset2], bottomData[offset3]);
+ const __m128i br = _mm_setr_epi32(bottomData[offset0 + 1], bottomData[offset1 + 1], bottomData[offset2 + 1], bottomData[offset3 + 1]);
+
+ __m128i v_distx = _mm_srli_epi16(v_fx, 12);
+ __m128i v_disty = _mm_srli_epi16(v_fy, 12);
v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
v_disty = _mm_shufflehi_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
v_disty = _mm_shufflelo_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
- interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b);
- b+=4;
- v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx);
- v_fy.vect = _mm_add_epi32(v_fy.vect, v_fdy);
+ interpolate_4_pixels_16_sse2(tl, tr, bl, br, v_distx, v_disty, colorMask, v_256, b);
+ b += 4;
+ v_fx = _mm_add_epi32(v_fx, v_fdx);
+ v_fy = _mm_add_epi32(v_fy, v_fdy);
}
- fx = v_fx.i[0];
- fy = v_fy.i[0];
+ fx = _mm_cvtsi128_si32(v_fx);
+ fy = _mm_cvtsi128_si32(v_fy);
#endif
}
@@ -1778,10 +1892,16 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
uint bl = s2[x1];
uint br = s2[x2];
+#if defined(__SSE2__)
+ // The SSE2 optimized interpolate_4_pixels is faster than interpolate_4_pixels_16.
+ int distx = (fx & 0x0000ffff) >> 8;
+ int disty = (fy & 0x0000ffff) >> 8;
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
+#else
int distx = (fx & 0x0000ffff) >> 12;
int disty = (fy & 0x0000ffff) >> 12;
-
*b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
+#endif
fx += fdx;
fy += fdy;
@@ -2334,6 +2454,12 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
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)];
}
@@ -2418,6 +2544,75 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope
return b;
}
+static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ const QRgba64 *b = buffer;
+ qreal t, inc;
+
+ bool affine = true;
+ qreal rx=0, ry=0;
+ if (op->linear.l == 0) {
+ t = inc = 0;
+ } else {
+ rx = data->m21 * (y + qreal(0.5)) + data->m11 * (x + qreal(0.5)) + data->dx;
+ ry = data->m22 * (y + qreal(0.5)) + data->m12 * (x + qreal(0.5)) + data->dy;
+ t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off;
+ inc = op->linear.dx * data->m11 + op->linear.dy * data->m12;
+ affine = !data->m13 && !data->m23;
+
+ if (affine) {
+ t *= (GRADIENT_STOPTABLE_SIZE - 1);
+ inc *= (GRADIENT_STOPTABLE_SIZE - 1);
+ }
+ }
+
+ const QRgba64 *end = buffer + length;
+ if (affine) {
+ if (inc > qreal(-1e-5) && inc < qreal(1e-5)) {
+ QRgba64 color = qt_gradient_pixel64_fixed(&data->gradient, int(t * FIXPT_SIZE));
+ qt_memfill64((quint64*)buffer, color, length);
+ } else {
+ if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) &&
+ t+inc*length > qreal(INT_MIN >> (FIXPT_BITS + 1))) {
+ // we can use fixed point math
+ int t_fixed = int(t * FIXPT_SIZE);
+ int inc_fixed = int(inc * FIXPT_SIZE);
+ while (buffer < end) {
+ *buffer = qt_gradient_pixel64_fixed(&data->gradient, t_fixed);
+ t_fixed += inc_fixed;
+ ++buffer;
+ }
+ } else {
+ // we have to fall back to float math
+ while (buffer < end) {
+ *buffer = qt_gradient_pixel64(&data->gradient, t/GRADIENT_STOPTABLE_SIZE);
+ t += inc;
+ ++buffer;
+ }
+ }
+ }
+ } else { // fall back to float math here as well
+ qreal rw = data->m23 * (y + qreal(0.5)) + data->m13 * (x + qreal(0.5)) + data->m33;
+ while (buffer < end) {
+ qreal x = rx/rw;
+ qreal y = ry/rw;
+ t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off;
+
+ *buffer = qt_gradient_pixel64(&data->gradient, t);
+ rx += data->m11;
+ ry += data->m12;
+ rw += data->m13;
+ if (!rw) {
+ rw += data->m13;
+ }
+ ++buffer;
+ }
+ }
+
+ return b;
+}
+
static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data)
{
v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x;
@@ -2573,11 +2768,35 @@ void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_
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
@@ -2597,6 +2816,19 @@ void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint
}
}
+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) {
@@ -2611,14 +2843,34 @@ void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL
}
}
+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
@@ -2640,6 +2892,19 @@ void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint 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)
@@ -2661,6 +2926,24 @@ void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_
}
}
+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
@@ -2678,6 +2961,16 @@ void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint co
}
}
+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)
@@ -2697,6 +2990,22 @@ void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uin
}
}
+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
@@ -4237,7 +4546,21 @@ static CompositionFunctionSolid functionForModeSolid_C[] = {
rasterop_solid_NotDestination
};
+static CompositionFunctionSolid64 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,
+ 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,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C;
+static const CompositionFunctionSolid64 *functionForModeSolid64 = functionForModeSolid64_C;
static CompositionFunction functionForMode_C[] = {
comp_func_SourceOver,
@@ -4280,7 +4603,21 @@ static CompositionFunction functionForMode_C[] = {
rasterop_NotDestination
};
+static CompositionFunction64 functionForMode64_C[] = {
+ comp_func_SourceOver_rgb64,
+ comp_func_DestinationOver_rgb64,
+ comp_func_Clear_rgb64,
+ comp_func_Source_rgb64,
+ comp_func_Destination_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,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
static const CompositionFunction *functionForMode = functionForMode_C;
+static const CompositionFunction64 *functionForMode64 = functionForMode64_C;
static TextureBlendType getBlendType(const QSpanData *data)
{
@@ -4310,24 +4647,28 @@ 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();
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 = 0; //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 = 0; //qt_fetch_conical_gradient_rgb64;
break;
case QSpanData::Texture:
- op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format];
+ op.srcFetch = sourceFetch[getBlendType(data)][data->texture.format];
+ op.srcFetch64 = 0; // sourceFetch64[getBlendType(data)][data->texture.format];
solidSource = !data->texture.hasAlpha;
default:
break;
@@ -4337,12 +4678,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)
@@ -4356,16 +4698,21 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
}
++spans;
}
- if (!alphaSpans)
- op.dest_fetch = 0;
+ if (!alphaSpans) {
+ op.destFetch = 0;
+ op.destFetch64 = 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;
}
@@ -4382,16 +4729,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;
}
@@ -4404,15 +4752,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);
@@ -4424,7 +4773,35 @@ 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 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ op.funcSolid64(dest, l, color, spans->coverage);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+ length -= l;
+ x += l;
+ }
++spans;
}
}
@@ -4439,13 +4816,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) {
@@ -4466,7 +4842,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;
@@ -4530,7 +4906,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?
@@ -4555,8 +4931,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)
@@ -4567,24 +4945,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)
@@ -4594,8 +4972,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.srcFetch64 && op.func64;
+ }
+
+ 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);
}
};
@@ -4606,6 +5014,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);
@@ -4636,11 +5058,60 @@ 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.srcFetch64 || !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 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ op.func64(dest, src, l, coverage);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
x += l;
sx += l;
length -= l;
@@ -4829,11 +5300,63 @@ 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.srcFetch64 || !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 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ op.func64(dest, src, l, coverage);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
x += l;
sx += l;
length -= l;
@@ -5714,10 +6237,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,
},
@@ -5742,10 +6265,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,
},
@@ -5770,10 +6293,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,
},
@@ -5797,12 +6320,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
{
@@ -5825,10 +6348,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,
},
@@ -5853,10 +6376,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
}
@@ -6012,13 +6535,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;
}
@@ -6030,39 +6551,39 @@ 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);
}
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);
@@ -6160,7 +6681,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,
@@ -6256,28 +6777,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)
@@ -6344,58 +6875,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
@@ -6548,39 +7088,39 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
},
// Format_BGR30
{
- blend_color_generic,
- blend_src_generic,
+ blend_color_generic_rgb64,
+ blend_src_generic_rgb64,
0,
0,
0,
- 0
+ qt_rectfill_rgb30<PixelOrderBGR>
},
// Format_A2BGR30_Premultiplied
{
- blend_color_generic,
- blend_src_generic,
+ blend_color_generic_rgb64,
+ blend_src_generic_rgb64,
0,
0,
0,
- 0
+ qt_rectfill_rgb30<PixelOrderBGR>
},
// Format_RGB30
{
- blend_color_generic,
- blend_src_generic,
+ blend_color_generic_rgb64,
+ blend_src_generic_rgb64,
0,
0,
0,
- 0
+ qt_rectfill_rgb30<PixelOrderRGB>
},
// Format_A2RGB30_Premultiplied
{
- blend_color_generic,
- blend_src_generic,
+ blend_color_generic_rgb64,
+ blend_src_generic_rgb64,
0,
0,
0,
- 0
+ qt_rectfill_rgb30<PixelOrderRGB>
},
// Format_Alpha8
{
@@ -6649,6 +7189,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)
{
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 7e12e62151..36e2488a94 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);
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 480ba4c97b..501f1ce033 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)];
}
@@ -526,7 +546,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) \
@@ -644,7 +664,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;
@@ -687,6 +708,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);
@@ -871,6 +897,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;
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index 84eb3b7909..b8957fe2fb 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -417,7 +417,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 +468,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);
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/qmatrix.cpp b/src/gui/painting/qmatrix.cpp
index 679b5000cb..acedc6a7ba 100644
--- a/src/gui/painting/qmatrix.cpp
+++ b/src/gui/painting/qmatrix.cpp
@@ -1130,6 +1130,7 @@ QDataStream &operator>>(QDataStream &s, QMatrix &m)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QMatrix &m)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QMatrix("
<< "11=" << m.m11()
<< " 12=" << m.m12()
@@ -1138,7 +1139,7 @@ QDebug operator<<(QDebug dbg, const QMatrix &m)
<< " dx=" << m.dx()
<< " dy=" << m.dy()
<< ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/painting/qpagelayout.cpp b/src/gui/painting/qpagelayout.cpp
index c1b23960ad..f443bbd5ac 100644
--- a/src/gui/painting/qpagelayout.cpp
+++ b/src/gui/painting/qpagelayout.cpp
@@ -942,6 +942,7 @@ QRect QPageLayout::paintRectPixels(int resolution) const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPageLayout &layout)
{
+ QDebugStateSaver saver(dbg);
if (layout.isValid()) {
QString output = QStringLiteral("QPageLayout(%1, %2, l:%3 r:%4 t:%5 b:%6 %7)");
QString units;
@@ -976,7 +977,7 @@ QDebug operator<<(QDebug dbg, const QPageLayout &layout)
} else {
dbg.nospace() << "QPageLayout()";
}
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/painting/qpagesize.cpp b/src/gui/painting/qpagesize.cpp
index fe445c0aec..c0aae603b7 100644
--- a/src/gui/painting/qpagesize.cpp
+++ b/src/gui/painting/qpagesize.cpp
@@ -1854,6 +1854,7 @@ QSize QPageSize::sizePixels(PageSizeId pageSizeId, int resolution)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPageSize &pageSize)
{
+ QDebugStateSaver saver(dbg);
if (pageSize.isValid()) {
QString output = QStringLiteral("QPageSize(\"%1\", \"%2\", %3x%4pt, %5)");
output = output.arg(pageSize.name())
@@ -1865,7 +1866,7 @@ QDebug operator<<(QDebug dbg, const QPageSize &pageSize)
} else {
dbg.nospace() << "QPageSize()";
}
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 18522cb6d0..3be6e0f1f4 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -57,6 +57,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 +831,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 +1413,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 +1773,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 +2220,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();
@@ -4137,7 +4134,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 +4143,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 +4171,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 +4187,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 +4196,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 +4217,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 +4238,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 +4255,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 +4274,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 +4287,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 +4311,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 +4331,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 +4352,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 +4370,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 +4403,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 +4414,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 +4431,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 +4452,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 69cbb42923..70862ea583 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7462,6 +7462,7 @@ start_lengthVariant:
range.format.setFontUnderline(true);
underlineFormats.append(range);
}
+#ifdef Q_OS_MAC
} else if (hidemnmemonic && *cin == QLatin1Char('(') && l >= 4 &&
cin[1] == QLatin1Char('&') && cin[2] != QLatin1Char('&') &&
cin[3] == QLatin1Char(')')) {
@@ -7473,6 +7474,7 @@ start_lengthVariant:
length -= n + 4;
l -= 4;
continue;
+#endif //Q_OS_MAC
}
*cout = *cin;
++cout;
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index 4796d2c0ad..6263d18b01 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -1026,12 +1026,13 @@ QDebug operator<<(QDebug dbg, const QPen &p)
"CustomDashLine"
};
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QPen(" << p.width() << ',' << p.brush()
<< ',' << PEN_STYLES[p.style()] << ',' << int(p.capStyle())
<< ',' << int(p.joinStyle()) << ',' << p.dashPattern()
<< ',' << p.dashOffset()
<< ',' << p.miterLimit() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp
index 511af49787..efcc8875a5 100644
--- a/src/gui/painting/qpolygon.cpp
+++ b/src/gui/painting/qpolygon.cpp
@@ -461,11 +461,12 @@ QRect QPolygon::boundingRect() const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPolygon &a)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QPolygon(";
for (int i = 0; i < a.count(); ++i)
dbg.nospace() << a.at(i);
dbg.nospace() << ')';
- return dbg.space();
+ return dbg;
}
#endif
@@ -802,11 +803,12 @@ QDataStream &operator>>(QDataStream &s, QPolygonF &a)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPolygonF &a)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QPolygonF(";
for (int i = 0; i < a.count(); ++i)
dbg.nospace() << a.at(i);
dbg.nospace() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h
index 2ea09e6bd6..51ce4ab10d 100644
--- a/src/gui/painting/qrgba64.h
+++ b/src/gui/painting/qrgba64.h
@@ -88,6 +88,9 @@ public:
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; }
@@ -133,6 +136,12 @@ public:
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); }
diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h
new file mode 100644
index 0000000000..a1452af8d9
--- /dev/null
+++ b/src/gui/painting/qrgba64_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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>
+
+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 multiplyAlpha255(QRgba64 rgba64, uint alpha255)
+{
+ 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));
+}
+
+inline QRgba64 multiplyAlpha65535(QRgba64 rgba64, uint alpha65535)
+{
+ 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));
+}
+
+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));
+}
+
+QT_END_NAMESPACE
+
+#endif // QRGBA64_P_H
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 881fae9afc..4c879cf05d 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -123,17 +123,6 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
continue;
- // This is a rather crude hack, but it works.
- // The FreeType font engine is not capable of getting precise metrics for the alphamap
- // without first rasterizing the glyph. If we force the glyph to be rasterized before
- // we ask for the alphaMapBoundingBox(), the glyph will be loaded, rasterized and its
- // proper metrics will be cached and used later.
- if (fontEngine->hasInternalCaching()) {
- QImage *locked = fontEngine->lockedAlphaMapForGlyph(glyph, subPixelPosition, m_format);
- if (locked && !locked->isNull())
- fontEngine->unlockAlphaMapForGlyph();
- }
-
glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, m_format);
#ifdef CACHE_DEBUG
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 4c1aff92ae..31d7a2300b 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -1091,6 +1091,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m)
"TxProject"
};
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
<< " 11=" << m.m11()
<< " 12=" << m.m12()
@@ -1103,7 +1104,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m)
<< " 33=" << m.m33()
<< ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index f9e6a7e335..3c98cb568d 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -364,6 +364,29 @@ static quint64 findKnownValue(const QString &name, const QCssKnownValue *start,
return prop->id;
}
+static inline bool isInheritable(Property propertyId)
+{
+ switch (propertyId) {
+ case Font:
+ case FontFamily:
+ case FontSize:
+ case FontStyle:
+ case FontWeight:
+ case TextIndent:
+ case Whitespace:
+ case ListStyleType:
+ case ListStyle:
+ case TextAlignment:
+ case FontVariant:
+ case TextTransform:
+ case LineHeight:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Value Extractor
ValueExtractor::ValueExtractor(const QVector<Declaration> &decls, const QPalette &pal)
@@ -2317,6 +2340,7 @@ bool Parser::parseProperty(Declaration *decl)
{
decl->d->property = lexem();
decl->d->propertyId = static_cast<Property>(findKnownValue(decl->d->property, properties, NumProperties));
+ decl->d->inheritable = isInheritable(decl->d->propertyId);
skipSpace();
return true;
}
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index ebd9904762..75802ba36a 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -426,12 +426,13 @@ struct Q_GUI_EXPORT Declaration
{
struct DeclarationData : public QSharedData
{
- inline DeclarationData() : propertyId(UnknownProperty), important(false) {}
+ inline DeclarationData() : propertyId(UnknownProperty), important(false), inheritable(false) {}
QString property;
Property propertyId;
QVector<Value> values;
QVariant parsed;
- bool important;
+ bool important:1;
+ bool inheritable:1;
};
QExplicitlySharedDataPointer<DeclarationData> d;
inline Declaration() : d(new DeclarationData()) {}
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 8176ede994..931c71dc63 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -43,6 +43,7 @@
#include "qfile.h"
#include "qfileinfo.h"
+#include <qscopedvaluerollback.h>
#include "qthreadstorage.h"
#include <qmath.h>
@@ -800,6 +801,17 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
return load_flags;
}
+static inline bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info)
+{
+ // false if exceeds QFontEngineFT::Glyph metrics
+ return (short)(info.linearAdvance) != info.linearAdvance
+ || (signed char)(info.xOff) != info.xOff
+ || (uchar)(info.width) != info.width
+ || (uchar)(info.height) != info.height
+ || (signed char)(info.x) != info.x
+ || (signed char)(info.y) != info.y;
+}
+
QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
QFixed subPixelPosition,
GlyphFormat format,
@@ -807,13 +819,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
{
// Q_ASSERT(freetype->lock == 1);
- if (format == Format_None) {
- if (defaultFormat != Format_None) {
- format = defaultFormat;
- } else {
- format = Format_Mono;
- }
- }
+ if (format == Format_None)
+ format = defaultFormat != Format_None ? defaultFormat : Format_Mono;
+ Q_ASSERT(format != Format_None);
Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0;
if (g && g->format == format && (fetchMetricsOnly || g->data))
@@ -822,32 +830,28 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
if (!g && set && set->isGlyphMissing(glyph))
return &emptyGlyph;
- QFontEngineFT::GlyphInfo info;
- Q_ASSERT(format != Format_None);
+ FT_Face face = freetype->face;
+
+ FT_Matrix matrix = freetype->matrix;
+
+ FT_Vector v;
+ v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.value());
+ v.y = 0;
+ FT_Set_Transform(face, &matrix, &v);
+
bool hsubpixel = false;
int vfactor = 1;
int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
- if (format != Format_Mono && !embeddedbitmap)
- load_flags |= FT_LOAD_NO_BITMAP;
-
- FT_Matrix matrix = freetype->matrix;
bool transform = matrix.xx != 0x10000
|| matrix.yy != 0x10000
|| matrix.xy != 0
|| matrix.yx != 0;
- if (transform)
+ if (transform || (format != Format_Mono && !embeddedbitmap))
load_flags |= FT_LOAD_NO_BITMAP;
- FT_Face face = freetype->face;
-
- FT_Vector v;
- v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.toReal() * 64);
- v.y = 0;
- FT_Set_Transform(face, &freetype->matrix, &v);
-
FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
load_flags &= ~FT_LOAD_NO_BITMAP;
@@ -891,6 +895,8 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
FT_Matrix_Multiply(&m, &matrix);
}
+ GlyphInfo info;
+ info.linearAdvance = slot->linearHoriAdvance >> 10;
info.xOff = TRUNC(ROUND(slot->advance.x));
info.yOff = 0;
@@ -899,27 +905,23 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
int right = CEIL(slot->metrics.horiBearingX + slot->metrics.width);
int top = CEIL(slot->metrics.horiBearingY);
int bottom = FLOOR(slot->metrics.horiBearingY - slot->metrics.height);
- int width = right-left;
- int height = top-bottom;
+ info.x = TRUNC(left);
+ info.y = TRUNC(top);
+ info.width = TRUNC(right - left);
+ info.height = TRUNC(top - bottom);
// If any of the metrics are too large to fit, don't cache them
- if (qAbs(info.xOff) >= 128
- || qAbs(TRUNC(top)) >= 128
- || TRUNC(width) >= 256
- || TRUNC(height) >= 256
- || qAbs(TRUNC(left)) >= 128
- || qAbs(TRUNC(ROUND(slot->advance.x))) >= 128) {
+ if (areMetricsTooLarge(info))
return 0;
- }
g = new Glyph;
g->data = 0;
- g->linearAdvance = slot->linearHoriAdvance >> 10;
- g->width = TRUNC(width);
- g->height = TRUNC(height);
- g->x = TRUNC(left);
- g->y = TRUNC(top);
- g->advance = TRUNC(ROUND(slot->advance.x));
+ g->linearAdvance = info.linearAdvance;
+ g->width = info.width;
+ g->height = info.height;
+ g->x = info.x;
+ g->y = info.y;
+ g->advance = info.xOff;
g->format = format;
if (set)
@@ -948,7 +950,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
info.height = slot->bitmap.rows / vfactor;
info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width;
- info.x = -slot->bitmap_left;
+ info.x = slot->bitmap_left;
info.y = slot->bitmap_top;
glyph_buffer_size = info.width * info.height * 4;
@@ -1013,23 +1015,16 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
hpixels = hpixels*3 + 8;
info.width = hpixels;
info.height = TRUNC(top - bottom);
- info.x = -TRUNC(left);
+ info.x = TRUNC(left);
info.y = TRUNC(top);
if (hsubpixel) {
info.width /= 3;
- info.x += 1;
+ info.x -= 1;
}
- bool large_glyph = (((short)(slot->linearHoriAdvance>>10) != slot->linearHoriAdvance>>10)
- || ((uchar)(info.width) != info.width)
- || ((uchar)(info.height) != info.height)
- || ((signed char)(info.x) != info.x)
- || ((signed char)(info.y) != info.y)
- || ((signed char)(info.xOff) != info.xOff));
-
- if (large_glyph) {
+ // If any of the metrics are too large to fit, don't cache them
+ if (areMetricsTooLarge(info))
return 0;
- }
int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 :
(format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
@@ -1142,10 +1137,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
g->data = 0;
}
- g->linearAdvance = slot->linearHoriAdvance >> 10;
+ g->linearAdvance = info.linearAdvance;
g->width = info.width;
g->height = info.height;
- g->x = -info.x;
+ g->x = info.x;
g->y = info.y;
g->advance = info.xOff;
g->format = format;
@@ -1725,100 +1720,60 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
return overall;
}
-QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition,
- QFontEngine::GlyphFormat neededFormat,
- const QTransform &t, QPoint *offset)
+static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEngine::GlyphFormat glyphFormat)
{
- Q_ASSERT(currentlyLockedAlphaMap.isNull());
- lockFace();
-
- if (isBitmapFont())
- neededFormat = Format_Mono;
- else if (neededFormat == Format_None && defaultFormat != Format_None)
- neededFormat = defaultFormat;
- else if (neededFormat == Format_None)
- neededFormat = Format_A8;
+ if (glyph == Q_NULLPTR)
+ return QImage();
QImage::Format format;
- switch (neededFormat) {
- case Format_Mono:
+ int bytesPerLine;
+ switch (glyphFormat) {
+ case QFontEngine::Format_Mono:
format = QImage::Format_Mono;
+ bytesPerLine = ((glyph->width + 31) & ~31) >> 3;
break;
- case Format_A8:
+ case QFontEngine::Format_A8:
format = QImage::Format_Alpha8;
+ bytesPerLine = (glyph->width + 3) & ~3;
break;
- case Format_A32:
+ case QFontEngine::Format_A32:
format = QImage::Format_ARGB32;
+ bytesPerLine = glyph->width * 4;
break;
default:
- Q_ASSERT(false);
- format = QImage::Format_Invalid;
+ Q_UNREACHABLE();
};
- QFontEngineFT::Glyph *glyph;
- if (cacheEnabled) {
- QGlyphSet *gset = loadGlyphSet(t);
- QFontEngine::HintStyle hintStyle = default_hint_style;
- if (t.type() >= QTransform::TxScale) {
- // disable hinting if the glyphs are transformed
- default_hint_style = HintNone;
- }
-
- if (gset) {
- FT_Matrix m = matrix;
- FT_Matrix_Multiply(&gset->transformationMatrix, &m);
- FT_Set_Transform(freetype->face, &m, 0);
- freetype->matrix = m;
- }
+ return QImage(static_cast<const uchar *>(glyph->data), glyph->width, glyph->height, bytesPerLine, format);
+}
- if (!gset || gset->outline_drawing || !(glyph = loadGlyph(gset, glyphIndex, subPixelPosition,
- neededFormat))) {
- default_hint_style = hintStyle;
- return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t,
- offset);
- }
- default_hint_style = hintStyle;
- } else {
- FT_Matrix m = matrix;
- FT_Matrix extra = QTransformToFTMatrix(t);
- FT_Matrix_Multiply(&extra, &m);
- FT_Set_Transform(freetype->face, &m, 0);
- freetype->matrix = m;
- glyph = loadGlyph(0, glyphIndex, subPixelPosition, neededFormat);
- }
+QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition,
+ QFontEngine::GlyphFormat neededFormat,
+ const QTransform &t, QPoint *offset)
+{
+ Q_ASSERT(currentlyLockedAlphaMap.isNull());
- if (glyph == 0 || glyph->data == 0 || glyph->width == 0 || glyph->height == 0) {
- if (!cacheEnabled && glyph != &emptyGlyph)
- delete glyph;
- unlockFace();
- return 0;
- }
+ if (isBitmapFont())
+ neededFormat = Format_Mono;
+ else if (neededFormat == Format_None && defaultFormat != Format_None)
+ neededFormat = defaultFormat;
+ else if (neededFormat == Format_None)
+ neededFormat = Format_A8;
- int pitch;
- switch (neededFormat) {
- case Format_Mono:
- pitch = ((glyph->width + 31) & ~31) >> 3;
- break;
- case Format_A8:
- pitch = (glyph->width + 3) & ~3;
- break;
- case Format_A32:
- pitch = glyph->width * 4;
- break;
- default:
- Q_ASSERT(false);
- pitch = 0;
- };
+ Glyph *glyph = loadGlyphFor(glyphIndex, subPixelPosition, neededFormat, t);
- if (offset != 0)
+ if (offset != 0 && glyph != 0)
*offset = QPoint(glyph->x, -glyph->y);
- currentlyLockedAlphaMap = QImage(glyph->data, glyph->width, glyph->height, pitch, format);
+ currentlyLockedAlphaMap = alphaMapFromGlyphData(glyph, neededFormat);
+
if (!cacheEnabled && glyph != &emptyGlyph) {
currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy();
delete glyph;
}
- Q_ASSERT(!currentlyLockedAlphaMap.isNull());
+
+ if (currentlyLockedAlphaMap.isNull())
+ return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t, offset);
QImageData *data = currentlyLockedAlphaMap.data_ptr();
data->is_locked = true;
@@ -1828,9 +1783,7 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
void QFontEngineFT::unlockAlphaMapForGlyph()
{
- Q_ASSERT(!currentlyLockedAlphaMap.isNull());
- unlockFace();
- currentlyLockedAlphaMap = QImage();
+ QFontEngine::unlockAlphaMapForGlyph();
}
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
@@ -1845,6 +1798,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
if (!glyph || glyph->format != format || (!fetchBoundingBox && !glyph->data)) {
+ QScopedValueRollback<HintStyle> saved_default_hint_style(default_hint_style);
+ if (t.type() >= QTransform::TxScale)
+ default_hint_style = HintNone; // disable hinting if the glyphs are transformed
+
lockFace();
FT_Matrix m = this->matrix;
FT_Matrix ftMatrix = glyphSet != 0 ? glyphSet->transformationMatrix : QTransformToFTMatrix(t);
@@ -1864,32 +1821,20 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
- Glyph *glyph = loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t);
- if (!glyph || !glyph->data) {
- if (!cacheEnabled && glyph != &emptyGlyph)
- delete glyph;
- return QFontEngine::alphaMapForGlyph(g);
- }
+ const GlyphFormat neededFormat = antialias ? Format_A8 : Format_Mono;
- const int pitch = antialias ? (glyph->width + 3) & ~3 : ((glyph->width + 31)/32) * 4;
+ Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t);
- QImage img(glyph->width, glyph->height, antialias ? QImage::Format_Alpha8 : QImage::Format_Mono);
- if (!antialias) {
- QVector<QRgb> colors(2);
- colors[0] = qRgba(0, 0, 0, 0);
- colors[1] = qRgba(0, 0, 0, 255);
- img.setColorTable(colors);
- }
- Q_ASSERT(img.bytesPerLine() == pitch);
- if (glyph->width) {
- for (int y = 0; y < glyph->height; ++y)
- memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch);
- }
+ QImage img = alphaMapFromGlyphData(glyph, neededFormat);
+ img = img.copy();
if (!cacheEnabled && glyph != &emptyGlyph)
delete glyph;
- return img;
+ if (!img.isNull())
+ return img;
+
+ return QFontEngine::alphaMapForGlyph(g);
}
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
@@ -1897,20 +1842,20 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co
if (t.type() > QTransform::TxRotate)
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
- Glyph *glyph = loadGlyphFor(g, subPixelPosition, Format_A32, t);
- if (!glyph || !glyph->data) {
- if (!cacheEnabled && glyph != &emptyGlyph)
- delete glyph;
- return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
- }
+ const GlyphFormat neededFormat = Format_A32;
- QImage img(glyph->width, glyph->height, QImage::Format_RGB32);
- memcpy(img.bits(), glyph->data, 4 * glyph->width * glyph->height);
+ Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t);
+
+ QImage img = alphaMapFromGlyphData(glyph, neededFormat);
+ img = img.copy();
if (!cacheEnabled && glyph != &emptyGlyph)
delete glyph;
- return img;
+ if (!img.isNull())
+ return img;
+
+ return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
}
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index e9d058d50c..7b28a4064f 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -143,6 +143,7 @@ public:
};
struct GlyphInfo {
+ int linearAdvance;
unsigned short width;
unsigned short height;
short x;
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 4baf1fd03c..102c62ea8a 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -94,6 +94,8 @@ static const hb_script_t _qtscript_to_hbscript[] = {
HB_SCRIPT_BUHID,
HB_SCRIPT_TAGBANWA,
HB_SCRIPT_COPTIC,
+
+ // Unicode 4.0 additions
HB_SCRIPT_LIMBU,
HB_SCRIPT_TAI_LE,
HB_SCRIPT_LINEAR_B,
@@ -102,6 +104,8 @@ static const hb_script_t _qtscript_to_hbscript[] = {
HB_SCRIPT_OSMANYA,
HB_SCRIPT_CYPRIOT,
HB_SCRIPT_BRAILLE,
+
+ // Unicode 4.1 additions
HB_SCRIPT_BUGINESE,
HB_SCRIPT_NEW_TAI_LUE,
HB_SCRIPT_GLAGOLITIC,
@@ -109,11 +113,15 @@ static const hb_script_t _qtscript_to_hbscript[] = {
HB_SCRIPT_SYLOTI_NAGRI,
HB_SCRIPT_OLD_PERSIAN,
HB_SCRIPT_KHAROSHTHI,
+
+ // Unicode 5.0 additions
HB_SCRIPT_BALINESE,
HB_SCRIPT_CUNEIFORM,
HB_SCRIPT_PHOENICIAN,
HB_SCRIPT_PHAGS_PA,
HB_SCRIPT_NKO,
+
+ // Unicode 5.1 additions
HB_SCRIPT_SUNDANESE,
HB_SCRIPT_LEPCHA,
HB_SCRIPT_OL_CHIKI,
@@ -125,6 +133,8 @@ static const hb_script_t _qtscript_to_hbscript[] = {
HB_SCRIPT_CARIAN,
HB_SCRIPT_LYDIAN,
HB_SCRIPT_CHAM,
+
+ // Unicode 5.2 additions
HB_SCRIPT_TAI_THAM,
HB_SCRIPT_TAI_VIET,
HB_SCRIPT_AVESTAN,
@@ -140,16 +150,45 @@ static const hb_script_t _qtscript_to_hbscript[] = {
HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
HB_SCRIPT_OLD_TURKIC,
HB_SCRIPT_KAITHI,
+
+ // Unicode 6.0 additions
HB_SCRIPT_BATAK,
HB_SCRIPT_BRAHMI,
HB_SCRIPT_MANDAIC,
+
+ // Unicode 6.1 additions
HB_SCRIPT_CHAKMA,
HB_SCRIPT_MEROITIC_CURSIVE,
HB_SCRIPT_MEROITIC_HIEROGLYPHS,
HB_SCRIPT_MIAO,
HB_SCRIPT_SHARADA,
HB_SCRIPT_SORA_SOMPENG,
- HB_SCRIPT_TAKRI
+ HB_SCRIPT_TAKRI,
+
+ // Unicode 7.0 additions
+ HB_SCRIPT_CAUCASIAN_ALBANIAN,
+ HB_SCRIPT_BASSA_VAH,
+ HB_SCRIPT_DUPLOYAN,
+ HB_SCRIPT_ELBASAN,
+ HB_SCRIPT_GRANTHA,
+ HB_SCRIPT_PAHAWH_HMONG,
+ HB_SCRIPT_KHOJKI,
+ HB_SCRIPT_LINEAR_A,
+ HB_SCRIPT_MAHAJANI,
+ HB_SCRIPT_MANICHAEAN,
+ HB_SCRIPT_MENDE_KIKAKUI,
+ HB_SCRIPT_MODI,
+ HB_SCRIPT_MRO,
+ HB_SCRIPT_OLD_NORTH_ARABIAN,
+ HB_SCRIPT_NABATAEAN,
+ HB_SCRIPT_PALMYRENE,
+ HB_SCRIPT_PAU_CIN_HAU,
+ HB_SCRIPT_OLD_PERMIC,
+ HB_SCRIPT_PSALTER_PAHLAVI,
+ HB_SCRIPT_SIDDHAM,
+ HB_SCRIPT_KHUDAWADI,
+ HB_SCRIPT_TIRHUTA,
+ HB_SCRIPT_WARANG_CITI
};
Q_STATIC_ASSERT(QChar::ScriptCount == sizeof(_qtscript_to_hbscript) / sizeof(_qtscript_to_hbscript[0]));
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index 3c3000da4d..5fa43948aa 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -522,9 +522,11 @@ enum {
VietnameseCsbBit = 8,
SimplifiedChineseCsbBit = 18,
TraditionalChineseCsbBit = 20,
+ ThaiCsbBit = 16,
JapaneseCsbBit = 17,
KoreanCsbBit = 19,
- KoreanJohabCsbBit = 21
+ KoreanJohabCsbBit = 21,
+ SymbolCsbBit = 31
};
/*!
@@ -579,6 +581,11 @@ QSupportedWritingSystems QPlatformFontDatabase::writingSystemsFromTrueTypeBits(q
hasScript = true;
//qDebug("font %s supports Arabic", familyName.latin1());
}
+ if (codePageRange[0] & (1 << ThaiCsbBit)) {
+ writingSystems.setSupported(QFontDatabase::Thai);
+ hasScript = true;
+ //qDebug("font %s supports Thai", familyName.latin1());
+ }
if (codePageRange[0] & (1 << VietnameseCsbBit)) {
writingSystems.setSupported(QFontDatabase::Vietnamese);
hasScript = true;
@@ -604,6 +611,11 @@ QSupportedWritingSystems QPlatformFontDatabase::writingSystemsFromTrueTypeBits(q
hasScript = true;
//qDebug("font %s supports Korean", familyName.latin1());
}
+ if (codePageRange[0] & (1 << SymbolCsbBit)) {
+ writingSystems = QSupportedWritingSystems();
+ hasScript = false;
+ }
+
if (!hasScript)
writingSystems.setSupported(QFontDatabase::Symbol);
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 3a86a454ac..db8a792be7 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2432,7 +2432,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
++it;
} else {
QTextFrame::Iterator lastIt;
- if (!previousIt.atEnd())
+ if (!previousIt.atEnd() && previousIt != it)
lastIt = previousIt;
previousIt = it;
QTextBlock block = it.currentBlock();
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 076b6bbde4..10a61d3c84 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -881,16 +881,22 @@ static inline void qt_getJustificationOpportunities(const ushort *string, int le
int spaceAs;
switch (si.analysis.script) {
+ case QChar::Script_Arabic:
+ case QChar::Script_Syriac:
case QChar::Script_Nko:
case QChar::Script_Mandaic:
case QChar::Script_Mongolian:
case QChar::Script_PhagsPa:
+ case QChar::Script_Manichaean:
+ case QChar::Script_PsalterPahlavi:
// same as default but inter character justification takes precedence
spaceAs = Justification_Arabic_Space;
break;
+ case QChar::Script_Tibetan:
case QChar::Script_Hiragana:
case QChar::Script_Katakana:
+ case QChar::Script_Bopomofo:
case QChar::Script_Han:
// same as default but inter character justification is the only option
spaceAs = Justification_Character;
@@ -1201,20 +1207,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
uint cluster = infos->cluster;
if (Q_LIKELY(last_cluster != cluster)) {
- if (Q_UNLIKELY(g.glyphs[i] == 0)) {
- // hide characters that should normally be invisible
- switch (string[item_pos + str_pos]) {
- case QChar::LineFeed:
- case 0x000c: // FormFeed
- case QChar::CarriageReturn:
- case QChar::LineSeparator:
- case QChar::ParagraphSeparator:
- g.attributes[i].dontPrint = true;
- break;
- default:
- break;
- }
- }
+ g.attributes[i].clusterStart = true;
// fix up clusters so that the cluster indices will be monotonic
// and thus we never return out-of-order indices
@@ -1222,7 +1215,32 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
log_clusters[str_pos++] = last_glyph_pos;
last_glyph_pos = i + glyphs_shaped;
last_cluster = cluster;
- g.attributes[i].clusterStart = true;
+
+ // hide characters that should normally be invisible
+ switch (string[item_pos + str_pos]) {
+ case QChar::LineFeed:
+ case 0x000c: // FormFeed
+ case QChar::CarriageReturn:
+ case QChar::LineSeparator:
+ case QChar::ParagraphSeparator:
+ g.attributes[i].dontPrint = true;
+ break;
+ case QChar::SoftHyphen:
+ if (!actualFontEngine->symbol) {
+ // U+00AD [SOFT HYPHEN] is a default ignorable codepoint,
+ // so we replace its glyph and metrics with ones for
+ // U+002D [HYPHEN-MINUS] and make it visible if it appears at line-break
+ g.glyphs[i] = actualFontEngine->glyphIndex('-');
+ if (Q_LIKELY(g.glyphs[i] != 0)) {
+ QGlyphLayout tmp = g.mid(i, 1);
+ actualFontEngine->recalcAdvances(&tmp, 0);
+ }
+ g.attributes[i].dontPrint = true;
+ }
+ break;
+ default:
+ break;
+ }
}
}
while (str_pos < item_length)
@@ -1618,10 +1636,10 @@ void QTextEngine::itemize() const
for (int i = 0; i < length; ++i) {
switch (analysis[i].script) {
case QChar::Script_Latin:
- case QChar::Script_Han:
case QChar::Script_Hiragana:
case QChar::Script_Katakana:
case QChar::Script_Bopomofo:
+ case QChar::Script_Han:
analysis[i].script = QChar::Script_Common;
break;
default:
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index efd12b2b15..c60d0cc775 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -3458,14 +3458,16 @@ void QTextFormatCollection::setDefaultFont(const QFont &f)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QTextLength &l)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QTextLength(QTextLength::Type(" << l.type() << "))";
- return dbg.space();
+ return dbg;
}
QDebug operator<<(QDebug dbg, const QTextFormat &f)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QTextFormat(QTextFormat::FormatType(" << f.type() << "))";
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index edace3d13c..f8f41bb53d 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1050,25 +1050,14 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
// set element specific attributes
switch (id) {
case Html_a:
- charFormat.setAnchor(true);
for (int i = 0; i < attributes.count(); i += 2) {
const QString key = attributes.at(i);
if (key.compare(QLatin1String("href"), Qt::CaseInsensitive) == 0
&& !attributes.at(i + 1).isEmpty()) {
hasHref = true;
- charFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
- charFormat.setForeground(QGuiApplication::palette().link());
}
}
-
- break;
- case Html_em:
- case Html_i:
- case Html_cite:
- case Html_address:
- case Html_var:
- case Html_dfn:
- charFormat.setFontItalic(true);
+ charFormat.setAnchor(true);
break;
case Html_big:
charFormat.setProperty(QTextFormat::FontSizeAdjustment, int(1));
@@ -1076,36 +1065,27 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
case Html_small:
charFormat.setProperty(QTextFormat::FontSizeAdjustment, int(-1));
break;
- case Html_strong:
- case Html_b:
- charFormat.setFontWeight(QFont::Bold);
- break;
case Html_h1:
- charFormat.setFontWeight(QFont::Bold);
charFormat.setProperty(QTextFormat::FontSizeAdjustment, int(3));
margin[QTextHtmlParser::MarginTop] = 18;
margin[QTextHtmlParser::MarginBottom] = 12;
break;
case Html_h2:
- charFormat.setFontWeight(QFont::Bold);
charFormat.setProperty(QTextFormat::FontSizeAdjustment, int(2));
margin[QTextHtmlParser::MarginTop] = 16;
margin[QTextHtmlParser::MarginBottom] = 12;
break;
case Html_h3:
- charFormat.setFontWeight(QFont::Bold);
charFormat.setProperty(QTextFormat::FontSizeAdjustment, int(1));
margin[QTextHtmlParser::MarginTop] = 14;
margin[QTextHtmlParser::MarginBottom] = 12;
break;
case Html_h4:
- charFormat.setFontWeight(QFont::Bold);
charFormat.setProperty(QTextFormat::FontSizeAdjustment, int(0));
margin[QTextHtmlParser::MarginTop] = 12;
margin[QTextHtmlParser::MarginBottom] = 12;
break;
case Html_h5:
- charFormat.setFontWeight(QFont::Bold);
charFormat.setProperty(QTextFormat::FontSizeAdjustment, int(-1));
margin[QTextHtmlParser::MarginTop] = 12;
margin[QTextHtmlParser::MarginBottom] = 4;
@@ -1114,11 +1094,7 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
margin[QTextHtmlParser::MarginTop] = 12;
margin[QTextHtmlParser::MarginBottom] = 12;
break;
- case Html_center:
- blockFormat.setAlignment(Qt::AlignCenter);
- break;
case Html_ul:
- listStyle = QTextListFormat::ListDisc;
// nested lists don't have margins, except for the toplevel one
if (!isNestedList(parser)) {
margin[QTextHtmlParser::MarginTop] = 12;
@@ -1127,7 +1103,6 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
// no left margin as we use indenting instead
break;
case Html_ol:
- listStyle = QTextListFormat::ListDecimal;
// nested lists don't have margins, except for the toplevel one
if (!isNestedList(parser)) {
margin[QTextHtmlParser::MarginTop] = 12;
@@ -1135,26 +1110,12 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
}
// no left margin as we use indenting instead
break;
- case Html_code:
- case Html_tt:
- case Html_kbd:
- case Html_samp:
- charFormat.setFontFamily(QString::fromLatin1("Courier New,courier"));
- // <tt> uses a fixed font, so set the property
- charFormat.setFontFixedPitch(true);
- break;
case Html_br:
text = QChar(QChar::LineSeparator);
- wsm = QTextHtmlParserNode::WhiteSpacePre;
break;
- // ##### sub / sup
case Html_pre:
- charFormat.setFontFamily(QString::fromLatin1("Courier New,courier"));
- wsm = WhiteSpacePre;
margin[QTextHtmlParser::MarginTop] = 12;
margin[QTextHtmlParser::MarginBottom] = 12;
- // <pre> uses a fixed font
- charFormat.setFontFixedPitch(true);
break;
case Html_blockquote:
margin[QTextHtmlParser::MarginTop] = 12;
@@ -1169,28 +1130,6 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
case Html_dd:
margin[QTextHtmlParser::MarginLeft] = 30;
break;
- case Html_u:
- charFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
- break;
- case Html_s:
- charFormat.setFontStrikeOut(true);
- break;
- case Html_nobr:
- wsm = WhiteSpaceNoWrap;
- break;
- case Html_th:
- charFormat.setFontWeight(QFont::Bold);
- blockFormat.setAlignment(Qt::AlignCenter);
- break;
- case Html_td:
- blockFormat.setAlignment(Qt::AlignLeft);
- break;
- case Html_sub:
- charFormat.setVerticalAlignment(QTextCharFormat::AlignSubScript);
- break;
- case Html_sup:
- charFormat.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
- break;
default: break;
}
}
@@ -1345,6 +1284,14 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::QtListNumberSuffix:
textListNumberSuffix = decl.d->values.first().variant.toString();
break;
+ case QCss::TextAlignment:
+ switch (identifier) {
+ case QCss::Value_Left: blockFormat.setAlignment(Qt::AlignLeft); break;
+ case QCss::Value_Center: blockFormat.setAlignment(Qt::AlignCenter); break;
+ case QCss::Value_Right: blockFormat.setAlignment(Qt::AlignRight); break;
+ default: break;
+ }
+ break;
default: break;
}
}
@@ -1833,6 +1780,189 @@ void QTextHtmlParser::importStyleSheet(const QString &href)
}
}
+QVector<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &node)
+{
+ QVector<QCss::Declaration> decls;
+ QCss::Declaration decl;
+ QCss::Value val;
+ switch (node.id) {
+ case Html_a:
+ case Html_u: {
+ bool needsUnderline = (node.id == Html_u) ? true : false;
+ if (node.id == Html_a) {
+ for (int i = 0; i < node.attributes.count(); i += 2) {
+ const QString key = node.attributes.at(i);
+ if (key.compare(QLatin1String("href"), Qt::CaseInsensitive) == 0
+ && !node.attributes.at(i + 1).isEmpty()) {
+ needsUnderline = true;
+ decl.d->property = QLatin1String("color");
+ decl.d->propertyId = QCss::Color;
+ val.type = QCss::Value::Color;
+ val.variant = QVariant(QGuiApplication::palette().link());
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ break;
+ }
+ }
+ }
+ if (needsUnderline) {
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("text-decoration");
+ decl.d->propertyId = QCss::TextDecoration;
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = QVariant(QCss::Value_Underline);
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ }
+ break;
+ }
+ case Html_b:
+ case Html_strong:
+ case Html_h1:
+ case Html_h2:
+ case Html_h3:
+ case Html_h4:
+ case Html_h5:
+ case Html_th:
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("font-weight");
+ decl.d->propertyId = QCss::FontWeight;
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = QVariant(QCss::Value_Bold);
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ if (node.id == Html_b || node.id == Html_strong)
+ break;
+ // Delibrate fall through
+ case Html_big:
+ case Html_small:
+ if (node.id != Html_th) {
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("font-size");
+ decl.d->propertyId = QCss::FontSize;
+ decl.d->inheritable = false;
+ val.type = QCss::Value::KnownIdentifier;
+ switch (node.id) {
+ case Html_h1: val.variant = QVariant(QCss::Value_XXLarge); break;
+ case Html_h2: val.variant = QVariant(QCss::Value_XLarge); break;
+ case Html_h3: case Html_big: val.variant = QVariant(QCss::Value_Large); break;
+ case Html_h4: val.variant = QVariant(QCss::Value_Medium); break;
+ case Html_h5: case Html_small: val.variant = QVariant(QCss::Value_Small); break;
+ default: break;
+ }
+ decl.d->values = QVector<QCss::Value>() << val;
+ decls << decl;
+ break;
+ }
+ // Delibrate fall through
+ case Html_center:
+ case Html_td:
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("text-align");
+ decl.d->propertyId = QCss::TextAlignment;
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = (node.id == Html_td) ? QVariant(QCss::Value_Left) : QVariant(QCss::Value_Center);
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ break;
+ case Html_s:
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("text-decoration");
+ decl.d->propertyId = QCss::TextDecoration;
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = QVariant(QCss::Value_LineThrough);
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ break;
+ case Html_em:
+ case Html_i:
+ case Html_cite:
+ case Html_address:
+ case Html_var:
+ case Html_dfn:
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("font-style");
+ decl.d->propertyId = QCss::FontStyle;
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = QVariant(QCss::Value_Italic);
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ break;
+ case Html_sub:
+ case Html_sup:
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("vertical-align");
+ decl.d->propertyId = QCss::VerticalAlignment;
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = (node.id == Html_sub) ? QVariant(QCss::Value_Sub) : QVariant(QCss::Value_Super);
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ break;
+ case Html_ul:
+ case Html_ol:
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("list-style");
+ decl.d->propertyId = QCss::ListStyle;
+ val.type = QCss::Value::KnownIdentifier;
+ val.variant = (node.id == Html_ul) ? QVariant(QCss::Value_Disc) : QVariant(QCss::Value_Decimal);
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ break;
+ case Html_code:
+ case Html_tt:
+ case Html_kbd:
+ case Html_samp:
+ case Html_pre: {
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("font-family");
+ decl.d->propertyId = QCss::FontFamily;
+ QVector<QCss::Value> values;
+ val.type = QCss::Value::String;
+ val.variant = QLatin1String("Courier New");
+ values << val;
+ val.type = QCss::Value::TermOperatorComma;
+ val.variant = QVariant();
+ values << val;
+ val.type = QCss::Value::String;
+ val.variant = QLatin1String("courier");
+ values << val;
+ decl.d->values = values;
+ decl.d->inheritable = true;
+ decls << decl;
+ }
+ if (node.id != Html_pre)
+ break;
+ // Delibrate fall through
+ case Html_br:
+ case Html_nobr:
+ decl = QCss::Declaration();
+ decl.d->property = QLatin1String("whitespace");
+ decl.d->propertyId = QCss::Whitespace;
+ val.type = QCss::Value::KnownIdentifier;
+ switch (node.id) {
+ case Html_br: val.variant = QVariant(QCss::Value_PreWrap); break;
+ case Html_nobr: val.variant = QVariant(QCss::Value_NoWrap); break;
+ case Html_pre: val.variant = QVariant(QCss::Value_Pre); break;
+ default: break;
+ }
+ decl.d->values = QVector<QCss::Value>() << val;
+ decl.d->inheritable = true;
+ decls << decl;
+ break;
+ default:
+ break;
+ }
+ return decls;
+}
+
QVector<QCss::Declaration> QTextHtmlParser::declarationsForNode(int node) const
{
QVector<QCss::Declaration> decls;
@@ -1860,8 +1990,20 @@ QVector<QCss::Declaration> QTextHtmlParser::declarationsForNode(int node) const
const char *extraPseudo = 0;
if (nodes.at(node).id == Html_a && nodes.at(node).hasHref)
extraPseudo = "link";
- decls = selector.declarationsForNode(n, extraPseudo);
-
+ // Ensure that our own style is taken into consideration
+ decls = standardDeclarationForNode(nodes.at(node));
+ decls += selector.declarationsForNode(n, extraPseudo);
+ n = selector.parentNode(n);
+ while (!selector.isNullNode(n)) {
+ QVector<QCss::Declaration> inheritedDecls;
+ inheritedDecls = selector.declarationsForNode(n, extraPseudo);
+ for (int i = 0; i < inheritedDecls.size(); ++i) {
+ const QCss::Declaration &decl = inheritedDecls.at(i);
+ if (decl.d->inheritable)
+ decls.prepend(decl);
+ }
+ n = selector.parentNode(n);
+ }
return decls;
}
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 385706f09e..4c92e5d000 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -166,6 +166,11 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
Unicode-aware, the user may have configured their client without these features.
Also, certain e-mail clients (e.g., Lotus Notes) have problems with long URLs.
+ \warning A return value of \c true indicates that the application has successfully requested
+ the operating system to open the URL in an external application. The external application may
+ still fail to launch or fail to open the requested URL. This result will not be reported back
+ to the application.
+
\sa setUrlHandler()
*/
bool QDesktopServices::openUrl(const QUrl &url)
@@ -185,7 +190,12 @@ bool QDesktopServices::openUrl(const QUrl &url)
}
if (!url.isValid())
return false;
- QPlatformServices *platformServices = QGuiApplicationPrivate::platformIntegration()->services();
+
+ QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ if (!platformIntegration)
+ return false;
+
+ QPlatformServices *platformServices = platformIntegration->services();
if (!platformServices) {
qWarning("%s: The platform plugin does not support services.", Q_FUNC_INFO);
return false;
diff --git a/src/gui/util/qlayoutpolicy.cpp b/src/gui/util/qlayoutpolicy.cpp
index f1900122ac..0a050184a6 100644
--- a/src/gui/util/qlayoutpolicy.cpp
+++ b/src/gui/util/qlayoutpolicy.cpp
@@ -119,9 +119,10 @@ QDataStream &operator>>(QDataStream &stream, QLayoutPolicy &policy)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QLayoutPolicy &p)
{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QLayoutPolicy(horizontalPolicy = " << p.horizontalPolicy()
<< ", verticalPolicy = " << p.verticalPolicy() << ')';
- return dbg.space();
+ return dbg;
}
#endif