diff options
27 files changed, 859 insertions, 780 deletions
diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 28d4ed4..2fd6fa8 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -423,22 +423,14 @@ signals with the \l {Connections} element. Additionally, if a property is added to a C++ class, all QML elements based on that C++ class will have a \e{value-changed} signal handler -for that property. The name of the signal handler is \e{on<Property -name>Changed}, with the first letter of the property name being upper -cased. - -\note If the NOTIFY signal for the added property is not simply -\c{<property_name>Changed()}, then you will get two equivalent signal -handlers, one because of the signal, one because of the property. For -example, if the property \c{test_property} with NOTIFY signal -\c{testPropChanged()} is added to a C++ class, then QML elements based -on that C++ class will have two signal handlers: -\c{onTest_propertyChanged} because of the property, and -\c{onTestPropChanged} because of the NOTIFY signal. For clarity, we -suggest that for properties exposed to QML in this way, the name of -the NOTIFY signal should be just \c{<property_name>Changed()}, so that -there will be just one signal handler in QML and one naming -convention used. +for that property. The name of the signal handler is +\e{on<Property-name>Changed}, with the first letter of the property +name being upper case. + +\note The QML signal handler will always be named +on<Property-name>Changed, regardless of the name used for the NOTIFY +signal in C++. We recommend using <property-name>Changed() for the +NOTIFY signal in C++. See also \l {Extending types from QML}. diff --git a/doc/src/template/style/style.css b/doc/src/template/style/style.css index 299806b..184a832 100755 --- a/doc/src/template/style/style.css +++ b/doc/src/template/style/style.css @@ -18,6 +18,8 @@ fieldset, img { border: 0; + height:100%; + width:100% } address, caption, cite, code, dfn, em, strong, th, var, optgroup { @@ -756,6 +758,7 @@ pre { border: 1px solid #DDDDDD; + -moz-border-radius: 7px 7px 7px 7px; margin: 0 20px 10px 10px; padding: 20px 15px 20px 20px; overflow-x: auto; @@ -1023,6 +1026,7 @@ } h3.fn, span.fn { + -moz-border-radius:7px 7px 7px 7px; background-color: #F6F6F6; border-width: 1px; border-style: solid; @@ -1040,6 +1044,7 @@ border-width: 1px; border-style: solid; border-color: #E6E6E6; + -moz-border-radius: 7px 7px 7px 7px; width:100%; } @@ -1199,6 +1204,7 @@ vertical-align:top; width:100%; background-color:#F6F6F6; border:1px solid #E6E6E6; +-moz-border-radius: 7px 7px 7px 7px; font-size:12pt; padding-left:10px; margin-top:10px; @@ -1250,8 +1256,9 @@ pre.highlightedCode { } .navTop{ float:right; - padding-right:5px; - margin-top:15px; + display:block; + padding-right:15px; + /*margin-top:10px;*/ } .wrap .content .toc h3{ diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 8eba2b0..9bc4063 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1377,6 +1377,50 @@ void QProcess::setStandardOutputProcess(QProcess *destination) dto->stdinChannel.pipeFrom(dfrom); } +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + +/*! + \since 4.7 + + Returns the additional native command line arguments for the program. + + \note This function is available only on the Windows and Symbian + platforms. + + \sa setNativeArguments() +*/ +QString QProcess::nativeArguments() const +{ + Q_D(const QProcess); + return d->nativeArguments; +} + +/*! + \since 4.7 + \overload + + Sets additional native command line arguments for the program. + + On operating systems where the system API for passing command line + arguments to a subprocess natively uses a single string, one can + conceive command lines which cannot be passed via QProcess's portable + list-based API. In such cases this function must be used to set a + string which is \e appended to the string composed from the usual + argument list, with a delimiting space. + + \note This function is available only on the Windows and Symbian + platforms. + + \sa nativeArguments() +*/ +void QProcess::setNativeArguments(const QString &arguments) +{ + Q_D(QProcess); + d->nativeArguments = arguments; +} + +#endif + /*! If QProcess has been assigned a working directory, this function returns the working directory that the QProcess will enter before the program has @@ -2082,14 +2126,19 @@ QProcess::ExitStatus QProcess::exitStatus() const process. On Windows, arguments that contain spaces are wrapped in quotes. + + If the process cannot be started, -2 is returned. If the process + crashes, -1 is returned. Otherwise, the process' exit code is + returned. */ int QProcess::execute(const QString &program, const QStringList &arguments) { QProcess process; process.setReadChannelMode(ForwardedChannels); process.start(program, arguments); - process.waitForFinished(-1); - return process.exitCode(); + if (!process.waitForFinished(-1)) + return -2; + return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; } /*! @@ -2104,8 +2153,9 @@ int QProcess::execute(const QString &program) QProcess process; process.setReadChannelMode(ForwardedChannels); process.start(program); - process.waitForFinished(-1); - return process.exitCode(); + if (!process.waitForFinished(-1)) + return -2; + return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; } /*! diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index f84b855..b07d742 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -148,6 +148,11 @@ public: void setStandardErrorFile(const QString &fileName, OpenMode mode = Truncate); void setStandardOutputProcess(QProcess *destination); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QString nativeArguments() const; + void setNativeArguments(const QString &arguments); +#endif + QString workingDirectory() const; void setWorkingDirectory(const QString &dir); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 60b7b5a..8b7e3ff 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -181,6 +181,9 @@ public: QString program; QStringList arguments; +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QString nativeArguments; +#endif QProcessEnvironment environment; QRingBuffer outputReadBuffer; diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index 92212fe..af657b2 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -219,7 +219,8 @@ static bool qt_rprocess_running(RProcess *proc) return false; } -static void qt_create_symbian_commandline(const QStringList &arguments, QString &commandLine) +static void qt_create_symbian_commandline( + const QStringList &arguments, const QString &nativeArguments, QString &commandLine) { for (int i = 0; i < arguments.size(); ++i) { QString tmp = arguments.at(i); @@ -243,12 +244,14 @@ static void qt_create_symbian_commandline(const QStringList &arguments, QString } } - // Chop the extra trailing space if any arguments were appended - if (arguments.size()) + if (!nativeArguments.isEmpty()) + commandLine += nativeArguments; + else if (!commandLine.isEmpty()) // Chop the extra trailing space if any arguments were appended commandLine.chop(1); } -static TInt qt_create_symbian_process(RProcess **proc, const QString &programName, const QStringList &arguments) +static TInt qt_create_symbian_process(RProcess **proc, + const QString &programName, const QStringList &arguments, const QString &nativeArguments) { RProcess *newProc = NULL; newProc = new RProcess(); @@ -257,7 +260,7 @@ static TInt qt_create_symbian_process(RProcess **proc, const QString &programNam return KErrNoMemory; QString commandLine; - qt_create_symbian_commandline(arguments, commandLine); + qt_create_symbian_commandline(arguments, nativeArguments, commandLine); TPtrC program_ptr(reinterpret_cast<const TText*>(programName.constData())); TPtrC cmdline_ptr(reinterpret_cast<const TText*>(commandLine.constData())); @@ -794,7 +797,7 @@ void QProcessPrivate::startProcess() q, SLOT(_q_processDied())); } - TInt err = qt_create_symbian_process(&symbianProcess, program, arguments); + TInt err = qt_create_symbian_process(&symbianProcess, program, arguments, nativeArguments); if (err == KErrNone) { pid = symbianProcess->Id().Id(); @@ -1030,7 +1033,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a RProcess *newProc = NULL; - TInt err = qt_create_symbian_process(&newProc, program, arguments); + TInt err = qt_create_symbian_process(&newProc, program, arguments, QString()); if (err == KErrNone) { if (pid) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index cb25a58..702349f 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -366,6 +366,11 @@ void QProcessPrivate::startProcess() if (environment.d.constData()) envlist = qt_create_environment(environment.d.constData()->hash); #endif + if (!nativeArguments.isEmpty()) { + if (!args.isEmpty()) + args += QLatin1Char(' '); + args += nativeArguments; + } #if defined QPROCESS_DEBUG qDebug("Creating process"); diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 58d2dcb..0ed9d5d 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -58,8 +58,7 @@ QT_BEGIN_HEADER #endif // SSE intrinsics -#if defined(QT_HAVE_SSE2) && !defined(QT_BOOTSTRAPPED) && (defined(__SSE2__) \ - || (defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP == 2))) +#if defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC)) #if defined(QT_LINUXBASE) /// this is an evil hack - the posix_memalign declaration in LSB /// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431 @@ -73,8 +72,10 @@ QT_BEGIN_HEADER # include <emmintrin.h> #endif +#if !defined(QT_BOOTSTRAPPED) && (!defined(Q_CC_MSVC) || (defined(_M_X64) || _M_IX86_FP == 2)) #define QT_ALWAYS_HAVE_SSE2 #endif +#endif // defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC)) // NEON intrinsics #if defined(QT_HAVE_NEON) diff --git a/src/gui/gui.pro b/src/gui/gui.pro index dede9d0..41f1904 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -77,3 +77,129 @@ symbian { DEPLOYMENT = partial_upgrade $$DEPLOYMENT } +contains(QMAKE_MAC_XARCH, no) { + DEFINES += QT_NO_MAC_XARCH +} else { + mmx:DEFINES += QT_HAVE_MMX + 3dnow:DEFINES += QT_HAVE_3DNOW + sse:DEFINES += QT_HAVE_SSE QT_HAVE_MMXEXT + sse2:DEFINES += QT_HAVE_SSE2 + iwmmxt:DEFINES += QT_HAVE_IWMMXT + + win32-g++*|!win32:!*-icc* { + mmx { + mmx_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + mmx_compiler.commands += -Xarch_i386 -mmmx + mmx_compiler.commands += -Xarch_x86_64 -mmmx + } else { + mmx_compiler.commands += -mmmx + } + + mmx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + mmx_compiler.dependency_type = TYPE_C + mmx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + mmx_compiler.input = MMX_SOURCES + mmx_compiler.variable_out = OBJECTS + mmx_compiler.name = compiling[mmx] ${QMAKE_FILE_IN} + silent:mmx_compiler.commands = @echo compiling[mmx] ${QMAKE_FILE_IN} && $$mmx_compiler.commands + QMAKE_EXTRA_COMPILERS += mmx_compiler + } + 3dnow { + mmx3dnow_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + mmx3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -mmmx + mmx3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -mmmx + } else { + mmx3dnow_compiler.commands += -m3dnow -mmmx + } + + mmx3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + mmx3dnow_compiler.dependency_type = TYPE_C + mmx3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + mmx3dnow_compiler.input = MMX3DNOW_SOURCES + mmx3dnow_compiler.variable_out = OBJECTS + mmx3dnow_compiler.name = compiling[mmx3dnow] ${QMAKE_FILE_IN} + silent:mmx3dnow_compiler.commands = @echo compiling[mmx3dnow] ${QMAKE_FILE_IN} && $$mmx3dnow_compiler.commands + QMAKE_EXTRA_COMPILERS += mmx3dnow_compiler + sse { + sse3dnow_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + sse3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -msse + sse3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -msse + } else { + sse3dnow_compiler.commands += -m3dnow -msse + } + + sse3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + sse3dnow_compiler.dependency_type = TYPE_C + sse3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + sse3dnow_compiler.input = SSE3DNOW_SOURCES + sse3dnow_compiler.variable_out = OBJECTS + sse3dnow_compiler.name = compiling[sse3dnow] ${QMAKE_FILE_IN} + silent:sse3dnow_compiler.commands = @echo compiling[sse3dnow] ${QMAKE_FILE_IN} && $$sse3dnow_compiler.commands + QMAKE_EXTRA_COMPILERS += sse3dnow_compiler + } + } + sse { + sse_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + sse_compiler.commands += -Xarch_i386 -msse + sse_compiler.commands += -Xarch_x86_64 -msse + } else { + sse_compiler.commands += -msse + } + + sse_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + sse_compiler.dependency_type = TYPE_C + sse_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + sse_compiler.input = SSE_SOURCES + sse_compiler.variable_out = OBJECTS + sse_compiler.name = compiling[sse] ${QMAKE_FILE_IN} + silent:sse_compiler.commands = @echo compiling[sse] ${QMAKE_FILE_IN} && $$sse_compiler.commands + QMAKE_EXTRA_COMPILERS += sse_compiler + } + sse2 { + sse2_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + sse2_compiler.commands += -Xarch_i386 -msse2 + sse2_compiler.commands += -Xarch_x86_64 -msse2 + } else { + sse2_compiler.commands += -msse2 + } + + sse2_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + sse2_compiler.dependency_type = TYPE_C + sse2_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + sse2_compiler.input = SSE2_SOURCES + sse2_compiler.variable_out = OBJECTS + sse2_compiler.name = compiling[sse2] ${QMAKE_FILE_IN} + silent:sse2_compiler.commands = @echo compiling[sse2] ${QMAKE_FILE_IN} && $$sse2_compiler.commands + QMAKE_EXTRA_COMPILERS += sse2_compiler + } + iwmmxt { + iwmmxt_compiler.commands = $$QMAKE_CXX -c -Winline + iwmmxt_compiler.commands += -mcpu=iwmmxt + iwmmxt_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + iwmmxt_compiler.dependency_type = TYPE_C + iwmmxt_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + iwmmxt_compiler.input = IWMMXT_SOURCES + iwmmxt_compiler.variable_out = OBJECTS + iwmmxt_compiler.name = compiling[iwmmxt] ${QMAKE_FILE_IN} + silent:iwmmxt_compiler.commands = @echo compiling[iwmmxt] ${QMAKE_FILE_IN} && $$iwmmxt_compiler.commands + QMAKE_EXTRA_COMPILERS += iwmmxt_compiler + } + } else { + mmx: SOURCES += $$MMX_SOURCES + 3dnow: SOURCES += $$MMX3DNOW_SOURCES + 3dnow:sse: SOURCES += $$SSE3DNOW_SOURCES + sse: SOURCES += $$SSE_SOURCES + sse2: SOURCES += $$SSE2_SOURCES + iwmmxt: SOURCES += $$IWMMXT_SOURCES + } +} diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 9f0c87e..3a02d56 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -92,3 +92,6 @@ contains(QT_CONFIG, jpeg):include($$PWD/qjpeghandler.pri) contains(QT_CONFIG, mng):include($$PWD/qmnghandler.pri) contains(QT_CONFIG, tiff):include($$PWD/qtiffhandler.pri) contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri) + +# SIMD +SSE2_SOURCES += image/qimage_sse2.cpp diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 79f266d..e5930ac 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -58,6 +58,7 @@ #include <private/qmemrotate_p.h> #include <private/qpixmapdata_p.h> #include <private/qimagescale_p.h> +#include <private/qsimd_p.h> #include <qhash.h> @@ -209,7 +210,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu break; } - const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 8) + const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4) // sanity check for potential overflows if (INT_MAX/depth < width @@ -3630,7 +3631,7 @@ static const Image_Converter converter_map[QImage::NImageFormats][QImage::NImage } // Format_ARGB4444_Premultiplied }; -static const InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] = +static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -3727,6 +3728,19 @@ static const InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats } // Format_ARGB4444_Premultiplied }; +void qInitImageConversions() +{ + const uint features = qDetectCPUFeatures(); + Q_UNUSED(features); + +#ifdef QT_HAVE_SSE2 + if (features & SSE2) { + extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); + inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2; + } +#endif +} + /*! Returns a copy of the image in the given \a format. diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index f1a0c47..da535aa 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -61,6 +61,8 @@ #include <QMap> #endif +class QImageWriter; + QT_BEGIN_NAMESPACE struct Q_GUI_EXPORT QImageData { // internal image data @@ -108,6 +110,8 @@ struct Q_GUI_EXPORT QImageData { // internal image data QPaintEngine *paintEngine; }; +void qInitImageConversions(); + QT_END_NAMESPACE #endif diff --git a/src/gui/image/qimage_sse2.cpp b/src/gui/image/qimage_sse2.cpp new file mode 100644 index 0000000..82d49a6 --- /dev/null +++ b/src/gui/image/qimage_sse2.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qimage.h" +#include <private/qimage_p.h> +#include <private/qsimd_p.h> +#include <private/qdrawhelper_p.h> +#include <private/qdrawingprimitive_sse2_p.h> + +#ifdef QT_HAVE_SSE2 + +QT_BEGIN_NAMESPACE + +bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_ARGB32); + + // extra pixels on each line + const int spare = data->width & 3; + // width in pixels of the pad at the end of each line + const int pad = (data->bytes_per_line >> 2) - data->width; + const int iter = data->width >> 2; + int height = data->height; + + const __m128i alphaMask = _mm_set1_epi32(0xff000000); + const __m128i nullVector = _mm_setzero_si128(); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + __m128i *d = reinterpret_cast<__m128i*>(data->data); + while (height--) { + const __m128i *end = d + iter; + + for (; d != end; ++d) { + const __m128i srcVector = _mm_loadu_si128(d); + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { + // opaque, data is unchanged + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) == 0xffff) { + // fully transparent + _mm_storeu_si128(d, nullVector); + } else { + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); + + __m128i result; + BYTE_MUL_SSE2(result, srcVector, alphaChannel, colorMask, half); + result = _mm_or_si128(_mm_andnot_si128(alphaMask, result), srcVectorAlpha); + _mm_storeu_si128(d, result); + } + } + + QRgb *p = reinterpret_cast<QRgb*>(d); + QRgb *pe = p+spare; + for (; p != pe; ++p) { + if (*p < 0x00ffffff) + *p = 0; + else if (*p < 0xff000000) + *p = PREMUL(*p); + } + + d = reinterpret_cast<__m128i*>(p+pad); + } + + data->format = QImage::Format_ARGB32_Premultiplied; + return true; +} + +QT_END_NAMESPACE + +#endif // QT_HAVE_SSE2 diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index ccfe88c..94211fd 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -902,6 +902,7 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, #endif // Q_WS_X11 extern void qInitDrawhelperAsm(); +extern void qInitImageConversions(); extern int qRegisterGuiVariant(); extern int qUnregisterGuiVariant(); #ifndef QT_NO_STATEMACHINE @@ -959,6 +960,8 @@ void QApplicationPrivate::initialize() // Set up which span functions should be used in raster engine... qInitDrawhelperAsm(); + // and QImage conversion functions + qInitImageConversions(); #ifndef QT_NO_WHEELEVENT QApplicationPrivate::wheel_scroll_lines = 3; diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index 8a3e89e..62d8a53 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -45,6 +45,7 @@ #include "qevent.h" #include "qwidget.h" #include "qabstractscrollarea.h" +#include <qgraphicssceneevent.h> #include "qdebug.h" #ifndef QT_NO_GESTURES @@ -509,49 +510,65 @@ QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, if (object == state && event->type() == QEvent::Timer) { q->killTimer(d->timerId); d->timerId = 0; - return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; + return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; } const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); - - QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; + const QMouseEvent *me = static_cast<const QMouseEvent *>(event); + const QGraphicsSceneMouseEvent *gsme = static_cast<const QGraphicsSceneMouseEvent *>(event); enum { TimerInterval = 2000 }; enum { TapRadius = 40 }; switch (event->type()) { + case QEvent::GraphicsSceneMousePress: + d->position = gsme->screenPos(); + q->setHotSpot(d->position); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = q->startTimer(TimerInterval); + return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout + case QEvent::MouseButtonPress: + d->position = me->globalPos(); + q->setHotSpot(d->position); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = q->startTimer(TimerInterval); + return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout case QEvent::TouchBegin: - d->position = ev->touchPoints().at(0).pos(); + d->position = ev->touchPoints().at(0).startScreenPos(); + q->setHotSpot(d->position); if (d->timerId) q->killTimer(d->timerId); d->timerId = q->startTimer(TimerInterval); - q->setHotSpot(ev->touchPoints().at(0).startScreenPos()); - result = QGestureRecognizer::TriggerGesture; - break; + return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout + case QEvent::GraphicsSceneMouseRelease: + case QEvent::MouseButtonRelease: case QEvent::TouchEnd: - if (d->timerId) - result = QGestureRecognizer::CancelGesture; - else - result = QGestureRecognizer::FinishGesture; - break; + return QGestureRecognizer::CancelGesture; // get out of the MayBeGesture state case QEvent::TouchUpdate: - if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { + if (d->timerId && ev->touchPoints().size() == 1) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); if (delta.manhattanLength() <= TapRadius) - result = QGestureRecognizer::TriggerGesture; + return QGestureRecognizer::MayBeGesture; } - break; - case QEvent::MouseButtonPress: - case QEvent::MouseMove: - case QEvent::MouseButtonRelease: - result = QGestureRecognizer::Ignore; - break; + return QGestureRecognizer::CancelGesture; + case QEvent::MouseMove: { + QPoint delta = me->globalPos() - d->position.toPoint(); + if (d->timerId && delta.manhattanLength() <= TapRadius) + return QGestureRecognizer::MayBeGesture; + return QGestureRecognizer::CancelGesture; + } + case QEvent::GraphicsSceneMouseMove: { + QPoint delta = gsme->screenPos() - d->position.toPoint(); + if (d->timerId && delta.manhattanLength() <= TapRadius) + return QGestureRecognizer::MayBeGesture; + return QGestureRecognizer::CancelGesture; + } default: - result = QGestureRecognizer::Ignore; - break; + return QGestureRecognizer::Ignore; } - return result; } void QTapAndHoldGestureRecognizer::reset(QGesture *state) diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 07aabc9..4023f65 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -202,154 +202,17 @@ x11|embedded { DEFINES += QT_NO_CUPS QT_NO_LPR } -contains(QMAKE_MAC_XARCH, no) { - DEFINES += QT_NO_MAC_XARCH -} else:if(mmx|3dnow|sse|sse2|iwmmxt) { +if(mmx|3dnow|sse|sse2|iwmmxt) { HEADERS += painting/qdrawhelper_x86_p.h \ painting/qdrawhelper_mmx_p.h \ - painting/qdrawhelper_sse_p.h - mmx { - DEFINES += QT_HAVE_MMX - MMX_SOURCES += painting/qdrawhelper_mmx.cpp - } - 3dnow { - DEFINES += QT_HAVE_3DNOW - MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp - sse { - SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp - } - } - sse { - DEFINES += QT_HAVE_SSE - SSE_SOURCES += painting/qdrawhelper_sse.cpp - - DEFINES += QT_HAVE_MMXEXT - } - sse2 { - DEFINES += QT_HAVE_SSE2 - SSE2_SOURCES += painting/qdrawhelper_sse2.cpp - } - iwmmxt { - DEFINES += QT_HAVE_IWMMXT - IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp - } - - win32-g++*|!win32:!*-icc* { - mmx { - mmx_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - mmx_compiler.commands += -Xarch_i386 -mmmx - mmx_compiler.commands += -Xarch_x86_64 -mmmx - } else { - mmx_compiler.commands += -mmmx - } - - mmx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - mmx_compiler.dependency_type = TYPE_C - mmx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - mmx_compiler.input = MMX_SOURCES - mmx_compiler.variable_out = OBJECTS - mmx_compiler.name = compiling[mmx] ${QMAKE_FILE_IN} - silent:mmx_compiler.commands = @echo compiling[mmx] ${QMAKE_FILE_IN} && $$mmx_compiler.commands - QMAKE_EXTRA_COMPILERS += mmx_compiler - } - 3dnow { - mmx3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - mmx3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -mmmx - mmx3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -mmmx - } else { - mmx3dnow_compiler.commands += -m3dnow -mmmx - } - - mmx3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - mmx3dnow_compiler.dependency_type = TYPE_C - mmx3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - mmx3dnow_compiler.input = MMX3DNOW_SOURCES - mmx3dnow_compiler.variable_out = OBJECTS - mmx3dnow_compiler.name = compiling[mmx3dnow] ${QMAKE_FILE_IN} - silent:mmx3dnow_compiler.commands = @echo compiling[mmx3dnow] ${QMAKE_FILE_IN} && $$mmx3dnow_compiler.commands - QMAKE_EXTRA_COMPILERS += mmx3dnow_compiler - sse { - sse3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -msse - sse3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -msse - } else { - sse3dnow_compiler.commands += -m3dnow -msse - } - - sse3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse3dnow_compiler.dependency_type = TYPE_C - sse3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse3dnow_compiler.input = SSE3DNOW_SOURCES - sse3dnow_compiler.variable_out = OBJECTS - sse3dnow_compiler.name = compiling[sse3dnow] ${QMAKE_FILE_IN} - silent:sse3dnow_compiler.commands = @echo compiling[sse3dnow] ${QMAKE_FILE_IN} && $$sse3dnow_compiler.commands - QMAKE_EXTRA_COMPILERS += sse3dnow_compiler - } - } - sse { - sse_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse_compiler.commands += -Xarch_i386 -msse - sse_compiler.commands += -Xarch_x86_64 -msse - } else { - sse_compiler.commands += -msse - } - - sse_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse_compiler.dependency_type = TYPE_C - sse_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse_compiler.input = SSE_SOURCES - sse_compiler.variable_out = OBJECTS - sse_compiler.name = compiling[sse] ${QMAKE_FILE_IN} - silent:sse_compiler.commands = @echo compiling[sse] ${QMAKE_FILE_IN} && $$sse_compiler.commands - QMAKE_EXTRA_COMPILERS += sse_compiler - } - sse2 { - sse2_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse2_compiler.commands += -Xarch_i386 -msse2 - sse2_compiler.commands += -Xarch_x86_64 -msse2 - } else { - sse2_compiler.commands += -msse2 - } - - sse2_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse2_compiler.dependency_type = TYPE_C - sse2_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse2_compiler.input = SSE2_SOURCES - sse2_compiler.variable_out = OBJECTS - sse2_compiler.name = compiling[sse2] ${QMAKE_FILE_IN} - silent:sse2_compiler.commands = @echo compiling[sse2] ${QMAKE_FILE_IN} && $$sse2_compiler.commands - QMAKE_EXTRA_COMPILERS += sse2_compiler - } - iwmmxt { - iwmmxt_compiler.commands = $$QMAKE_CXX -c -Winline - iwmmxt_compiler.commands += -mcpu=iwmmxt - iwmmxt_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - iwmmxt_compiler.dependency_type = TYPE_C - iwmmxt_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - iwmmxt_compiler.input = IWMMXT_SOURCES - iwmmxt_compiler.variable_out = OBJECTS - iwmmxt_compiler.name = compiling[iwmmxt] ${QMAKE_FILE_IN} - silent:iwmmxt_compiler.commands = @echo compiling[iwmmxt] ${QMAKE_FILE_IN} && $$iwmmxt_compiler.commands - QMAKE_EXTRA_COMPILERS += iwmmxt_compiler - } - } else { - mmx: SOURCES += $$MMX_SOURCES - 3dnow: SOURCES += $$MMX3DNOW_SOURCES - 3dnow:sse: SOURCES += $$SSE3DNOW_SOURCES - sse: SOURCES += $$SSE_SOURCES - sse2: SOURCES += $$SSE2_SOURCES - iwmmxt: SOURCES += $$IWMMXT_SOURCES - } + painting/qdrawhelper_sse_p.h \ + painting/qdrawingprimitive_sse2_p.h + MMX_SOURCES += painting/qdrawhelper_mmx.cpp + MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp + SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp + SSE_SOURCES += painting/qdrawhelper_sse.cpp + SSE2_SOURCES += painting/qdrawhelper_sse2.cpp + IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp } x11 { diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 6cd8688..346e177 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -43,176 +43,12 @@ #ifdef QT_HAVE_SSE2 +#include <private/qsimd_p.h> +#include <private/qdrawingprimitive_sse2_p.h> #include <private/qpaintengine_raster_p.h> -#ifdef QT_LINUXBASE -// this is an evil hack - the posix_memalign declaration in LSB -// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431 -# define posix_memalign _lsb_hack_posix_memalign -# include <emmintrin.h> -# undef posix_memalign -#else -# include <emmintrin.h> -#endif - QT_BEGIN_NAMESPACE -/* - * Multiply the components of pixelVector by alphaChannel - * Each 32bits components of alphaChannel must be in the form 0x00AA00AA - * colorMask must have 0x00ff00ff on each 32 bits component - * half must have the value 128 (0x80) for each 32 bits compnent - */ -#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ -{ \ - /* 1. separate the colors in 2 vectors so each color is on 16 bits \ - (in order to be multiplied by the alpha \ - each 32 bit of dstVectorAG are in the form 0x00AA00GG \ - each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ - __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ - __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ - \ - /* 2. multiply the vectors by the alpha channel */\ - pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ - pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ - \ - /* 3. devide by 255, that's the tricky part. \ - we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ - /** so first (X + X/256 + rounding) */\ - pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ - pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ - pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ - pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ - \ - /** second devide by 256 */\ - pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ - /** for AG, we could >> 8 to divide followed by << 8 to put the \ - bytes in the correct position. By masking instead, we execute \ - only one instruction */\ - pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ - \ - /* 4. combine the 2 pairs of colors */ \ - result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ -} - -/* - * Each 32bits components of alphaChannel must be in the form 0x00AA00AA - * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component - * colorMask must have 0x00ff00ff on each 32 bits component - * half must have the value 128 (0x80) for each 32 bits compnent - */ -#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ - /* interpolate AG */\ - __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ - __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ - __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ - __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ - __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ - finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ - finalAG = _mm_add_epi16(finalAG, half); \ - finalAG = _mm_andnot_si128(colorMask, finalAG); \ - \ - /* interpolate RB */\ - __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ - __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ - __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ - __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ - __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ - finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ - finalRB = _mm_add_epi16(finalRB, half); \ - finalRB = _mm_srli_epi16(finalRB, 8); \ - \ - /* combine */\ - result = _mm_or_si128(finalAG, finalRB); \ -} - -// Basically blend src over dst with the const alpha defined as constAlphaVector. -// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: -//const __m128i nullVector = _mm_set1_epi32(0); -//const __m128i half = _mm_set1_epi16(0x80); -//const __m128i one = _mm_set1_epi16(0xff); -//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); -//const __m128i alphaMask = _mm_set1_epi32(0xff000000); -// -// The computation being done is: -// result = s + d * (1-alpha) -// with shortcuts if fully opaque or fully transparent. -#define BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ - int x = 0; \ - for (; x < length-3; x += 4) { \ - const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ - const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ - /* all opaque */ \ - _mm_storeu_si128((__m128i *)&dst[x], srcVector); \ - } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ - /* not fully transparent */ \ - /* extract the alpha channel on 2 x 16 bits */ \ - /* so we have room for the multiplication */ \ - /* each 32 bits will be in the form 0x00AA00AA */ \ - /* with A being the 1 - alpha */ \ - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ - alphaChannel = _mm_sub_epi16(one, alphaChannel); \ - \ - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ - __m128i destMultipliedByOneMinusAlpha; \ - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ - \ - /* result = s + d * (1-alpha) */\ - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ - _mm_storeu_si128((__m128i *)&dst[x], result); \ - } \ - } \ - for (; x < length; ++x) { \ - uint s = src[x]; \ - if (s >= 0xff000000) \ - dst[x] = s; \ - else if (s != 0) \ - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ - } \ -} - -// Basically blend src over dst with the const alpha defined as constAlphaVector. -// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: -//const __m128i nullVector = _mm_set1_epi32(0); -//const __m128i half = _mm_set1_epi16(0x80); -//const __m128i one = _mm_set1_epi16(0xff); -//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); -// -// The computation being done is: -// dest = (s + d * sia) * ca + d * cia -// = s * ca + d * (sia * ca + cia) -// = s * ca + d * (1 - sa*ca) -#define BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector) \ -{ \ - int x = 0; \ - for (; x < length-3; x += 4) { \ - __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { \ - BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); \ -\ - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ - alphaChannel = _mm_sub_epi16(one, alphaChannel); \ - \ - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ - __m128i destMultipliedByOneMinusAlpha; \ - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ - \ - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ - _mm_storeu_si128((__m128i *)&dst[x], result); \ - } \ - } \ - for (; x < length; ++x) { \ - quint32 s = src[x]; \ - if (s != 0) { \ - s = BYTE_MUL(s, const_alpha); \ - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ - } \ - } \ -} - void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h new file mode 100644 index 0000000..3c96946 --- /dev/null +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDRAWINGPRIMITIVE_SSE2_P_H +#define QDRAWINGPRIMITIVE_SSE2_P_H + +#include <private/qsimd_p.h> + +#ifdef QT_HAVE_SSE2 + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +/* + * Multiply the components of pixelVector by alphaChannel + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ +{ \ + /* 1. separate the colors in 2 vectors so each color is on 16 bits \ + (in order to be multiplied by the alpha \ + each 32 bit of dstVectorAG are in the form 0x00AA00GG \ + each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ + __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ + __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ + \ + /* 2. multiply the vectors by the alpha channel */\ + pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ + pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ + \ + /* 3. devide by 255, that's the tricky part. \ + we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ + /** so first (X + X/256 + rounding) */\ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ + \ + /** second devide by 256 */\ + pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ + /** for AG, we could >> 8 to divide followed by << 8 to put the \ + bytes in the correct position. By masking instead, we execute \ + only one instruction */\ + pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ + \ + /* 4. combine the 2 pairs of colors */ \ + result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ +} + +/* + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ + /* interpolate AG */\ + __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ + __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ + __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ + __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ + __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ + finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ + finalAG = _mm_add_epi16(finalAG, half); \ + finalAG = _mm_andnot_si128(colorMask, finalAG); \ + \ + /* interpolate RB */\ + __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ + __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ + __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ + __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ + __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ + finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ + finalRB = _mm_add_epi16(finalRB, half); \ + finalRB = _mm_srli_epi16(finalRB, 8); \ + \ + /* combine */\ + result = _mm_or_si128(finalAG, finalRB); \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +//const __m128i alphaMask = _mm_set1_epi32(0xff000000); +// +// The computation being done is: +// result = s + d * (1-alpha) +// with shortcuts if fully opaque or fully transparent. +#define BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ + /* all opaque */ \ + _mm_storeu_si128((__m128i *)&dst[x], srcVector); \ + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ + /* not fully transparent */ \ + /* extract the alpha channel on 2 x 16 bits */ \ + /* so we have room for the multiplication */ \ + /* each 32 bits will be in the form 0x00AA00AA */ \ + /* with A being the 1 - alpha */ \ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + /* result = s + d * (1-alpha) */\ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + uint s = src[x]; \ + if (s >= 0xff000000) \ + dst[x] = s; \ + else if (s != 0) \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +// +// The computation being done is: +// dest = (s + d * sia) * ca + d * cia +// = s * ca + d * (sia * ca + cia) +// = s * ca + d * (1 - sa*ca) +#define BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector) \ +{ \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { \ + BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); \ +\ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + quint32 s = src[x]; \ + if (s != 0) { \ + s = BYTE_MUL(s, const_alpha); \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ + } \ +} + +QT_END_NAMESPACE + +#endif // QT_HAVE_SSE2 + +#endif // QDRAWINGPRIMITIVE_SSE2_P_H diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index 101c6a8..94be1bb 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4482,4 +4482,6 @@ EXPORTS ?textDirection@QLocale@@QBE?AW4LayoutDirection@Qt@@XZ @ 4481 NONAME ; enum Qt::LayoutDirection QLocale::textDirection(void) const ?peek@QIODevicePrivate@@UAE_JPAD_J@Z @ 4482 NONAME ; long long QIODevicePrivate::peek(char *, long long) ?peek@QIODevicePrivate@@UAE?AVQByteArray@@_J@Z @ 4483 NONAME ; class QByteArray QIODevicePrivate::peek(long long) + ?nativeArguments@QProcess@@QBE?AVQString@@XZ @ 4484 NONAME ; class QString QProcess::nativeArguments(void) const + ?setNativeArguments@QProcess@@QAEXABVQString@@@Z @ 4485 NONAME ; void QProcess::setNativeArguments(class QString const &) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 7b9e777..46c4885 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3709,4 +3709,6 @@ EXPORTS _ZNK7QString13isRightToLeftEv @ 3708 NONAME _ZN16QIODevicePrivate4peekEPcx @ 3709 NONAME _ZN16QIODevicePrivate4peekEx @ 3710 NONAME + _ZN8QProcess18setNativeArgumentsERK7QString @ 3711 NONAME + _ZNK8QProcess15nativeArgumentsEv @ 3712 NONAME diff --git a/tests/auto/linguist/lrelease/tst_lrelease.cpp b/tests/auto/linguist/lrelease/tst_lrelease.cpp index fdb384e..3b2c2d2 100644 --- a/tests/auto/linguist/lrelease/tst_lrelease.cpp +++ b/tests/auto/linguist/lrelease/tst_lrelease.cpp @@ -171,7 +171,12 @@ void tst_lrelease::mixedcodecs() { QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/mixedcodecs-ts11.ts")); QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/mixedcodecs-ts20.ts")); +#ifdef Q_OS_WIN + QVERIFY(!QProcess::execute("fc /b testdata\\mixedcodecs-ts11.qm testdata\\mixedcodecs-ts20.qm")); +#else QVERIFY(!QProcess::execute("cmp testdata/mixedcodecs-ts11.qm testdata/mixedcodecs-ts20.qm")); +#endif + QTranslator translator; QVERIFY(translator.load("testdata/mixedcodecs-ts11.qm")); qApp->installTranslator(&translator); diff --git a/tests/auto/qprocess/testProcessSpacesArgs/main.cpp b/tests/auto/qprocess/testProcessSpacesArgs/main.cpp index d842934..ae5d3ae 100644 --- a/tests/auto/qprocess/testProcessSpacesArgs/main.cpp +++ b/tests/auto/qprocess/testProcessSpacesArgs/main.cpp @@ -44,9 +44,14 @@ int main(int argc, char ** argv) { -#if defined(__SYMBIAN32__) +#if defined(__SYMBIAN32__) || defined(WINCE) || defined(_WIN32_WCE) +# if defined(__SYMBIAN32__) // Printing to stdout messes up the out.txt, so open a file and print there. FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","w+"); +# else + // No pipes on this "OS" + FILE* file = fopen("\\temp\\qprocess_args_test.txt","w+"); +# endif for (int i = 0; i < argc; ++i) { if (i) fprintf(file, "|"); diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index 8dae9a0..fd310f4 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -93,6 +93,7 @@ private slots: void getSetCheck(); void constructing(); void simpleStart(); + void execute(); void startDetached(); void crashTest(); void crashTest2(); @@ -131,6 +132,9 @@ private slots: void waitForBytesWrittenInABytesWrittenSlot(); void spaceArgsTest_data(); void spaceArgsTest(); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + void nativeArguments(); +#endif void exitCodeTest(); void setEnvironment_data(); void setEnvironment(); @@ -284,6 +288,14 @@ void tst_QProcess::simpleStart() QCOMPARE(qVariantValue<QProcess::ProcessState>(spy.at(2).at(0)), QProcess::NotRunning); } //----------------------------------------------------------------------------- +void tst_QProcess::execute() +{ + QCOMPARE(QProcess::execute("testProcessNormal/testProcessNormal", + QStringList() << "arg1" << "arg2"), 0); + QCOMPARE(QProcess::execute("nonexistingexe"), -2); +} + +//----------------------------------------------------------------------------- void tst_QProcess::startDetached() { QProcess proc; @@ -1621,6 +1633,55 @@ void tst_QProcess::spaceArgsTest() process = 0; } +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + +//----------------------------------------------------------------------------- +void tst_QProcess::nativeArguments() +{ + QProcess proc; + + // This doesn't actually need special quoting, so it is pointless to use + // native arguments here, but that's not the point of this test. + proc.setNativeArguments("hello kitty, \"*\"!"); + + proc.start(QString::fromLatin1("testProcessSpacesArgs/nospace"), QStringList()); + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QVERIFY(proc.waitForStarted(5000)); + QVERIFY(proc.waitForFinished(5000)); +#else + QVERIFY(proc.waitForStarted(10000)); + QVERIFY(proc.waitForFinished(10000)); +#endif + +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE) + // Symbian test outputs to a file, so check that +# ifdef Q_OS_SYMBIAN + FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","r"); +# else + FILE* file = fopen("\\temp\\qprocess_args_test.txt","r"); +# endif + char buf[256]; + fgets(buf, 256, file); + fclose(file); + QStringList actual = QString::fromLatin1(buf).split("|"); +#else + QStringList actual = QString::fromLatin1(proc.readAll()).split("|"); +#endif + QVERIFY(!actual.isEmpty()); + // not interested in the program name, it might be different. + actual.removeFirst(); + QStringList expected; +#if defined(Q_OS_WINCE) + expected << "hello" << "kitty," << "\"*\"!"; // Weird, weird ... +#else + expected << "hello" << "kitty," << "*!"; +#endif + QCOMPARE(actual, expected); +} + +#endif + //----------------------------------------------------------------------------- void tst_QProcess::exitCodeTest() { diff --git a/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp b/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp index 8e9de4a..27e5025 100644 --- a/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp @@ -40,9 +40,12 @@ ****************************************************************************/ #include <qtest.h> -#include <QPixmap> #include <QBitmap> +#include <QDir> +#include <QImage> +#include <QImageReader> #include <QPainter> +#include <QPixmap> #include <private/qpixmap_raster_p.h> class tst_QPixmap : public QObject @@ -62,6 +65,9 @@ private slots: void transformed(); void mask_data(); void mask(); + + void fromImageReader_data(); + void fromImageReader(); }; Q_DECLARE_METATYPE(QImage::Format) @@ -248,6 +254,62 @@ void tst_QPixmap::mask() } } +void tst_QPixmap::fromImageReader_data() +{ + const QString tempDir = QDir::tempPath(); + QTest::addColumn<QString>("filename"); + + QImage image(2000, 2000, QImage::Format_ARGB32); + image.fill(0); + { + // Generate an image with opaque and transparent pixels + // with an interesting distribution. + QPainter painter(&image); + + QRadialGradient radialGrad(QPointF(1000, 1000), 1000); + radialGrad.setColorAt(0, QColor(255, 0, 0, 255)); + radialGrad.setColorAt(0.5, QColor(0, 255, 0, 255)); + radialGrad.setColorAt(0.9, QColor(0, 0, 255, 100)); + radialGrad.setColorAt(1, QColor(0, 0, 0, 0)); + + painter.fillRect(image.rect(), radialGrad); + } + image.save("test.png"); + + // RGB32 + const QString rgb32Path = tempDir + QString::fromLatin1("/rgb32.jpg"); + image.save(rgb32Path); + QTest::newRow("gradient RGB32") << rgb32Path; + + // ARGB32 + const QString argb32Path = tempDir + QString::fromLatin1("/argb32.png"); + image.save(argb32Path); + QTest::newRow("gradient ARGB32") << argb32Path; + + // Indexed 8 + const QString indexed8Path = tempDir + QString::fromLatin1("/indexed8.gif"); + image.save(indexed8Path); + QTest::newRow("gradient indexed8") << indexed8Path; + +} + +void tst_QPixmap::fromImageReader() +{ + QFETCH(QString, filename); + // warmup + { + QImageReader imageReader(filename); + QPixmap::fromImageReader(&imageReader); + } + + QBENCHMARK { + QImageReader imageReader(filename); + QPixmap::fromImageReader(&imageReader); + } + QFile::remove(filename); +} + + QTEST_MAIN(tst_QPixmap) #include "tst_qpixmap.moc" diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 49ba5f6..89b1e98 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -1359,7 +1359,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, if (!s->inherited.isEmpty()) { out() << "<ul>\n"; - generateSectionInheritedList(*s, inner, marker, true); + generateSectionInheritedList(*s, inner, marker); out() << "</ul>\n"; } } @@ -2636,44 +2636,6 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, } } -/*void HtmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); - } - marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), - "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - - if (style == CodeMarker::Summary) - marked.replace("@name>", "b>"); - - if (style == CodeMarker::SeparateList) { - QRegExp extraRegExp("<@extra>.*</@extra>"); - extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } - else { - marked.replace("<@extra>", " <tt>"); - marked.replace("</@extra>", "</tt>"); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); - } - out() << highlightedCode(marked, marker, relative); -}*/ - #ifdef QDOC_QML void HtmlGenerator::generateQmlItem(const Node *node, const Node *relative, @@ -2703,6 +2665,17 @@ void HtmlGenerator::generateQmlItem(const Node *node, marked.replace("<@type>", ""); marked.replace("</@type>", ""); } + if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* qpn = static_cast<const QmlPropertyNode*>(node); + if (!summary && qpn->name() == "color" && qpn->dataType() == "color") { + if (relative && relative->name() == "GradientStop") { + qDebug() << "color : color"; + debugging_on = true; + qDebug() << " " << relative->name() << relative->type() << relative->subType(); + qDebug() << marked; + } + } + } out() << highlightedCode(marked, marker, relative); debugging_on = false; } @@ -2822,24 +2795,23 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m } } -#ifdef QDOC_NAME_ALIGNMENT void HtmlGenerator::generateSection(const NodeList& nl, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!nl.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (nl.count() >= 16); } else if (nl.first()->type() == Node::Property) { twoColumn = (nl.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { + if (alignNames) { out() << "<table class=\"alignedsummary\">\n"; } else { @@ -2857,7 +2829,7 @@ void HtmlGenerator::generateSection(const NodeList& nl, continue; } - if (name_alignment) { + if (alignNames) { out() << "<tr><td class=\"memItemLeft rightAlign topAlign\"> "; } else { @@ -2866,15 +2838,15 @@ void HtmlGenerator::generateSection(const NodeList& nl, out() << "<li class=\"fn\">"; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "</td></tr>\n"; else out() << "</li>\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "</table>\n"; else { out() << "</ul>\n"; @@ -2889,18 +2861,18 @@ void HtmlGenerator::generateSectionList(const Section& section, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!section.members.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (section.members.count() >= 16); } else if (section.members.first()->type() == Node::Property) { twoColumn = (section.members.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { + if (alignNames) { out() << "<table class=\"alignedsummary\">\n"; } else { @@ -2918,7 +2890,7 @@ void HtmlGenerator::generateSectionList(const Section& section, continue; } - if (name_alignment) { + if (alignNames) { out() << "<tr><td class=\"memItemLeft topAlign rightAlign\"> "; } else { @@ -2927,15 +2899,15 @@ void HtmlGenerator::generateSectionList(const Section& section, out() << "<li class=\"fn\">"; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "</td></tr>\n"; else out() << "</li>\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "</table>\n"; else { out() << "</ul>\n"; @@ -2946,22 +2918,18 @@ void HtmlGenerator::generateSectionList(const Section& section, if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { out() << "<ul>\n"; - generateSectionInheritedList(section, relative, marker, name_alignment); + generateSectionInheritedList(section, relative, marker); out() << "</ul>\n"; } } void HtmlGenerator::generateSectionInheritedList(const Section& section, const Node *relative, - CodeMarker *marker, - bool nameAlignment) + CodeMarker *marker) { QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { - if (nameAlignment) - out() << "<li class=\"fn\">"; - else - out() << "<li class=\"fn\">"; + out() << "<li class=\"fn\">"; out() << (*p).second << " "; if ((*p).second == 1) { out() << section.singularMember; @@ -2981,7 +2949,7 @@ void HtmlGenerator::generateSynopsis(const Node *node, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style, - bool nameAlignment) + bool alignNames) { QString marked = marker->markedUpSynopsis(node, relative, style); QRegExp templateTag("(<[^@>]*>)"); @@ -3014,14 +2982,13 @@ void HtmlGenerator::generateSynopsis(const Node *node, marked.replace("<@type>", ""); marked.replace("</@type>", ""); } - out() << highlightedCode(marked, marker, relative, style, nameAlignment); + out() << highlightedCode(marked, marker, relative, alignNames); } QString HtmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle , - bool nameAlignment) + CodeMarker* marker, + const Node* relative, + bool alignNames) { QString src = markedCode; QString html; @@ -3031,20 +2998,24 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, const QChar charLangle = '<'; const QChar charAt = '@'; - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" + static const QString typeTag("type"); + static const QString headerTag("headerfile"); + static const QString funcTag("func"); static const QString linkTag("link"); + + // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" bool done = false; - for (int i = 0, n = src.size(); i < n;) { + for (int i = 0, srcSize = src.size(); i < srcSize;) { if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { - if (nameAlignment && !done) {// && (i != 0)) Why was this here? + if (alignNames && !done) {// && (i != 0)) Why was this here? html += "</td><td class=\"memItemRight bottomAlign\">"; done = true; } i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { + if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) { html += "<b>"; - QString link = linkForNode( - CodeMarker::nodeForString(par1.toString()), relative); + const Node* n = CodeMarker::nodeForString(par1.toString()); + QString link = linkForNode(n, relative); addLink(link, arg, &html); html += "</b>"; } @@ -3064,16 +3035,14 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" src = html; html = QString(); - static const QString funcTag("func"); - for (int i = 0, n = src.size(); i < n;) { + for (int i = 0, srcSize = src.size(); i < srcSize;) { if (src.at(i) == charLangle && src.at(i + 1) == charAt) { i += 2; - if (parseArg(src, funcTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); + if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + const Node* n = marker->resolveTarget(par1.toString(), + myTree, + relative); + QString link = linkForNode(n, relative); addLink(link, arg, &html); par1 = QStringRef(); } @@ -3091,295 +3060,36 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags src = html; html = QString(); - static const QString typeTags[] = { "type", "headerfile", "func" }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { + + for (int i=0, srcSize=src.size(); i<srcSize;) { + if (src.at(i) == charLangle && src.at(i+1) == charAt) { i += 2; bool handled = false; - for (int k = 0; k != 3; ++k) { - if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { - par1 = QStringRef(); - const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); - QString link = linkForNode(n,relative); - addLink(link, arg, &html); - handled = true; - break; + if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + if (HtmlGenerator::debugging_on) { + if (n) { + qDebug() << " " << n->name() << n->type() << n->subType(); + qDebug() << " " << relative->name() << relative->type() << relative->subType(); + } } + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - if (!handled) { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - - // replace all - // "<@comment>" -> "<span class=\"comment\">"; - // "<@preprocessor>" -> "<span class=\"preprocessor\">"; - // "<@string>" -> "<span class=\"string\">"; - // "<@char>" -> "<span class=\"char\">"; - // "</@(?:comment|preprocessor|string|char)>" -> "</span>" - src = html; - html = QString(); - static const QString spanTags[] = { - "<@comment>", "<span class=\"comment\">", - "<@preprocessor>", "<span class=\"preprocessor\">", - "<@string>", "<span class=\"string\">", - "<@char>", "<span class=\"char\">", - "</@comment>", "</span>", - "</@preprocessor>","</span>", - "</@string>", "</span>", - "</@char>", "</span>" - // "<@char>", "<font color=blue>", - // "</@char>", "</font>", - // "<@func>", "<font color=green>", - // "</@func>", "</font>", - // "<@id>", "<i>", - // "</@id>", "</i>", - // "<@keyword>", "<b>", - // "</@keyword>", "</b>", - // "<@number>", "<font color=yellow>", - // "</@number>", "</font>", - // "<@op>", "<b>", - // "</@op>", "</b>", - // "<@param>", "<i>", - // "</@param>", "</i>", - // "<@string>", "<font color=green>", - // "</@string>", "</font>", - }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle) { - bool handled = false; - for (int k = 0; k != 8; ++k) { - const QString & tag = spanTags[2 * k]; - if (tag == QStringRef(&src, i, tag.length())) { - html += spanTags[2 * k + 1]; - i += tag.length(); - handled = true; - break; - } + else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - if (!handled) { - ++i; - if (src.at(i) == charAt || - (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) { - // drop 'our' unknown tags (the ones still containing '@') - while (i < n && src.at(i) != QLatin1Char('>')) - ++i; - ++i; - } - else { - // retain all others - html += charLangle; - } + else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - } - else { - html += src.at(i); - ++i; - } - } - - return html; -} -#else -void HtmlGenerator::generateSectionList(const Section& section, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - if (!section.members.isEmpty()) { - bool twoColumn = false; - if (style == CodeMarker::SeparateList) { - twoColumn = (section.members.count() >= 16); - } - else if (section.members.first()->type() == Node::Property) { - twoColumn = (section.members.count() >= 5); - } - if (twoColumn) - out() << "<table class=\"generic\">\n"; - if (++numTableRows % 2 == 1) - out() << "<tr class=\"odd topAlign\">"; - else - out() << "<tr class=\"even topAlign\">"; - -// << "<tr><td class=\"topAlign\">"; - out() << "<ul>\n"; - - int i = 0; - NodeList::ConstIterator m = section.members.begin(); - while (m != section.members.end()) { - if ((*m)->access() == Node::Private) { - ++m; - continue; - } - - if (twoColumn && i == (int) (section.members.count() + 1) / 2) - out() << "</ul></td><td class=\"topAlign\"><ul>\n"; - - out() << "<li class=\"fn\">"; - if (style == CodeMarker::Accessors) - out() << "<b>"; - generateSynopsis(*m, relative, marker, style); - if (style == CodeMarker::Accessors) - out() << "</b>"; - out() << "</li>\n"; - i++; - ++m; - } - out() << "</ul>\n"; - if (twoColumn) - out() << "</td></tr>\n</table>\n"; - } - - if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { - out() << "<ul>\n"; - generateSectionInheritedList(section, relative, marker); - out() << "</ul>\n"; - } -} - -void HtmlGenerator::generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker) -{ - QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); - while (p != section.inherited.end()) { - out() << "<li class=\"fn\">"; - out() << (*p).second << " "; - if ((*p).second == 1) { - out() << section.singularMember; - } else { - out() << section.pluralMember; - } - out() << " inherited from <a href=\"" << fileName((*p).first) - << "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">" - << protectEnc(marker->plainFullName((*p).first, relative)) - << "</a></li>\n"; - ++p; - } -} - -void HtmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); - } - marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - - if (style == CodeMarker::Summary) - marked.replace("@name>", "b>"); - - if (style == CodeMarker::SeparateList) { - QRegExp extraRegExp("<@extra>.*</@extra>"); - extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } else { - marked.replace("<@extra>", "<tt>"); - marked.replace("</@extra>", "</tt>"); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); - } - out() << highlightedCode(marked, marker, relative); -} - -QString HtmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative) -{ - QString src = markedCode; - QString html; - QStringRef arg; - QStringRef par1; - - const QChar charLangle = '<'; - const QChar charAt = '@'; - - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" - static const QString linkTag("link"); - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { - const Node* node = CodeMarker::nodeForString(par1.toString()); - QString link = linkForNode(node, relative); - addLink(link, arg, &html); - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - - if (slow) { - // is this block ever used at all? - // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" - src = html; - html = QString(); - static const QString funcTag("func"); - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, funcTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); - addLink(link, arg, &html); - par1 = QStringRef(); - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - } - - // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags - src = html; - html = QString(); - static const QString typeTags[] = { "type", "headerfile", "func" }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - bool handled = false; - for (int k = 0; k != 3; ++k) { - if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { - par1 = QStringRef(); - QString link = linkForNode( - marker->resolveTarget(arg.toString(), myTree, relative), - relative); - addLink(link, arg, &html); - handled = true; - break; - } - } if (!handled) { html += charLangle; html += charAt; @@ -3407,22 +3117,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, "</@preprocessor>","</span>", "</@string>", "</span>", "</@char>", "</span>" - // "<@char>", "<font color=blue>", - // "</@char>", "</font>", - // "<@func>", "<font color=green>", - // "</@func>", "</font>", - // "<@id>", "<i>", - // "</@id>", "</i>", - // "<@keyword>", "<b>", - // "</@keyword>", "</b>", - // "<@number>", "<font color=yellow>", - // "</@number>", "</font>", - // "<@op>", "<b>", - // "</@op>", "</b>", - // "<@param>", "<i>", - // "</@param>", "</i>", - // "<@string>", "<font color=green>", - // "</@string>", "</font>", }; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { @@ -3459,7 +3153,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, return html; } -#endif void HtmlGenerator::generateLink(const Atom* atom, const Node* /* relative */, diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index aad5021..80341de 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -46,8 +46,6 @@ #ifndef HTMLGENERATOR_H #define HTMLGENERATOR_H -#define QDOC_NAME_ALIGNMENT - #include <qmap.h> #include <qregexp.h> #include <QXmlStreamWriter> @@ -198,7 +196,7 @@ class HtmlGenerator : public PageGenerator void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); #endif -#ifdef QDOC_NAME_ALIGNMENT + void generateSection(const NodeList& nl, const Node *relative, CodeMarker *marker, @@ -207,28 +205,15 @@ class HtmlGenerator : public PageGenerator const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style, - bool nameAlignment = false); - void generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker, - bool nameAlignment = false); - QString highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle style = CodeMarker::Accessors, - bool nameAlignment = false); -#else - void generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style); + bool alignNames = false); void generateSectionInheritedList(const Section& section, const Node *relative, CodeMarker *marker); QString highlightedCode(const QString& markedCode, CodeMarker *marker, - const Node *relative); -#endif + const Node *relative, + bool alignNames = false); + void generateFullName(const Node *apparentNode, const Node *relative, CodeMarker *marker, diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index d3de46c..70b998f 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -134,15 +134,16 @@ Node *Tree::findNode(const QStringList &path, Node *relative, int findFlags) /*! */ -const Node *Tree::findNode(const QStringList &path, - const Node *relative, +const Node* Tree::findNode(const QStringList &path, + const Node* start, int findFlags) const { - if (!relative) - relative = root(); + const Node* current = start; + if (!current) + current = root(); do { - const Node *node = relative; + const Node *node = current; int i; for (i = 0; i < path.size(); ++i) { @@ -171,10 +172,10 @@ const Node *Tree::findNode(const QStringList &path, if (node && i == path.size() && (!(findFlags & NonFunction) || node->type() != Node::Function || ((FunctionNode *)node)->metaness() == FunctionNode::MacroWithoutParams)) - if (node->subType() != Node::QmlPropertyGroup) + if ((node != start) && (node->subType() != Node::QmlPropertyGroup)) return node; - relative = relative->parent(); - } while (relative); + current = current->parent(); + } while (current); return 0; } |