diff options
Diffstat (limited to 'src/gui/painting')
42 files changed, 2353 insertions, 361 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index d226be2..4121be6 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -82,6 +82,7 @@ SOURCES += \ DEFINES += QT_RASTER_IMAGEENGINE win32:DEFINES += QT_RASTER_PAINTENGINE embedded:DEFINES += QT_RASTER_PAINTENGINE + symbian:DEFINES += QT_RASTER_PAINTENGINE SOURCES += \ painting/qpaintengine_raster.cpp \ painting/qdrawhelper.cpp \ @@ -152,14 +153,14 @@ unix:x11 { painting/qprintengine_mac.mm \ } -unix:!mac { +unix:!mac:!symbian { HEADERS += \ painting/qprinterinfo_unix_p.h SOURCES += \ painting/qprinterinfo_unix.cpp } -win32|x11|mac|embedded { +win32|x11|mac|embedded|symbian { SOURCES += painting/qbackingstore.cpp HEADERS += painting/qbackingstore_p.h } @@ -176,6 +177,13 @@ embedded { painting/qpaintdevice_qws.cpp } +symbian { + SOURCES += \ + painting/qpaintdevice_s60.cpp \ + painting/qregion_s60.cpp \ + painting/qcolormap_s60.cpp +} + x11|embedded { contains(QT_CONFIG,qtopia) { DEFINES += QT_NO_CUPS QT_NO_LPR @@ -353,3 +361,18 @@ embedded { } +symbian { + HEADERS += painting/qwindowsurface_s60_p.h + SOURCES += painting/qwindowsurface_s60.cpp + armccIfdefBlock = \ + "$${LITERAL_HASH}if defined(ARMV6)" \ + "MACRO QT_HAVE_ARMV6" \ + "SOURCEPATH painting" \ + "SOURCE qblendfunctions_armv6_rvct.s" \ + "SOURCE qdrawhelper_armv6_rvct.s" \ + "$${LITERAL_HASH}endif" + + MMP_RULES += armccIfdefBlock + QMAKE_CXXFLAGS.ARMCC *= -O3 +} + diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 01c6159..40c9bf2 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -832,6 +832,10 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) QWidgetBackingStore::~QWidgetBackingStore() { + for (int c = 0; c < dirtyWidgets.size(); ++c) { + resetWidget(dirtyWidgets.at(c)); + } + delete windowSurface; windowSurface = 0; delete dirtyOnScreenWidgets; diff --git a/src/gui/painting/qblendfunctions_armv6_rvct.s b/src/gui/painting/qblendfunctions_armv6_rvct.s new file mode 100644 index 0000000..312bd07 --- /dev/null +++ b/src/gui/painting/qblendfunctions_armv6_rvct.s @@ -0,0 +1,223 @@ +;/**************************************************************************** +;** +;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +;** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +;** Beta Release License Agreement. +;** +;** 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.0, included in the file LGPL_EXCEPTION.txt in this +;** package. +;** +;** GNU General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU +;** General Public License version 3.0 as published by the Free Software +;** Foundation and appearing in the file LICENSE.GPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU General Public License version 3.0 requirements will be +;** met: http://www.gnu.org/copyleft/gpl.html. +;** +;** If you are unsure which license is appropriate for your use, please +;** contact the sales department at qt-sales@nokia.com. +;** $QT_END_LICENSE$ +;** +;****************************************************************************/ + +; +; 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. +; + + + ARM + PRESERVE8 + + INCLUDE qdrawhelper_armv6_rvct.inc + + +;----------------------------------------------------------------------------- +; qt_blend_rgb32_on_rgb32_arm +; +; @brief +; +; @param dest Destination pixels (r0) +; @param dbpl Destination bytes per line (r1) +; @param src Source pixels (r2) +; @param sbpl Source bytes per line (r3) +; @param w Width (s0 -> r4) +; @param h Height (s1 -> r5) +; @param const_alpha Constant alpha (s2 -> r6) +; +;--------------------------------------------------------------------------- +qt_blend_rgb32_on_rgb32_armv6 Function + stmfd sp!, {r4-r12, r14} + + ; read arguments off the stack + add r8, sp, #10 * 4 + ldmia r8, {r9-r11} + + ; Reorganize registers + + mov r4, r10 + mov r5, r1 + mov r6, r3 + + mov r1, r2 + mov r2, r9 + mov r3, r11 + + ; Now we have registers + ; @param dest Destination pixels (r0) + ; @param src Source pixels (r1) + ; @param w Width (r2) + ; @param const_alpha Constant alpha (r3) + ; @param h Height (r4) + ; @param dbpl Destination bytes per line (r5) + ; @param sbpl Source bytes per line (r6) + + cmp r3, #256 ; test if we have fully opaque constant alpha value + bne rgb32_blend_const_alpha ; branch if not + +rgb32_blend_loop + + subs r4, r4, #1 + bmi rgb32_blend_exit ; while(h--) + +rgb321 PixCpySafe r0, r1, r2 + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b rgb32_blend_loop + + +rgb32_blend_const_alpha + + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + + sub r3, r3, #1 ; const_alpha -= 1; + +rgb32_blend_loop_const_alpha + + subs r4, r4, #1 + bmi rgb32_blend_exit ; while(h--) + +rgb322 BlendRowSafe PixelSourceOverConstAlpha + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b rgb32_blend_loop_const_alpha + +rgb32_blend_exit + + ldmfd sp!, {r4-r12, pc} ; pop and return + + + +;----------------------------------------------------------------------------- +; qt_blend_argb32_on_argb32_arm +; +; @brief +; +; @param dest Destination pixels (r0) +; @param dbpl Destination bytes per line (r1) +; @param src Source pixels (r2) +; @param sbpl Source bytes per line (r3) +; @param w Width (s0 -> r4) +; @param h Height (s1 -> r5) +; @param const_alpha Constant alpha (s2 -> r6) +; +;--------------------------------------------------------------------------- +qt_blend_argb32_on_argb32_armv6 Function + stmfd sp!, {r4-r12, r14} + + ; read arguments off the stack + add r8, sp, #10 * 4 + ldmia r8, {r9-r11} + + ; Reorganize registers + + mov r4, r10 + mov r5, r1 + mov r6, r3 + + mov r1, r2 + mov r2, r9 + mov r3, r11 + + ; Now we have registers + ; @param dest Destination pixels (r0) + ; @param src Source pixels (r1) + ; @param w Width (r2) + ; @param const_alpha Constant alpha (r3) + ; @param h Height (r4) + ; @param dbpl Destination bytes per line (r5) + ; @param sbpl Source bytes per line (r6) + + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + + cmp r3, #256 ; test if we have fully opaque constant alpha value + bne argb32_blend_const_alpha ; branch if not + +argb32_blend_loop + + subs r4, r4, #1 + bmi argb32_blend_exit ; while(h--) + +argb321 BlendRowSafe PixelSourceOver + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b argb32_blend_loop + +argb32_blend_const_alpha + + sub r3, r3, #1 ; const_alpha -= 1; + +argb32_blend_loop_const_alpha + + subs r4, r4, #1 + bmi argb32_blend_exit ; while(h--) + +argb322 BlendRowSafe PixelSourceOverConstAlpha + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b argb32_blend_loop_const_alpha + +argb32_blend_exit + + ldmfd sp!, {r4-r12, pc} ; pop and return + + + END ; File end + diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index f767bb3..519e02e 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -221,7 +221,7 @@ bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush) { if (brush.style() != Qt::TexturePattern) return false; - QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d); + QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d.data()); return tx_data->m_has_pixmap_texture; } @@ -230,6 +230,37 @@ struct QGradientBrushData : public QBrushData QGradient gradient; }; +struct QBrushDataPointerHandler +{ + static inline void deleteData(QBrushData *d) + { + switch (d->style) { + case Qt::TexturePattern: + delete static_cast<QTexturedBrushData*>(d); + break; + case Qt::LinearGradientPattern: + case Qt::RadialGradientPattern: + case Qt::ConicalGradientPattern: + delete static_cast<QGradientBrushData*>(d); + break; + default: + delete d; + } + } + + static inline void cleanup(QBrushData *d) + { + if (d && !d->ref.deref()) { + deleteData(d); + } + } + + static inline void reset(QBrushData *&d, QBrushData *other) + { + cleanup(d); + d = other; + } +}; /*! \class QBrush @@ -364,20 +395,20 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style) { switch(style) { case Qt::NoBrush: - d = nullBrushInstance(); + d.data_ptr() = nullBrushInstance(); d->ref.ref(); if (d->color != color) setColor(color); return; case Qt::TexturePattern: - d = new QTexturedBrushData; + d.data_ptr() = new QTexturedBrushData; break; case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: - d = new QGradientBrushData; + d.data_ptr() = new QGradientBrushData; break; default: - d = new QBrushData; + d.data_ptr() = new QBrushData; break; } d->ref = 1; @@ -391,8 +422,8 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style) */ QBrush::QBrush() + : d(nullBrushInstance()) { - d = nullBrushInstance(); Q_ASSERT(d); d->ref.ref(); } @@ -435,7 +466,7 @@ QBrush::QBrush(Qt::BrushStyle style) if (qbrush_check_type(style)) init(Qt::black, style); else { - d = nullBrushInstance(); + d.data_ptr() = nullBrushInstance(); d->ref.ref(); } } @@ -451,7 +482,7 @@ QBrush::QBrush(const QColor &color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d = nullBrushInstance(); + d.data_ptr() = nullBrushInstance(); d->ref.ref(); } } @@ -468,7 +499,7 @@ QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d = nullBrushInstance(); + d.data_ptr() = nullBrushInstance(); d->ref.ref(); } } @@ -510,8 +541,8 @@ QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap) */ QBrush::QBrush(const QBrush &other) + : d(other.d.data()) { - d = other.d; d->ref.ref(); } @@ -535,7 +566,7 @@ QBrush::QBrush(const QGradient &gradient) }; init(QColor(), enum_table[gradient.type()]); - QGradientBrushData *grad = static_cast<QGradientBrushData *>(d); + QGradientBrushData *grad = static_cast<QGradientBrushData *>(d.data()); grad->gradient = gradient; } @@ -545,24 +576,11 @@ QBrush::QBrush(const QGradient &gradient) QBrush::~QBrush() { - if (!d->ref.deref()) - cleanUp(d); } void QBrush::cleanUp(QBrushData *x) { - switch (x->style) { - case Qt::TexturePattern: - delete static_cast<QTexturedBrushData*>(x); - break; - case Qt::LinearGradientPattern: - case Qt::RadialGradientPattern: - case Qt::ConicalGradientPattern: - delete static_cast<QGradientBrushData*>(x); - break; - default: - delete x; - } + QBrushDataPointerHandler::deleteData(x); } @@ -571,38 +589,36 @@ void QBrush::detach(Qt::BrushStyle newStyle) if (newStyle == d->style && d->ref == 1) return; - QBrushData *x; + QScopedPointer<QBrushData> x; switch(newStyle) { case Qt::TexturePattern: { QTexturedBrushData *tbd = new QTexturedBrushData; if (d->style == Qt::TexturePattern) { - QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data()); if (data->m_has_pixmap_texture) tbd->setPixmap(data->pixmap()); else tbd->setImage(data->image()); } - x = tbd; + x.reset(tbd); break; } case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: - x = new QGradientBrushData; - static_cast<QGradientBrushData *>(x)->gradient = - static_cast<QGradientBrushData *>(d)->gradient; + x.reset(new QGradientBrushData); + static_cast<QGradientBrushData *>(x.data())->gradient = + static_cast<QGradientBrushData *>(d.data())->gradient; break; default: - x = new QBrushData; + x.reset(new QBrushData); break; } x->ref = 1; x->style = newStyle; x->color = d->color; x->transform = d->transform; - if (!d->ref.deref()) - cleanUp(d); - d = x; + d.reset(x.take()); } @@ -615,10 +631,11 @@ void QBrush::detach(Qt::BrushStyle newStyle) QBrush &QBrush::operator=(const QBrush &b) { + if (this == &b) + return *this; + b.d->ref.ref(); - if (!d->ref.deref()) - cleanUp(d); - d = b.d; + d.reset(b.d.data()); return *this; } @@ -713,7 +730,7 @@ QPixmap *QBrush::pixmap() const { if (d->style != Qt::TexturePattern) return 0; - QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d.data()); QPixmap &pixmap = data->pixmap(); return pixmap.isNull() ? 0 : &pixmap; } @@ -730,7 +747,7 @@ QPixmap *QBrush::pixmap() const QPixmap QBrush::texture() const { return d->style == Qt::TexturePattern - ? ((QTexturedBrushData*) d)->pixmap() + ? (static_cast<QTexturedBrushData *>(d.data()))->pixmap() : QPixmap(); } @@ -748,7 +765,7 @@ void QBrush::setTexture(const QPixmap &pixmap) { if (!pixmap.isNull()) { detach(Qt::TexturePattern); - QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data()); data->setPixmap(pixmap); } else { detach(Qt::NoBrush); @@ -771,7 +788,7 @@ void QBrush::setTexture(const QPixmap &pixmap) QImage QBrush::textureImage() const { return d->style == Qt::TexturePattern - ? ((QTexturedBrushData *) d)->image() + ? (static_cast<QTexturedBrushData *>(d.data()))->image() : QImage(); } @@ -796,7 +813,7 @@ void QBrush::setTextureImage(const QImage &image) { if (!image.isNull()) { detach(Qt::TexturePattern); - QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data()); data->setImage(image); } else { detach(Qt::NoBrush); @@ -812,7 +829,7 @@ const QGradient *QBrush::gradient() const if (d->style == Qt::LinearGradientPattern || d->style == Qt::RadialGradientPattern || d->style == Qt::ConicalGradientPattern) { - return &static_cast<const QGradientBrushData *>(d)->gradient; + return &static_cast<const QGradientBrushData *>(d.data())->gradient; } return 0; } @@ -925,16 +942,16 @@ bool QBrush::operator==(const QBrush &b) const if (b.d->style == d->style && b.d->color == d->color) { switch (d->style) { case Qt::TexturePattern: { - QPixmap &us = ((QTexturedBrushData *) d)->pixmap(); - QPixmap &them = ((QTexturedBrushData *) b.d)->pixmap(); + QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap(); + QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap(); return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey()); } case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: { - QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d); - QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d); + QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data()); + QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data()); return d1->gradient == d2->gradient; } default: diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 13b5eba..fdb3a8a 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -45,6 +45,7 @@ #include <QtCore/qpair.h> #include <QtCore/qpoint.h> #include <QtCore/qvector.h> +#include <QtCore/qscopedpointer.h> #include <QtGui/qcolor.h> #include <QtGui/qmatrix.h> #include <QtGui/qtransform.h> @@ -70,6 +71,7 @@ struct QBrushData; class QPixmap; class QGradient; class QVariant; +struct QBrushDataPointerHandler; class Q_GUI_EXPORT QBrush { @@ -135,13 +137,13 @@ private: friend bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush); void detach(Qt::BrushStyle newStyle); void init(const QColor &color, Qt::BrushStyle bs); - QBrushData *d; + QScopedCustomPointer<QBrushData, QBrushDataPointerHandler> d; void cleanUp(QBrushData *x); public: inline bool isDetached() const; typedef QBrushData * DataPtr; - inline DataPtr &data_ptr() { return d; } + inline DataPtr &data_ptr() { return d.data_ptr(); } }; inline void QBrush::setColor(Qt::GlobalColor acolor) diff --git a/src/gui/painting/qcolormap_s60.cpp b/src/gui/painting/qcolormap_s60.cpp new file mode 100644 index 0000000..1b58598 --- /dev/null +++ b/src/gui/painting/qcolormap_s60.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcolormap.h" +#include "qcolor.h" + +QT_BEGIN_NAMESPACE + +class QColormapPrivate +{ +public: + inline QColormapPrivate() + : ref(1) + { } + + QAtomicInt ref; +}; + +void QColormap::initialize() +{ +} + +void QColormap::cleanup() +{ +} + +QColormap QColormap::instance(int) +{ + return QColormap(); +} + +QColormap::QColormap() : d(new QColormapPrivate) +{} + +QColormap::QColormap(const QColormap &colormap) :d (colormap.d) +{ d->ref.ref(); } + +QColormap::~QColormap() +{ + if (!d->ref.deref()) + delete d; +} + +QColormap::Mode QColormap::mode() const +{ return QColormap::Direct; } + +int QColormap::depth() const +{ + return 32; +} + +int QColormap::size() const +{ + return -1; +} + +uint QColormap::pixel(const QColor &color) const +{ return color.rgba(); } + +const QColor QColormap::colorAt(uint pixel) const +{ return QColor(pixel); } + +const QVector<QColor> QColormap::colormap() const +{ return QVector<QColor>(); } + +QColormap &QColormap::operator=(const QColormap &colormap) +{ qAtomicAssign(d, colormap.d); return *this; } + +QT_END_NAMESPACE + diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index b6603e4..d77ed57 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -38,15 +38,18 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include <private/qdrawhelper_p.h> #include <private/qpaintengine_raster_p.h> #include <private/qpainter_p.h> #include <private/qdrawhelper_x86_p.h> +#include <private/qdrawhelper_armv6_p.h> #include <private/qmath_p.h> #include <qmath.h> QT_BEGIN_NAMESPACE + #define MASK(src, a) src = BYTE_MUL(src, a) #if defined(Q_OS_IRIX) && defined(Q_CC_GNU) && __GNUC__ == 3 && __GNUC__ < 4 && QT_POINTER_SIZE == 8 @@ -654,7 +657,15 @@ Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, int y, int x, int length) { +#ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 + FetchPixelProc fetch; + if (format != QImage::Format_Invalid) + fetch = qt_fetchPixel<format>; + else + fetch = fetchPixelProc[data->texture.format]; +#else FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format]; +#endif int image_width = data->texture.width; int image_height = data->texture.height; @@ -1203,7 +1214,35 @@ static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operato return b; } - +#if defined(Q_CC_RVCT) +// Force ARM code generation for comp_func_* -methods +# pragma push +# pragma arm +# if defined(QT_HAVE_ARMV6) +static __forceinline void preload(const uint *start) +{ + asm( "pld [start]" ); +} +static const uint L2CacheLineLength = 32; +static const uint L2CacheLineLengthInInts = L2CacheLineLength/sizeof(uint); +# define PRELOAD_INIT(x) preload(x); +# define PRELOAD_INIT2(x,y) PRELOAD_INIT(x) PRELOAD_INIT(y) +# define PRELOAD_COND(x) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); +// Two consecutive preloads stall, so space them out a bit by using different modulus. +# define PRELOAD_COND2(x,y) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); \ + if (((uint)&y[i])%L2CacheLineLength == 16) preload(&y[i] + L2CacheLineLengthInInts); +# else +# define PRELOAD_INIT(x) +# define PRELOAD_INIT2(x,y) +# define PRELOAD_COND(x) +# define PRELOAD_COND2(x,y) +# endif +#else +# define PRELOAD_INIT(x) +# define PRELOAD_INIT2(x,y) +# define PRELOAD_COND(x) +# define PRELOAD_COND2(x,y) +#endif /* The constant alpha factor describes an alpha factor that gets applied to the result of the composition operation combining it with the destination. @@ -1236,8 +1275,11 @@ static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint QT_MEMFILL_UINT(dest, length, 0); } else { int ialpha = 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], ialpha); + } } } @@ -1247,8 +1289,11 @@ static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, ui QT_MEMFILL_UINT(dest, length, 0); } else { int ialpha = 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], ialpha); + } } } @@ -1263,8 +1308,11 @@ static void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint colo } else { int ialpha = 255 - const_alpha; color = BYTE_MUL(color, const_alpha); - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = color + BYTE_MUL(dest[i], ialpha); + } } } @@ -1274,8 +1322,11 @@ static void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length ::memcpy(dest, src, length * sizeof(uint)); } else { int ialpha = 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); + } } } @@ -1300,20 +1351,26 @@ static void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint } else { if (const_alpha != 255) color = BYTE_MUL(color, const_alpha); - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color)); + } } } static void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = src[i]; dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); } @@ -1329,7 +1386,9 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, { if (const_alpha != 255) color = BYTE_MUL(color, const_alpha); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = d + BYTE_MUL(color, qAlpha(~d)); } @@ -1337,13 +1396,16 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; dest[i] = d + BYTE_MUL(src[i], qAlpha(~d)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = BYTE_MUL(src[i], const_alpha); dest[i] = d + BYTE_MUL(s, qAlpha(~d)); @@ -1357,13 +1419,17 @@ static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, i */ static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha) { + PRELOAD_INIT(dest) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(color, qAlpha(dest[i])); + } } else { color = BYTE_MUL(color, const_alpha); uint cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia); } @@ -1372,12 +1438,16 @@ static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint co static void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(src[i], qAlpha(dest[i])); + } } else { uint cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = BYTE_MUL(src[i], const_alpha); dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia); @@ -1396,19 +1466,25 @@ static void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, ui if (const_alpha != 255) { a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; } + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], a); } } static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(dest[i], qAlpha(src[i])); + } } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia; dest[i] = BYTE_MUL(dest[i], a); } @@ -1422,13 +1498,17 @@ static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha) { + PRELOAD_INIT(dest) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(color, qAlpha(~dest[i])); + } } else { color = BYTE_MUL(color, const_alpha); int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia); } @@ -1437,12 +1517,16 @@ static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint c static void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i])); + } } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia); @@ -1460,18 +1544,25 @@ static void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, u uint a = qAlpha(~color); if (const_alpha != 255) a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], a); + } } static void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i])); + } } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia; dest[i] = BYTE_MUL(dest[i], sia); } @@ -1490,20 +1581,26 @@ static void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color = BYTE_MUL(color, const_alpha); } uint sia = qAlpha(~color); - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia); + } } static void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = src[i]; uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); @@ -1523,7 +1620,9 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, color = BYTE_MUL(color, const_alpha); a = qAlpha(color) + 255 - const_alpha; } + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d)); } @@ -1531,8 +1630,10 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = src[i]; uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d)); @@ -1540,6 +1641,7 @@ static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, i } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); uint d = dest[i]; uint a = qAlpha(s) + cia; @@ -1560,7 +1662,9 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, color = BYTE_MUL(color, const_alpha); uint sia = qAlpha(~color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia); } @@ -1568,14 +1672,17 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, static void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = BYTE_MUL(src[i], const_alpha); dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); @@ -1626,7 +1733,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int { uint s = color; + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; #define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); @@ -1646,7 +1755,9 @@ static void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -1682,7 +1793,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -1708,7 +1821,9 @@ static void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint co template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -1746,7 +1861,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, i int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -1772,7 +1889,9 @@ static void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint colo template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -1821,7 +1940,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -1847,7 +1968,9 @@ static void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint col template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -1890,7 +2013,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, i int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -1916,7 +2041,9 @@ static void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint colo template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -1959,7 +2086,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -1985,7 +2114,9 @@ static void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint col template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2038,7 +2169,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *des int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2064,7 +2197,9 @@ static void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2117,7 +2252,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2143,7 +2280,9 @@ static void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2193,7 +2332,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2219,7 +2360,9 @@ static void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2278,7 +2421,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2304,7 +2449,9 @@ static void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2347,7 +2494,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *des int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2373,7 +2522,9 @@ static void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2410,7 +2561,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_imp int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2436,7 +2589,9 @@ static void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2462,6 +2617,11 @@ static void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int len comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha)); } +#if defined(Q_CC_RVCT) +// Restore pragma state from previous #pragma arm +# pragma pop +#endif + static void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, int length, uint color, @@ -7739,6 +7899,96 @@ static uint detectCPUFeatures() #endif } +#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) +// Move these to qdrawhelper_arm.c when all +// functions are implemented using arm assembly. +static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = { + comp_func_solid_SourceOver, + comp_func_solid_DestinationOver, + comp_func_solid_Clear, + comp_func_solid_Source, + comp_func_solid_Destination, + comp_func_solid_SourceIn, + comp_func_solid_DestinationIn, + comp_func_solid_SourceOut, + comp_func_solid_DestinationOut, + comp_func_solid_SourceAtop, + comp_func_solid_DestinationAtop, + comp_func_solid_XOR, + comp_func_solid_Plus, + comp_func_solid_Multiply, + comp_func_solid_Screen, + comp_func_solid_Overlay, + comp_func_solid_Darken, + comp_func_solid_Lighten, + comp_func_solid_ColorDodge, + comp_func_solid_ColorBurn, + comp_func_solid_HardLight, + comp_func_solid_SoftLight, + comp_func_solid_Difference, + comp_func_solid_Exclusion, + rasterop_solid_SourceOrDestination, + rasterop_solid_SourceAndDestination, + rasterop_solid_SourceXorDestination, + rasterop_solid_NotSourceAndNotDestination, + rasterop_solid_NotSourceOrNotDestination, + rasterop_solid_NotSourceXorDestination, + rasterop_solid_NotSource, + rasterop_solid_NotSourceAndDestination, + rasterop_solid_SourceAndNotDestination +}; + +static CompositionFunction qt_functionForMode_ARMv6[numCompositionFunctions] = { + comp_func_SourceOver_armv6, + comp_func_DestinationOver, + comp_func_Clear, + comp_func_Source_armv6, + comp_func_Destination, + comp_func_SourceIn, + comp_func_DestinationIn, + comp_func_SourceOut, + comp_func_DestinationOut, + comp_func_SourceAtop, + comp_func_DestinationAtop, + comp_func_XOR, + comp_func_Plus, + comp_func_Multiply, + comp_func_Screen, + comp_func_Overlay, + comp_func_Darken, + comp_func_Lighten, + comp_func_ColorDodge, + comp_func_ColorBurn, + comp_func_HardLight, + comp_func_SoftLight, + comp_func_Difference, + comp_func_Exclusion, + rasterop_SourceOrDestination, + rasterop_SourceAndDestination, + rasterop_SourceXorDestination, + rasterop_NotSourceAndNotDestination, + rasterop_NotSourceOrNotDestination, + rasterop_NotSourceXorDestination, + rasterop_NotSource, + rasterop_NotSourceAndDestination, + rasterop_SourceAndNotDestination +}; + +static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + CompositionFunctionSolid func = qt_functionForModeSolid_ARMv6[data->rasterBuffer->compositionMode]; + while (count--) { + uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; + func(target, spans->len, data->solid.color, spans->coverage); + ++spans; + } +} + +#endif // Q_CC_RVCT && QT_HAVE_ARMV6 + + void qInitDrawhelperAsm() { static uint features = 0xffffffff; @@ -7854,6 +8104,20 @@ void qInitDrawhelperAsm() #endif // QT_NO_DEBUG +#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) + functionForModeAsm = qt_functionForMode_ARMv6; + functionForModeSolidAsm = qt_functionForModeSolid_ARMv6; + + qt_memfill32 = qt_memfill32_armv6; + + qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_armv6; + + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; +#endif // Q_CC_RVCT && QT_HAVE_ARMV6 + if (functionForModeSolidAsm) { const int destinationMode = QPainter::CompositionMode_Destination; functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode]; diff --git a/src/gui/painting/qdrawhelper_armv6_p.h b/src/gui/painting/qdrawhelper_armv6_p.h new file mode 100644 index 0000000..a4c1df2 --- /dev/null +++ b/src/gui/painting/qdrawhelper_armv6_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDRAWHELPER_ARMV6_P_H +#define QDRAWHELPER_ARMV6_P_H + +// +// 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. +// + +#include <private/qdrawhelper_p.h> + +QT_BEGIN_NAMESPACE + +#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) + +extern "C" void qt_blend_rgb32_on_rgb32_armv6(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +extern "C" void qt_blend_argb32_on_argb32_armv6(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +extern "C" void qt_memfill32_armv6(quint32 *dest, quint32 value, int count); + +extern "C" void comp_func_Source_armv6(uint *dest, const uint *src, int length, uint const_alpha); +extern "C" void comp_func_SourceOver_armv6(uint *dest, const uint *src, int length, uint const_alpha); + +#endif // QT_HAVE_ARMV6 + +QT_END_NAMESPACE + +#endif // QDRAWHELPER_ARMV6_P_H diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.inc b/src/gui/painting/qdrawhelper_armv6_rvct.inc new file mode 100644 index 0000000..b3e0605 --- /dev/null +++ b/src/gui/painting/qdrawhelper_armv6_rvct.inc @@ -0,0 +1,496 @@ +;/**************************************************************************** +;** +;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +;** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +;** Beta Release License Agreement. +;** +;** 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.0, included in the file LGPL_EXCEPTION.txt in this +;** package. +;** +;** GNU General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU +;** General Public License version 3.0 as published by the Free Software +;** Foundation and appearing in the file LICENSE.GPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU General Public License version 3.0 requirements will be +;** met: http://www.gnu.org/copyleft/gpl.html. +;** +;** If you are unsure which license is appropriate for your use, please +;** contact the sales department at qt-sales@nokia.com. +;** $QT_END_LICENSE$ +;** +;****************************************************************************/ + +; +; 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. +; + +;----------------------------------------------------------------------------- +; Globals. +; Earch marcro expects that caller has loaded 0x800080 to r14. +;----------------------------------------------------------------------------- + +ComponentHalf EQU 0x800080 + +;----------------------------------------------------------------------------- +; ARM assembly implementations of accelerated graphics operations. +; +; Conventions: +; +; - r0 = Target buffer pointer +; - r1 = Source buffer pointer +; - r2 = Length of the buffer to blend +; - r3 = Constant alpha for source buffer +; +;----------------------------------------------------------------------------- + +; A macro for transparently defining ARM functions + MACRO +$func Function + AREA Function_$func, CODE + GLOBAL $func + ALIGN 4 + CODE32 +$func + MEND + + +;----------------------------------------------------------------------------- +; Armv6 boosted implementation of BYTE_MUL(...) function found in qdrawhelper_p.h. +; +; @param dst Destination register where to store the result +; @param x Value to multiply +; @param a Multiplicator byte +; @param r14 Component half 0x800080 +; +; @note Trashes x, r8 +;----------------------------------------------------------------------------- + MACRO + ByteMul $dst, $x, $a + + ; static inline uint BYTE_MUL(uint x, uint a) + + ; uint r8 = (x & 0xff00ff) * a + 0x800080 + uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF + mla r8, r8, $a, r14 + + ; x = ((r >> 8) & 0xff00ff) * a + 0x800080 + uxtb16 $x, $x, ror #8 + mla $x, $x, $a, r14 + + + ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8 + ; r8 &= 0xff00ff + uxtab16 r8, r8, r8, ror #8 + uxtb16 r8, r8, ror #8 + + ; x = x + ((x >>8) & 0xff00ff) + uxtab16 $x, $x, $x, ror #8 + + ; x &= 0xff00ff00 + ; x |= r8 + uxtb16 $x, $x, ror #8 + orr $dst, r8, $x, lsl #8 + + MEND + +;----------------------------------------------------------------------------- +; Armv6 boosted implementation of INTERPOLATE_PIXEL_255(...) function found in +; qdrawhelper_p.h. +; +; @param dst Destination register where to store the result +; @param x First value to multiply +; @param a Multiplicator byte for first value +; @param y Second value to multiply +; @param b Multiplicator byte for second value +; @param r14 Component half 0x800080 +; +; +; @note Trashes x, r8, r14 +;----------------------------------------------------------------------------- + MACRO + InterpolatePixel255 $dst, $x, $a, $y, $b + + ; static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) + + ; First calculate the parts where we need 0x800080 + + ; uint r8 = (((x & 0xff00ff) * a) + 0x800080) + uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF + mla r8, r8, $a, r14 + + ; x = ((((x >> 8) & 0xff00ff) * a) + 0x800080) + uxtb16 $x, $x, ror #8 + mla $x, $x, $a, r14 + + ; Now we are trashing r14 to free it for other purposes + + ; uint r14 = (y & 0xff00ff) * b + uxtb16 r14, $y ; r14 = y & 0x00FF00FF + mul r14, r14, $b + + ; r8 = r8 + r14 + add r8, r8, r14 + + ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8 + ; r8 &= 0xff00ff + uxtab16 r8, r8, r8, ror #8 + uxtb16 r8, r8, ror #8 + + ; r14 = ((y >> 8) & 0xff00ff) * b + uxtb16 r14, $y, ror #8 ; r14 = ((y >> 8) & 0xFF00FF) + mul r14, r14, $b + + ; x = x + r14 + add $x, $x, r14 + + ; x = x + ((x >>8) & 0xff00ff) + uxtab16 $x, $x, $x, ror #8 + + ; x &= 0xff00ff00 + ; x |= r8 + uxtb16 $x, $x, ror #8 + orr $dst, r8, $x, lsl #8 + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend4Pixels $BlendPixel + + ; Blend first 4 pixels + + ldmia r1!, {r4-r7} + ldm r0, {r9-r12} + +b4p1_$label $BlendPixel r9, r4, r3 +b4p2_$label $BlendPixel r10, r5, r3 +b4p3_$label $BlendPixel r11, r6, r3 +b4p4_$label $BlendPixel r12, r7, r3 + + stmia r0!, {r9-r12} + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend8Pixels $BlendPixel + +b8p1_$label Blend4Pixels $BlendPixel +b8p2_$label Blend4Pixels $BlendPixel + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend16Pixels $BlendPixel + +b16p1_$label Blend8Pixels $BlendPixel +b16p2_$label Blend8Pixels $BlendPixel + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend32Pixels $BlendPixel + +b32p1_$label Blend16Pixels $BlendPixel +b32p2_$label Blend16Pixels $BlendPixel + + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one row of pixels and saving the results +; to destination buffer. +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; @param r14 Component Half (0x800080) (r14) +; +; @note Advances r0, r1 +; @note Trashes r2, r4-r12 +;----------------------------------------------------------------------------- + MACRO +$label BlendRow $BlendPixel + + pld [r1] + +bloop_$label + ; Blend 32 pixels per loop iteration + subs r2, r2, #32 + bmi b_remaining_$label + +brp1_$label Blend32Pixels $BlendPixel + + b bloop_$label + +b_remaining_$label + + ; Remaining 31 pixels + + addmi r2, r2, #32 + + ; Blend 16 pixels + tst r2, #16 + beq b_remaining8_$label + +brp2_$label Blend16Pixels $BlendPixel + +b_remaining8_$label + + ; Blend 8 pixels + tst r2, #8 + beq b_remaining4_$label + +brp3_$label Blend8Pixels $BlendPixel + +b_remaining4_$label + + ; Blend 4 pixels + tst r2, #4 + beq b_remaining3_$label + +brp4_$label Blend4Pixels $BlendPixel + +b_remaining3_$label + + ; Remaining 3 pixels + + tst r2, #2 + beq b_last_$label + + ldmia r1!, {r4-r5} + ldm r0, {r9-r10} + +brp5_$label $BlendPixel r9, r4, r3 +brp6_$label $BlendPixel r10, r5, r3 + + stmia r0!, {r9-r10} + +b_last_$label + + tst r2, #1 + beq bexit_$label + + ldr r4, [r1] + ldr r9, [r0] + +bpl_$label $BlendPixel r9, r4, r3 + + str r9, [r0] + +bexit_$label + + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one row of pixels and saving the results +; to destination buffer. Restores all registers. +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; @param r14 Component Half (0x800080) (r14) +; +; @note Advances r0, r1 +; @note Trashes r2, r4-r12 +;----------------------------------------------------------------------------- + MACRO +$label BlendRowSafe $BlendPixel + + stmfd sp!, {r0-r6} ; Preserves registers only up to r6 + +brs_$label BlendRow $BlendPixel + + ldmfd sp!, {r0-r6} + + MEND + + +;----------------------------------------------------------------------------- +; Pix Copy. +; NOTE! Cache line size of ARM1136JF-S and ARM1136J-S is 32 bytes (8 pixels). +; +; @param dst Destination pixels (r0) +; @param src Source pixels (r1) +; @param len Length (r2) +; +; @note Trashes r3-r10 +;----------------------------------------------------------------------------- + MACRO +$label PixCpy $dst, $src, $len + + pld [$src] + +pcpy_loop_$label + ; Copy 8 pixels per loop iteration + pld [$src, #96] + subs $len, $len, #8 + ldmgeia $src!, {r3-r10} + stmgeia $dst!, {r3-r10} + bgt pcpy_loop_$label + +pcpy_remaining_$label + + ; Copy up to 7 remaining pixels + + ; Copy 4 pixels + tst $len, #4 + ldmneia $src!, {r3-r6} + stmneia $dst!, {r3-r6} + + tst $len, #2 + ldmneia $src!, {r3-r4} + stmneia $dst!, {r3-r4} + + tst $len, #1 + ldrne r3, [$src] + strne r3, [$dst] + + MEND + +;----------------------------------------------------------------------------- +; General Pix Copy. Maximum 8 pixels at time. Restores all registers. +; +; @param dst Destination pixels (r0) +; @param src Source pixels (r1) +; @param len Length (r2) +; +; @note Trashes r3-r10 +;----------------------------------------------------------------------------- + MACRO +$label PixCpySafe $dst, $src, $len + + stmfd sp!, {r0-r6} ; Preserves registers only up to r6 + +pcs_$label PixCpy $dst, $src, $len + + ldmfd sp!, {r0-r6} ; pop + + MEND + + +;----------------------------------------------------------------------------- +; A macro for source over compositing one pixel and saving the result to +; dst register. +; +; @param dst Destination register, must contain destination pixel upon entry +; @param src Source register, must contain source pixel upon entry +; @param const_alpha Constant source alpha +; @param r14 Component half 0x800080 +; +; @note Trashes const_alpha, r8 +;----------------------------------------------------------------------------- + MACRO +$label PixelSourceOver $dst, $src, $const_alpha + + ; Negate src and extract alpha + mvn $const_alpha, $src ; bitwise not + uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24); + + ;cmp $const_alpha, #255 ; test for full transparency ( negated ) + ;beq exit_$label + cmp $const_alpha, #0 ; test for full opacity ( negated ) + moveq $dst, $src + beq exit_$label + + ByteMul $dst, $dst, $const_alpha + add $dst, $src, $dst + +exit_$label + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one pixel and saving the result to +; dst register. +; +; @param dst Destination register, must contain destination pixel upon entry +; @param src Source register, must contain source pixel upon entry +; @param const_alpha Constant source alpha +; @param r14 Component half 0x800080 +; +; @note Trashes src, const_alpha, r8 +;----------------------------------------------------------------------------- + MACRO +$label PixelSourceOverConstAlpha $dst, $src, $const_alpha + + ; store alpha because we are going to trash it + stmfd sp!, {$const_alpha} + + ByteMul $src, $src, $const_alpha + + ; Negate src and extract alpha + mvn $const_alpha, $src ; bitwise not + uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24); + + ByteMul $dst, $dst, $const_alpha + + add $dst, $src, $dst + + ; recover alpha + ldmfd sp!, {$const_alpha} + + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one pixel and saving the result to +; a register. +; +; @param dst Destination register, must contain destination pixel upon entry +; @param src Source register, must contain source pixel upon entry +; @param const_alpha Constant source alpha +; @param r14 Component half 0x800080 +; +; @note Trashes src, r8 +;----------------------------------------------------------------------------- + MACRO +$label PixelSourceConstAlpha $dst, $src, $const_alpha + + ; store r2 and r14 because we are going to trash them + stmfd sp!, {r2, r14} + + rsb r2, $const_alpha, #255 + InterpolatePixel255 $dst, $src, $const_alpha, $dst, r2 + + ; recover r2 and r14 + ldmfd sp!, {r2, r14} + + MEND + + END ; File end diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.s b/src/gui/painting/qdrawhelper_armv6_rvct.s new file mode 100644 index 0000000..3ffe48b --- /dev/null +++ b/src/gui/painting/qdrawhelper_armv6_rvct.s @@ -0,0 +1,178 @@ +;/**************************************************************************** +;** +;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +;** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +;** Beta Release License Agreement. +;** +;** 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.0, included in the file LGPL_EXCEPTION.txt in this +;** package. +;** +;** GNU General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU +;** General Public License version 3.0 as published by the Free Software +;** Foundation and appearing in the file LICENSE.GPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU General Public License version 3.0 requirements will be +;** met: http://www.gnu.org/copyleft/gpl.html. +;** +;** If you are unsure which license is appropriate for your use, please +;** contact the sales department at qt-sales@nokia.com. +;** $QT_END_LICENSE$ +;** +;****************************************************************************/ + +; +; 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. +; + + ARM + PRESERVE8 + + INCLUDE qdrawhelper_armv6_rvct.inc + +;----------------------------------------------------------------------------- +; qt_memfill32_armv6 +; +; @brief Not yet in use! +; +; @param dest Destination buffer (r0) +; @param value Value (r1) +; @param count Count (r2) +; +;--------------------------------------------------------------------------- +qt_memfill32_armv6 Function + stmfd sp!, {r4-r12, r14} + + mov r3, r1 + mov r4, r1 + mov r5, r1 + mov r6, r1 + mov r7, r1 + mov r8, r1 + mov r9, r1 + +mfill_loop + ; Fill 32 pixels per loop iteration + subs r2, r2, #32 + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + bgt mfill_loop + +mfill_remaining + + ; Fill up to 31 remaining pixels + + ; Fill 16 pixels + tst r2, #16 + stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + + ; Fill 8 pixels + tst r2, #8 + stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + + ; Fill 4 pixels + tst r2, #4 + stmneia r0!, {r1, r3, r4, r5} + + ; Fill 2 pixels + tst r2, #2 + stmneia r0!, {r1, r3} + + ; Fill last one + tst r2, #1 + strne r1, [r0] + + ldmfd sp!, {r4-r12, pc} ; pop and return + +;----------------------------------------------------------------------------- +; comp_func_Source_arm +; +; @brief +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; +;--------------------------------------------------------------------------- +comp_func_Source_armv6 Function + stmfd sp!, {r4-r12, r14} + + cmp r3, #255 ; if(r3 == 255) + bne src2 ; branch if not + +src1 PixCpy r0, r1, r2 + + ldmfd sp!, {r4-r12, pc} ; pop and return + +src2 + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + +src22 BlendRow PixelSourceConstAlpha + + ldmfd sp!, {r4-r12, pc} ; pop and return + +;----------------------------------------------------------------------------- +; comp_func_SourceOver_arm +; +; @brief +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; +;--------------------------------------------------------------------------- +comp_func_SourceOver_armv6 Function + stmfd sp!, {r4-r12, r14} + + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + + cmp r3, #255 ; if(r3 == 255) + bne srcovr2 ; branch if not + +srcovr1 BlendRow PixelSourceOver + + ldmfd sp!, {r4-r12, pc} ; pop and return + +srcovr2 + +srcovr22 BlendRow PixelSourceOverConstAlpha + + ldmfd sp!, {r4-r12, pc} ; pop and return + + + END ; File end + diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 7979716..75b39b7 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE #if defined(Q_CC_RVCT) // RVCT doesn't like static template functions # define Q_STATIC_TEMPLATE_FUNCTION -# define Q_STATIC_INLINE_FUNCTION inline +# define Q_STATIC_INLINE_FUNCTION static __forceinline #else # define Q_STATIC_TEMPLATE_FUNCTION static # define Q_STATIC_INLINE_FUNCTION static inline @@ -301,19 +301,23 @@ struct QSpanData }; -static inline uint BYTE_MUL_RGB16(uint x, uint a) { +Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) { a += 1; uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0; t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f; return t; } -static inline uint BYTE_MUL_RGB16_32(uint x, uint a) { +Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) { uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0; t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f; return t; } +#if defined(Q_CC_RVCT) +# pragma push +# pragma arm +#endif Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { uint t = (x & 0xff00ff) * a; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; @@ -325,8 +329,11 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { x |= t; return x; } +#if defined(Q_CC_RVCT) +# pragma pop +#endif -static inline uint PREMUL(uint x) { +Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) { uint a = x >> 24; uint t = (x & 0xff00ff) * a; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; @@ -391,7 +398,7 @@ public: return qt_colorConvert<quint16, quint32>(data, 0); } - static inline quint32p fromRawData(quint32 v) + Q_STATIC_INLINE_FUNCTION quint32p fromRawData(quint32 v) { quint32p p; p.data = v; @@ -422,7 +429,7 @@ class qrgb565; class qargb8565 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } inline qargb8565() {} inline qargb8565(quint32 v); @@ -439,8 +446,8 @@ public: data[1] &= 0xdf; return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline qargb8565 byte_mul(quint8 a) const; inline qargb8565 operator+(qargb8565 v) const; @@ -458,7 +465,7 @@ private: class qrgb565 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } qrgb565(int v = 0) : data(v) {} @@ -473,8 +480,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb565 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline qrgb565 byte_mul(quint8 a) const; @@ -654,7 +661,7 @@ class qrgb555; class qargb8555 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } qargb8555() {} inline qargb8555(quint32 v); @@ -666,8 +673,8 @@ public: inline quint8 alpha() const { return data[0]; } inline qargb8555 truncedAlpha() { data[0] &= 0xf8; return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline qargb8555 operator+(qargb8555 v) const; inline qargb8555 byte_mul(quint8 a) const; @@ -684,7 +691,7 @@ private: class qrgb555 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb555(int v = 0) : data(v) {} @@ -733,8 +740,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb555 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline bool operator==(const qrgb555 &v) const { return v.data == data; } inline bool operator!=(const qrgb555 &v) const { return v.data != data; } @@ -882,7 +889,7 @@ class qrgb666; class qargb6666 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } inline qargb6666() {} inline qargb6666(quint32 v) { *this = qargb6666(quint32p(v)); } @@ -894,8 +901,8 @@ public: inline quint8 alpha() const; inline qargb6666 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; } - static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } inline qargb6666 byte_mul(quint8 a) const; inline qargb6666 operator+(qargb6666 v) const; @@ -912,7 +919,7 @@ private: class qrgb666 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb666() {} inline qrgb666(quint32 v); @@ -922,8 +929,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb666 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; } - static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } inline qrgb666 operator+(qrgb666 v) const; inline qrgb666 byte_mul(quint8 a) const; @@ -1080,7 +1087,7 @@ quint32 qargb6666::rawValue() const class qrgb888 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb888() {} inline qrgb888(quint32 v); @@ -1089,8 +1096,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb888 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return a; } - static inline quint8 ialpha(quint8 a) { return 255 - a; } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return a; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 255 - a; } inline qrgb888 byte_mul(quint8 a) const; inline qrgb888 operator+(qrgb888 v) const; @@ -1269,7 +1276,7 @@ class qrgb444; class qargb4444 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } inline qargb4444() {} inline qargb4444(quint32 v) { *this = qargb4444(quint32p(v)); } @@ -1283,8 +1290,8 @@ public: inline quint8 alpha() const { return ((data & 0xf000) >> 8) | ((data & 0xf000) >> 12); } inline qargb4444 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; } - static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } inline qargb4444 byte_mul(quint8 a) const; inline bool operator==(const qargb4444 &v) const { return data == v.data; } @@ -1300,7 +1307,7 @@ private: class qrgb444 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb444() {} inline qrgb444(quint32 v); @@ -1312,8 +1319,8 @@ public: inline qrgb444 operator+(qrgb444 v) const; inline quint8 alpha() const { return 0xff; } inline qrgb444 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; } - static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } inline qrgb444 byte_mul(quint8 a) const; inline bool operator==(const qrgb444 &v) const { return data == v.data; } @@ -1774,7 +1781,14 @@ do { \ } \ } while (0) +#if defined(Q_CC_RVCT) +# pragma push +# pragma arm +#endif Q_STATIC_INLINE_FUNCTION int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +#if defined(Q_CC_RVCT) +# pragma pop +#endif inline ushort qConvertRgb32To16(uint c) { @@ -1817,7 +1831,7 @@ inline int qBlue565(quint16 rgb) { } #if 1 -static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; t >>= 8; t &= 0xff00ff; @@ -1828,7 +1842,11 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { return x; } -static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { +#if defined(Q_CC_RVCT) +# pragma push +# pragma arm +#endif +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; t &= 0xff00ff; @@ -1839,9 +1857,12 @@ static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { x |= t; return x; } +#if defined(Q_CC_RVCT) +# pragma pop +#endif #else // possible implementation for 64 bit -static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b; t >>= 8; @@ -1849,7 +1870,7 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { return (uint(t)) | (uint(t >> 24)); } -static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b; t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080); @@ -1864,7 +1885,7 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { return (uint(t)) | (uint(t >> 24)); } -static inline uint PREMUL(uint x) { +Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) { uint a = x >> 24; ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080); diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index 2a99f16..d4c7a65 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -44,7 +44,7 @@ #ifdef Q_WS_X11 # include <private/qpixmap_x11_p.h> #endif -#ifdef Q_WS_WIN +#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) # include <private/qpixmap_raster_p.h> #endif #ifdef Q_WS_MAC @@ -64,7 +64,7 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ #endif #if defined(Q_WS_X11) return new QX11PixmapData(type); -#elif defined(Q_WS_WIN) +#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp index ddc66f3..bf186e6 100644 --- a/src/gui/painting/qgraphicssystemfactory.cpp +++ b/src/gui/painting/qgraphicssystemfactory.cpp @@ -68,7 +68,7 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key) if (system.isEmpty()) { system = QLatin1String("openvg"); } -#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) +#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN) if (system.isEmpty()) { system = QLatin1String("raster"); } diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c index c41b040..6ab7055 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.c @@ -160,7 +160,12 @@ #include <private/qrasterdefs_p.h> #include <private/qgrayraster_p.h> +// Bug in stdlib.h, see more information from fixed_stdlib.h +#if (defined __SYMBIAN32__ && !defined __cplusplus) +#include <fixed_stdlib.h> +#else #include <stdlib.h> +#endif // defined __SYMBIAN32__ && !defined __cplusplus #include <stdio.h> /* This macro is used to indicate that a function parameter is unused. */ diff --git a/src/gui/painting/qpaintdevice_s60.cpp b/src/gui/painting/qpaintdevice_s60.cpp new file mode 100644 index 0000000..a2c4499 --- /dev/null +++ b/src/gui/painting/qpaintdevice_s60.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpaintdevice.h" +#include "qpainter.h" +#include "qwidget.h" +#include "qbitmap.h" +#include "qapplication.h" +#include <private/qapplication_p.h> +#include "qprinter.h" + +QT_BEGIN_NAMESPACE + +QPaintDevice::QPaintDevice() +{ + painters = 0; +} + + +QPaintDevice::~QPaintDevice() +{ + if (paintingActive()) + qWarning("QPaintDevice: Cannot destroy paint device that is being " + "painted. Be sure to QPainter::end() painters!"); +} + +int QPaintDevice::metric(PaintDeviceMetric) const +{ + qWarning("QPaintDevice::metrics: Device has no metric information"); + return 0; +} + + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index 4fb1832..5565146 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -717,7 +717,6 @@ QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps) */ QPaintEngine::~QPaintEngine() { - delete d_ptr; } /*! diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index 57c9e2d..92aa506 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -44,6 +44,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qobjectdefs.h> +#include <QtCore/qscopedpointer.h> #include <QtGui/qpainter.h> QT_BEGIN_HEADER @@ -239,7 +240,7 @@ protected: uint selfDestruct : 1; uint extended : 1; - QPaintEnginePrivate *d_ptr; + QScopedPointer<QPaintEnginePrivate> d_ptr; private: void setAutoDestruct(bool autoDestr) { selfDestruct = autoDestr; } diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 74456dd..d9af3f6 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -91,6 +91,8 @@ # include <private/qfontengine_qpf_p.h> # endif # include <private/qabstractfontengine_p.h> +#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) +# include <private/qfontengine_s60_p.h> #endif #if defined(Q_WS_WIN64) @@ -342,6 +344,7 @@ void QRasterPaintEngine::init() #else (unsigned char *) malloc(d->rasterPoolSize); #endif + Q_CHECK_PTR(d->rasterPoolBase); // The antialiasing raster. d->grayRaster = new QT_FT_Raster; @@ -3159,7 +3162,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte ensurePen(); ensureState(); -#if defined (Q_WS_WIN) || defined(Q_WS_MAC) +#if defined (Q_WS_WIN) || defined(Q_WS_MAC) || (defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)) bool drawCached = true; @@ -3192,7 +3195,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte return; } -#else // Q_WS_WIN || Q_WS_MAC +#else // Q_WS_WIN || Q_WS_MAC || Q_OS_SYMBIAN && QT_NO_FREETYPE QFontEngine *fontEngine = ti.fontEngine; @@ -3212,7 +3215,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte } #endif // Q_WS_QWS -#if (defined(Q_WS_X11) || defined(Q_WS_QWS)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2) if (fontEngine->type() == QFontEngine::QPF2) { @@ -3877,7 +3880,7 @@ static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *r // find required length int max = qMax(c1_spans[c1_count - 1].x + c1_spans[c1_count - 1].len, - c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len); + c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len); buffer.resize(max); memset(buffer.data(), 0, buffer.size() * sizeof(short)); @@ -4039,6 +4042,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, #else (unsigned char *) malloc(rasterPoolSize); #endif + Q_CHECK_PTR(rasterPoolBase); // note: we just freed the old rasterPoolBase. I hope it's not fatal. qt_ft_grays_raster.raster_done(*grayRaster); qt_ft_grays_raster.raster_new(0, grayRaster); @@ -4161,8 +4165,14 @@ int QCustomRasterPaintDevice::bytesPerLine() const { return (width() * depth() + 7) / 8; } -#endif // Q_WS_QWS +#elif defined(Q_OS_SYMBIAN) + +void QRasterBuffer::prepareBuffer(int /* width */, int /* height */) +{ +} + +#endif // Q_OS_SYMBIAN /*! \class QCustomRasterPaintDevice @@ -4270,95 +4280,109 @@ void QClipData::initialize() if (!m_clipLines) m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight); - m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan)); - allocated = clipSpanHeight; - - if (hasRectClip) { - int y = 0; - while (y < ymin) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; - } - - const int len = clipRect.width(); - count = 0; - while (y < ymax) { - QSpan *span = m_spans + count; - span->x = xmin; - span->len = len; - span->y = y; - span->coverage = 255; - ++count; - - m_clipLines[y].spans = span; - m_clipLines[y].count = 1; - ++y; - } + Q_CHECK_PTR(m_clipLines); + QT_TRY { + m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan)); + allocated = clipSpanHeight; + Q_CHECK_PTR(m_spans); + + QT_TRY { + if (hasRectClip) { + int y = 0; + while (y < ymin) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } - while (y < clipSpanHeight) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; - } - } else if (hasRegionClip) { + const int len = clipRect.width(); + count = 0; + while (y < ymax) { + QSpan *span = m_spans + count; + span->x = xmin; + span->len = len; + span->y = y; + span->coverage = 255; + ++count; - const QVector<QRect> rects = clipRegion.rects(); - const int numRects = rects.size(); + m_clipLines[y].spans = span; + m_clipLines[y].count = 1; + ++y; + } - { // resize - const int maxSpans = (ymax - ymin) * numRects; - if (maxSpans > allocated) { - m_spans = (QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan)); - allocated = maxSpans; - } - } + while (y < clipSpanHeight) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } + } else if (hasRegionClip) { + + const QVector<QRect> rects = clipRegion.rects(); + const int numRects = rects.size(); + + { // resize + const int maxSpans = (ymax - ymin) * numRects; + if (maxSpans > allocated) { + QSpan *newSpans = (QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan)); + Q_CHECK_PTR(newSpans); + m_spans = newSpans; + allocated = maxSpans; + } + } - int y = 0; - int firstInBand = 0; - count = 0; - while (firstInBand < numRects) { - const int currMinY = rects.at(firstInBand).y(); - const int currMaxY = currMinY + rects.at(firstInBand).height(); + int y = 0; + int firstInBand = 0; + count = 0; + while (firstInBand < numRects) { + const int currMinY = rects.at(firstInBand).y(); + const int currMaxY = currMinY + rects.at(firstInBand).height(); + + while (y < currMinY) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } - while (y < currMinY) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; - } + int lastInBand = firstInBand; + while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y) + ++lastInBand; - int lastInBand = firstInBand; - while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y) - ++lastInBand; + while (y < currMaxY) { - while (y < currMaxY) { + m_clipLines[y].spans = m_spans + count; + m_clipLines[y].count = lastInBand - firstInBand + 1; - m_clipLines[y].spans = m_spans + count; - m_clipLines[y].count = lastInBand - firstInBand + 1; + for (int r = firstInBand; r <= lastInBand; ++r) { + const QRect &currRect = rects.at(r); + QSpan *span = m_spans + count; + span->x = currRect.x(); + span->len = currRect.width(); + span->y = y; + span->coverage = 255; + ++count; + } + ++y; + } - for (int r = firstInBand; r <= lastInBand; ++r) { - const QRect &currRect = rects.at(r); - QSpan *span = m_spans + count; - span->x = currRect.x(); - span->len = currRect.width(); - span->y = y; - span->coverage = 255; - ++count; + firstInBand = lastInBand + 1; } - ++y; - } - firstInBand = lastInBand + 1; - } + Q_ASSERT(count <= allocated); - Q_ASSERT(count <= allocated); + while (y < clipSpanHeight) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } - while (y < clipSpanHeight) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; + } + } QT_CATCH(...) { + free(m_spans); + QT_RETHROW; } - + } QT_CATCH(...) { + free(m_clipLines); + QT_RETHROW; } } @@ -4633,8 +4657,10 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData) &newspans, newClip->allocated - newClip->count); newClip->count = newspans - newClip->m_spans; if (spans < end) { + QSpan *newSpan = (QSpan *)realloc(newClip->m_spans, newClip->allocated*2*sizeof(QSpan)); + Q_CHECK_PTR(newSpan); + newClip->m_spans = newSpan; newClip->allocated *= 2; - newClip->m_spans = (QSpan *)realloc(newClip->m_spans, newClip->allocated*sizeof(QSpan)); } } } diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index ed9b858..81dce4f 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -179,8 +179,7 @@ void QPaintEngineExPrivate::replayClipOperations() if (!p || !p->d_ptr) return; - QPainterPrivate *pp = p->d_ptr; - QList<QPainterClipInfo> clipInfo = pp->state->clipInfo; + QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo; QTransform transform = q->state()->matrix; @@ -231,8 +230,7 @@ bool QPaintEngineExPrivate::hasClipOperations() const if (!p || !p->d_ptr) return false; - QPainterPrivate *pp = p->d_ptr; - QList<QPainterClipInfo> clipInfo = pp->state->clipInfo; + QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo; return !clipInfo.isEmpty(); } diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 7705cc1..22354bc 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -55,10 +55,10 @@ #include <QtGui/qpaintengine.h> -#include "qpaintengine_p.h" -#include "qstroker_p.h" -#include "qpainter_p.h" -#include "qvectorpath_p.h" +#include <private/qpaintengine_p.h> +#include <private/qstroker_p.h> +#include <private/qpainter_p.h> +#include <private/qvectorpath_p.h> QT_BEGIN_HEADER diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 9c7a7fa..76e2fcc 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -75,14 +75,26 @@ QT_BEGIN_NAMESPACE #define QGradient_StretchToDevice 0x10000000 #define QPaintEngine_OpaqueBackground 0x40000000 -// use the same rounding as in qrasterizer.cpp (6 bit fixed point) -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - // #define QT_DEBUG_DRAW #ifdef QT_DEBUG_DRAW bool qt_show_painter_debug_output = true; #endif +class QPainterPrivateCleaner +{ +public: + static inline void cleanup(QPainterPrivate *d) + { + delete d; + } + + static inline void reset(QPainterPrivate *&d, QPainterPrivate *other) + { + delete d; + d = other; + } +}; + extern QPixmap qt_pixmapForBrush(int style, bool invert); void qt_format_text(const QFont &font, @@ -259,14 +271,17 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) // in 99% of all cases). E.g: A renders B which renders C which renders D. sp->d_ptr->d_ptrs_size = 4; sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *)); + Q_CHECK_PTR(sp->d_ptr->d_ptrs); } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) { // However, to support corner cases we grow the array dynamically if needed. sp->d_ptr->d_ptrs_size <<= 1; const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *); - sp->d_ptr->d_ptrs = (QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize); + QPainterPrivate ** newPointers = (QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize); + Q_CHECK_PTR(newPointers); + sp->d_ptr->d_ptrs = newPointers; } - sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr; - q->d_ptr = sp->d_ptr; + sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data(); + q->d_ptr.data_ptr() = sp->d_ptr.data(); Q_ASSERT(q->d_ptr->state); @@ -319,7 +334,7 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q) d_ptrs[refcount - 1] = 0; q->restore(); - q->d_ptr = original; + q->d_ptr.data_ptr() = original; if (emulationEngine) { extended = emulationEngine->real_engine; @@ -1354,8 +1369,8 @@ void QPainterPrivate::updateState(QPainterState *newState) */ QPainter::QPainter() + : d_ptr(new QPainterPrivate(this)) { - d_ptr = new QPainterPrivate(this); } /*! @@ -1387,7 +1402,7 @@ QPainter::QPainter(QPaintDevice *pd) { Q_ASSERT(pd != 0); if (!QPainterPrivate::attachPainterPrivate(this, pd)) { - d_ptr = new QPainterPrivate(this); + d_ptr.reset(new QPainterPrivate(this)); begin(pd); } Q_ASSERT(d_ptr); @@ -1399,11 +1414,14 @@ QPainter::QPainter(QPaintDevice *pd) QPainter::~QPainter() { d_ptr->inDestructor = true; - if (isActive()) - end(); - else if (d_ptr->refcount > 1) - d_ptr->detachPainterPrivate(this); - + QT_TRY { + if (isActive()) + end(); + else if (d_ptr->refcount > 1) + d_ptr->detachPainterPrivate(this); + } QT_CATCH(...) { + // don't throw anything in the destructor. + } if (d_ptr) { // Make sure we haven't messed things up. Q_ASSERT(d_ptr->inDestructor); @@ -1411,7 +1429,6 @@ QPainter::~QPainter() Q_ASSERT(d_ptr->refcount == 1); if (d_ptr->d_ptrs) free(d_ptr->d_ptrs); - delete d_ptr; } } @@ -5686,7 +5703,6 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif engine.justify(line); } QFixed x = QFixed::fromReal(p.x()); - QFixed ox = x; for (int i = 0; i < nItems; ++i) { int item = visualOrder[i]; @@ -7412,8 +7428,21 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) void qt_painter_removePaintDevice(QPaintDevice *dev) { - QMutexLocker locker(globalRedirectionsMutex()); - if(QPaintDeviceRedirectionList *redirections = globalRedirections()) { + QMutex *mutex = 0; + QT_TRY { + mutex = globalRedirectionsMutex(); + } QT_CATCH(...) { + // ignore the missing mutex, since we could be called from + // a destructor, and destructors shall not throw + } + QMutexLocker locker(mutex); + QPaintDeviceRedirectionList *redirections = 0; + QT_TRY { + redirections = globalRedirections(); + } QT_CATCH(...) { + // do nothing - code below is safe with redirections being 0. + } + if (redirections) { for (int i = 0; i < redirections->size(); ) { if(redirections->at(i) == dev || redirections->at(i).replacement == dev) redirections->removeAt(i); diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index e9c35ee..c81f5d4 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -45,6 +45,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qrect.h> #include <QtCore/qpoint.h> +#include <QtCore/qscopedpointer.h> #include <QtGui/qpixmap.h> #include <QtGui/qimage.h> #include <QtGui/qtextoption.h> @@ -78,6 +79,8 @@ class QTextItem; class QMatrix; class QTransform; +class QPainterPrivateCleaner; + class Q_GUI_EXPORT QPainter { Q_DECLARE_PRIVATE(QPainter) @@ -497,7 +500,7 @@ private: Q_DISABLE_COPY(QPainter) friend class Q3Painter; - QPainterPrivate *d_ptr; + QScopedCustomPointer<QPainterPrivate, QPainterPrivateCleaner> d_ptr; friend class QFontEngine; friend class QFontEngineBox; diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 8e9d61e..4364772 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -63,7 +63,7 @@ #include "QtGui/qpaintengine.h" #include <QtCore/qhash.h> -#include "qpen_p.h" +#include <private/qpen_p.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 09972b0..f9fd61e 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -73,6 +73,24 @@ QT_BEGIN_NAMESPACE +struct QPainterPathPrivateHandler +{ + static inline void cleanup(QPainterPathPrivate *d) + { + // note - we must up-cast to QPainterPathData since QPainterPathPrivate + // has a non-virtual destructor! + if (d && !d->ref.deref()) + delete static_cast<QPainterPathData *>(d); + } + + static inline void reset(QPainterPathPrivate *&d, QPainterPathPrivate *other) + { + QPainterPathPrivate *oldD = d; + d = other; + cleanup(oldD); + } +}; + // This value is used to determine the length of control point vectors // when approximating arc segments as curves. The factor is multiplied // with the radius of the circle. @@ -506,10 +524,10 @@ QPainterPath::QPainterPath() \sa operator=() */ QPainterPath::QPainterPath(const QPainterPath &other) - : d_ptr(other.d_ptr) + : d_ptr(other.d_ptr.data()) { - if (d_func()) - d_func()->ref.ref(); + if (d_ptr) + d_ptr->ref.ref(); } /*! @@ -530,9 +548,7 @@ QPainterPath::QPainterPath(const QPointF &startPoint) void QPainterPath::detach_helper() { QPainterPathPrivate *data = new QPainterPathData(*d_func()); - if (d_ptr && !d_ptr->ref.deref()) - delete d_ptr; - d_ptr = data; + d_ptr.reset(data); } /*! @@ -544,9 +560,7 @@ void QPainterPath::ensureData_helper() data->elements.reserve(16); QPainterPath::Element e = { 0, 0, QPainterPath::MoveToElement }; data->elements << e; - if (d_ptr && !d_ptr->ref.deref()) - delete d_ptr; - d_ptr = data; + d_ptr.reset(data); Q_ASSERT(d_ptr != 0); } @@ -563,9 +577,7 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other) QPainterPathPrivate *data = other.d_func(); if (data) data->ref.ref(); - if (d_ptr && !d_ptr->ref.deref()) - delete d_ptr; - d_ptr = data; + d_ptr.reset(data); } return *this; } @@ -575,8 +587,6 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other) */ QPainterPath::~QPainterPath() { - if (d_func() && !d_func()->ref.deref()) - delete d_func(); } /*! @@ -2464,7 +2474,6 @@ QPainterPathStroker::QPainterPathStroker() */ QPainterPathStroker::~QPainterPathStroker() { - delete d_ptr; } diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 846bd8a..5068739 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -47,6 +47,7 @@ #include <QtCore/qrect.h> #include <QtCore/qline.h> #include <QtCore/qvector.h> +#include <QtCore/qscopedpointer.h> QT_BEGIN_HEADER @@ -56,6 +57,7 @@ QT_MODULE(Gui) class QFont; class QPainterPathPrivate; +struct QPainterPathPrivateHandler; class QPainterPathData; class QPainterPathStrokerPrivate; class QPolygonF; @@ -201,7 +203,7 @@ public: QPainterPath &operator-=(const QPainterPath &other); private: - QPainterPathPrivate *d_ptr; + QScopedCustomPointer<QPainterPathPrivate, QPainterPathPrivateHandler> d_ptr; inline void ensureData() { if (!d_ptr) ensureData_helper(); } void ensureData_helper(); @@ -211,7 +213,7 @@ private: void computeBoundingRect() const; void computeControlPointRect() const; - QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr); } + QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr.data()); } friend class QPainterPathData; friend class QPainterPathStroker; @@ -235,6 +237,7 @@ public: friend class QPainterPathStrokerPrivate; friend class QMatrix; friend class QTransform; + friend struct QPainterPathPrivateHandler; #ifndef QT_NO_DATASTREAM friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPainterPath &); friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPainterPath &); @@ -285,7 +288,7 @@ public: private: friend class QX11PaintEngine; - QPainterPathStrokerPrivate *d_ptr; + QScopedPointer<QPainterPathStrokerPrivate> d_ptr; }; inline void QPainterPath::moveTo(qreal x, qreal y) diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h index b2ab3b4..784b75d 100644 --- a/src/gui/painting/qpathclipper_p.h +++ b/src/gui/painting/qpathclipper_p.h @@ -160,8 +160,6 @@ public: Direction directionTo(int vertex) const; int vertex(Direction direction) const; - bool isBezier() const; - private: int m_next[2][2]; }; @@ -347,11 +345,6 @@ inline int QPathEdge::vertex(Direction direction) const return direction == Backward ? first : second; } -inline bool QPathEdge::isBezier() const -{ - return bezier >= 0; -} - inline QPathVertex::QPathVertex(const QPointF &p, int e) : edge(e) , x(p.x()) diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp index 02a5a02..bc54b5c 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -712,7 +712,6 @@ QPrinter::~QPrinter() #ifndef QT_NO_PRINTPREVIEWWIDGET delete d->previewEngine; #endif - delete d; } /*! diff --git a/src/gui/painting/qprinter.h b/src/gui/painting/qprinter.h index 90ed20d..25c2f0c 100644 --- a/src/gui/painting/qprinter.h +++ b/src/gui/painting/qprinter.h @@ -42,8 +42,9 @@ #ifndef QPRINTER_H #define QPRINTER_H -#include <QtGui/qpaintdevice.h> #include <QtCore/qstring.h> +#include <QtCore/qscopedpointer.h> +#include <QtGui/qpaintdevice.h> QT_BEGIN_HEADER @@ -288,7 +289,7 @@ private: Q_DISABLE_COPY(QPrinter) - QPrinterPrivate *d_ptr; + QScopedPointer<QPrinterPrivate> d_ptr; friend class QPrintDialogPrivate; friend class QAbstractPrintDialog; diff --git a/src/gui/painting/qprinterinfo.h b/src/gui/painting/qprinterinfo.h index eafdec5..c34e591 100644 --- a/src/gui/painting/qprinterinfo.h +++ b/src/gui/painting/qprinterinfo.h @@ -53,6 +53,7 @@ QT_MODULE(Gui) #ifndef QT_NO_PRINTER class QPrinterInfoPrivate; +class QPrinterInfoPrivateCleanup; class Q_GUI_EXPORT QPrinterInfo { Q_DECLARE_PRIVATE(QPrinterInfo) @@ -76,7 +77,7 @@ public: private: QPrinterInfo(const QString& name); - QPrinterInfoPrivate* d_ptr; + QScopedCustomPointer<QPrinterInfoPrivate, QPrinterInfoPrivateCleanup> d_ptr; }; #endif // QT_NO_PRINTER diff --git a/src/gui/painting/qprinterinfo_mac.cpp b/src/gui/painting/qprinterinfo_mac.cpp index c84271c..6932015 100644 --- a/src/gui/painting/qprinterinfo_mac.cpp +++ b/src/gui/painting/qprinterinfo_mac.cpp @@ -65,6 +65,22 @@ private: static QPrinterInfoPrivate nullQPrinterInfoPrivate; +class QPrinterInfoPrivateCleanup +{ +public: + static inline void cleanup(QPrinterInfoPrivate *d) + { + if (d != &nullQPrinterInfoPrivate) + delete d; + } + + static inline void reset(QPrinterInfoPrivate *&d, QPrinterInfoPrivate *other) + { + cleanup(d); + d = other; + } +}; + extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size); ///////////////////////////////////////////////////////////////////////////// @@ -106,8 +122,8 @@ QPrinterInfo QPrinterInfo::defaultPrinter(){ ///////////////////////////////////////////////////////////////////////////// QPrinterInfo::QPrinterInfo(const QPrinter& prn) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; QList<QPrinterInfo> list = availablePrinters(); for (int c = 0; c < list.size(); ++c) { if (prn.printerName() == list[c].printerName()) { @@ -115,39 +131,33 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn) return; } } - - *this = QPrinterInfo(); } QPrinterInfo::~QPrinterInfo() { - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; } QPrinterInfo::QPrinterInfo() + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; } QPrinterInfo::QPrinterInfo(const QString& name) + : d_ptr(new QPrinterInfoPrivate(name)) { - d_ptr = new QPrinterInfoPrivate(name); d_ptr->q_ptr = this; } QPrinterInfo::QPrinterInfo(const QPrinterInfo& src) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; *this = src; } QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src) { Q_ASSERT(d_ptr); - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; - d_ptr = new QPrinterInfoPrivate(*src.d_ptr); + d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr)); d_ptr->q_ptr = this; return *this; } diff --git a/src/gui/painting/qprinterinfo_unix.cpp b/src/gui/painting/qprinterinfo_unix.cpp index 1ce5e1e..b9f1f3b 100644 --- a/src/gui/painting/qprinterinfo_unix.cpp +++ b/src/gui/painting/qprinterinfo_unix.cpp @@ -82,6 +82,22 @@ private: static QPrinterInfoPrivate nullQPrinterInfoPrivate; +class QPrinterInfoPrivateCleanup +{ +public: + static inline void cleanup(QPrinterInfoPrivate *d) + { + if (d != &nullQPrinterInfoPrivate) + delete d; + } + + static inline void reset(QPrinterInfoPrivate *&d, QPrinterInfoPrivate *other) + { + cleanup(d); + d = other; + } +}; + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -867,19 +883,19 @@ QPrinterInfo QPrinterInfo::defaultPrinter() } QPrinterInfo::QPrinterInfo() + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; } QPrinterInfo::QPrinterInfo(const QPrinterInfo& src) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; *this = src; } QPrinterInfo::QPrinterInfo(const QPrinter& printer) + : d_ptr(new QPrinterInfoPrivate(printer.printerName())) { - d_ptr = new QPrinterInfoPrivate(printer.printerName()); Q_D(QPrinterInfo); d->q_ptr = this; @@ -929,28 +945,23 @@ QPrinterInfo::QPrinterInfo(const QPrinter& printer) #endif // Printer not found. - delete d; - d_ptr = &nullQPrinterInfoPrivate; + d_ptr.reset(&nullQPrinterInfoPrivate); } QPrinterInfo::QPrinterInfo(const QString& name) + : d_ptr(new QPrinterInfoPrivate(name)) { - d_ptr = new QPrinterInfoPrivate(name); d_ptr->q_ptr = this; } QPrinterInfo::~QPrinterInfo() { - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; } QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src) { Q_ASSERT(d_ptr); - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; - d_ptr = new QPrinterInfoPrivate(*src.d_ptr); + d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr)); d_ptr->q_ptr = this; return *this; } diff --git a/src/gui/painting/qprinterinfo_win.cpp b/src/gui/painting/qprinterinfo_win.cpp index bea2e3a..4a92d30 100644 --- a/src/gui/painting/qprinterinfo_win.cpp +++ b/src/gui/painting/qprinterinfo_win.cpp @@ -69,6 +69,22 @@ private: static QPrinterInfoPrivate nullQPrinterInfoPrivate; +class QPrinterInfoPrivateCleanup +{ +public: + static inline void cleanup(QPrinterInfoPrivate *d) + { + if (d != &nullQPrinterInfoPrivate) + delete d; + } + + static inline void reset(QPrinterInfoPrivate *&d, QPrinterInfoPrivate *other) + { + cleanup(d); + d = other; + } +}; + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -125,25 +141,25 @@ QPrinterInfo QPrinterInfo::defaultPrinter() ///////////////////////////////////////////////////////////////////////////// QPrinterInfo::QPrinterInfo() + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; } QPrinterInfo::QPrinterInfo(const QString& name) + : d_ptr(new QPrinterInfoPrivate(name)) { - d_ptr = new QPrinterInfoPrivate(name); d_ptr->q_ptr = this; } QPrinterInfo::QPrinterInfo(const QPrinterInfo& src) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; *this = src; } QPrinterInfo::QPrinterInfo(const QPrinter& prn) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; QList<QPrinterInfo> list = availablePrinters(); for (int c = 0; c < list.size(); ++c) { if (prn.printerName() == list[c].printerName()) { @@ -157,16 +173,12 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn) QPrinterInfo::~QPrinterInfo() { - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; } QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src) { Q_ASSERT(d_ptr); - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; - d_ptr = new QPrinterInfoPrivate(*src.d_ptr); + d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr)); d_ptr->q_ptr = this; return *this; } diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index 58e4b4e..6d15271 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -436,8 +436,11 @@ void QScanConverter::end() inline void QScanConverter::allocate(int size) { if (m_alloc < size) { - m_alloc = qMax(size, 2 * m_alloc); - m_intersections = (Intersection *)realloc(m_intersections, m_alloc * sizeof(Intersection)); + int newAlloc = qMax(size, 2 * m_alloc); + Intersection *newIntersections = (Intersection *)realloc(m_intersections, newAlloc * sizeof(Intersection)); + Q_CHECK_PTR(newIntersections); + m_alloc = newAlloc; + m_intersections = newIntersections; } } diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index d59f3ff..47d24b3 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -3163,6 +3163,7 @@ static void InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline, { tmpSLLBlock = (ScanLineListBlock *)malloc(sizeof(ScanLineListBlock)); + Q_CHECK_PTR(tmpSLLBlock); (*SLLBlock)->next = tmpSLLBlock; tmpSLLBlock->next = (ScanLineListBlock *)NULL; *SLLBlock = tmpSLLBlock; @@ -3549,6 +3550,8 @@ static void PtsToRegion(register int numFullPtBlocks, register int iCurPtBlock, * Scan converts a polygon by returning a run-length * encoding of the resultant bitmap -- the run-length * encoding is in the form of an array of rectangles. + * + * Can return 0 in case of errors. */ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) //Point *Pts; /* the pts */ @@ -3620,75 +3623,28 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) } - if (rule == EvenOddRule) { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; ++y) { - - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - + QT_TRY { + if (rule == EvenOddRule) { /* - * for each active edge + * for each scanline */ - while (pAET) { - pts->setX(pAET->bres.minor_axis); - pts->setY(y); - ++pts; - ++iPts; + for (y = ET.ymin; y < ET.ymax; ++y) { /* - * send out the buffer + * Add a new edge to the active edge table when we + * get to the next edge. */ - if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK)); - tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data); - curPtBlock->next = tmpPtBlock; - curPtBlock = tmpPtBlock; - pts = curPtBlock->pts; - ++numFullPtBlocks; - iPts = 0; + if (pSLL && y == pSLL->scanline) { + loadAET(&AET, pSLL->edgelist); + pSLL = pSLL->next; } - EVALUATEEDGEEVENODD(pAET, pPrevAET, y) - } - InsertionSort(&AET); - } - } else { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; ++y) { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - computeWAET(&AET); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - pWETE = pAET; + pPrevAET = &AET; + pAET = AET.next; - /* - * for each active edge - */ - while (pAET) { /* - * add to the buffer only those edges that - * are in the Winding active edge table. + * for each active edge */ - if (pWETE == pAET) { + while (pAET) { pts->setX(pAET->bres.minor_axis); pts->setY(y); ++pts; @@ -3698,7 +3654,8 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK))); + tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK)); + Q_CHECK_PTR(tmpPtBlock); tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data); curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; @@ -3706,21 +3663,81 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) ++numFullPtBlocks; iPts = 0; } - pWETE = pWETE->nextWETE; + EVALUATEEDGEEVENODD(pAET, pPrevAET, y) } - EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) + InsertionSort(&AET); } - + } else { /* - * recompute the winding active edge table if - * we just resorted or have exited an edge. + * for each scanline */ - if (InsertionSort(&AET) || fixWAET) { - computeWAET(&AET); - fixWAET = false; + for (y = ET.ymin; y < ET.ymax; ++y) { + /* + * Add a new edge to the active edge table when we + * get to the next edge. + */ + if (pSLL && y == pSLL->scanline) { + loadAET(&AET, pSLL->edgelist); + computeWAET(&AET); + pSLL = pSLL->next; + } + pPrevAET = &AET; + pAET = AET.next; + pWETE = pAET; + + /* + * for each active edge + */ + while (pAET) { + /* + * add to the buffer only those edges that + * are in the Winding active edge table. + */ + if (pWETE == pAET) { + pts->setX(pAET->bres.minor_axis); + pts->setY(y); + ++pts; + ++iPts; + + /* + * send out the buffer + */ + if (iPts == NUMPTSTOBUFFER) { + tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK))); + tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data); + curPtBlock->next = tmpPtBlock; + curPtBlock = tmpPtBlock; + pts = curPtBlock->pts; + ++numFullPtBlocks; + iPts = 0; + } + pWETE = pWETE->nextWETE; + } + EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) + } + + /* + * recompute the winding active edge table if + * we just resorted or have exited an edge. + */ + if (InsertionSort(&AET) || fixWAET) { + computeWAET(&AET); + fixWAET = false; + } } } + } QT_CATCH(...) { + FreeStorage(SLLBlock.next); + PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); + for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { + tmpPtBlock = curPtBlock->next; + free(curPtBlock); + curPtBlock = tmpPtBlock; + } + free(pETEs); + return 0; // this function returns 0 in case of an error } + FreeStorage(SLLBlock.next); PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { @@ -3919,11 +3936,10 @@ QRegion &QRegion::operator=(const QRegion &r) /*! \internal */ - QRegion QRegion::copy() const { QRegion r; - QRegionData *x = new QRegionData; + QScopedPointer<QRegionData> x(new QRegionData); x->ref = 1; #if defined(Q_WS_X11) x->rgn = 0; @@ -3937,7 +3953,7 @@ QRegion QRegion::copy() const x->qt_rgn = new QRegionPrivate; if (!r.d->ref.deref()) cleanUp(r.d); - r.d = x; + r.d = x.take(); return r; } diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index 84024ce..8a56d54 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -59,7 +59,7 @@ QT_MODULE(Gui) template <class T> class QVector; class QVariant; -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) struct QRegionPrivate; #endif @@ -200,7 +200,7 @@ private: #elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove. #endif -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) QRegionPrivate *qt_rgn; #endif }; diff --git a/src/gui/painting/qregion_s60.cpp b/src/gui/painting/qregion_s60.cpp new file mode 100644 index 0000000..4d96910 --- /dev/null +++ b/src/gui/painting/qregion_s60.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbitmap.h" +#include "qbuffer.h" +#include "qimage.h" +#include "qpolygon.h" +#include "qregion.h" + +QT_BEGIN_NAMESPACE + +QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; + +QT_END_NAMESPACE diff --git a/src/gui/painting/qtessellator.cpp b/src/gui/painting/qtessellator.cpp index 31ee4f3..711f997 100644 --- a/src/gui/painting/qtessellator.cpp +++ b/src/gui/painting/qtessellator.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE #ifdef DEBUG #define QDEBUG qDebug #else -#define QDEBUG if (1); else qDebug +#define QDEBUG if (1){} else qDebug #endif static const bool emit_clever = true; @@ -703,7 +703,6 @@ struct QCoincidingEdge { } }; - static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2) { if (e1.before) { diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index 9264c9c..df49500 100644 --- a/src/gui/painting/qvectorpath_p.h +++ b/src/gui/painting/qvectorpath_p.h @@ -55,9 +55,9 @@ #include <QtGui/qpaintengine.h> -#include "qpaintengine_p.h" -#include "qstroker_p.h" -#include "qpainter_p.h" +#include <private/qpaintengine_p.h> +#include <private/qstroker_p.h> +#include <private/qpainter_p.h> QT_BEGIN_HEADER diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index eddbfd2..863237b 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -105,8 +105,6 @@ QRasterWindowSurface::~QRasterWindowSurface() #endif if (d_ptr->image) delete d_ptr->image; - - delete d_ptr; } @@ -284,6 +282,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi CGContextFlush(context); #endif #endif + +#ifdef Q_OS_SYMBIAN + Q_UNUSED(widget); + Q_UNUSED(rgn); + Q_UNUSED(offset); +#endif } void QRasterWindowSurface::setGeometry(const QRect &rect) diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h index 996aaef..b3256b3 100644 --- a/src/gui/painting/qwindowsurface_raster_p.h +++ b/src/gui/painting/qwindowsurface_raster_p.h @@ -109,7 +109,7 @@ public: private: void prepareBuffer(QImage::Format format, QWidget *widget); Q_DECLARE_PRIVATE(QRasterWindowSurface) - QRasterWindowSurfacePrivate *d_ptr; + QScopedPointer<QRasterWindowSurfacePrivate> d_ptr; }; QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp new file mode 100644 index 0000000..e81adcc --- /dev/null +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> // for Q_WS_WIN define (non-PCH) + +#include <QtGui/qpaintdevice.h> +#include <private/qwidget_p.h> +#include "qwindowsurface_s60_p.h" +#include "qt_s60_p.h" +#include "private/qdrawhelper_p.h" + +QT_BEGIN_NAMESPACE + +struct QS60WindowSurfacePrivate +{ + QImage device; + CFbsBitmap *bitmap; + uchar* bytes; + + // Since only one CFbsBitmap is allowed to be locked at a time, this is static. + static QS60WindowSurface* lockedSurface; +}; +QS60WindowSurface* QS60WindowSurfacePrivate::lockedSurface = NULL; + +QS60WindowSurface::QS60WindowSurface(QWidget* widget) + : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) +{ + d_ptr->bytes = 0; + d_ptr->bitmap = 0; + + TDisplayMode mode = S60->screenDevice()->DisplayMode(); + bool isOpaque = qt_widget_private(widget)->isOpaque; + if (mode == EColor16MA && isOpaque) + mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated + else if (mode == EColor16MU && !isOpaque) + mode = EColor16MA; // Try for transparency anyway + + + // We create empty CFbsBitmap here -> it will be resized in setGeometry + d_ptr->bitmap = new (ELeave) CFbsBitmap; + User::LeaveIfError( d_ptr->bitmap->Create(TSize(0, 0), mode ) ); + + updatePaintDeviceOnBitmap(); + + setStaticContentsSupport(true); +} + +QS60WindowSurface::~QS60WindowSurface() +{ + // Ensure that locking and unlocking of this surface were symmetrical + Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface != this); + + delete d_ptr->bitmap; + delete d_ptr; +} + +void QS60WindowSurface::beginPaint(const QRegion &rgn) +{ + if(!d_ptr->bitmap) + return; + + Q_ASSERT(!QS60WindowSurfacePrivate::lockedSurface); + QS60WindowSurfacePrivate::lockedSurface = this; + lockBitmapHeap(); + + if (!qt_widget_private(window())->isOpaque) { + QRgb *data = reinterpret_cast<QRgb *>(d_ptr->device.bits()); + const int row_stride = d_ptr->device.bytesPerLine() / 4; + + const QVector<QRect> rects = rgn.rects(); + for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { + const int x_start = it->x(); + const int width = it->width(); + + const int y_start = it->y(); + const int height = it->height(); + + QRgb *row = data + row_stride * y_start; + for (int y = 0; y < height; ++y) { + qt_memfill(row + x_start, 0U, width); + row += row_stride; + } + } + } +} + +void QS60WindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &) +{ + const QVector<QRect> subRects = region.rects(); + for (int i = 0; i < subRects.count(); ++i) { + TRect tr = qt_QRect2TRect(subRects[i]); + widget->winId()->DrawNow(tr); + } +} + +bool QS60WindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + QRect rect = area.boundingRect(); + + if (dx == 0 && dy == 0) + return false; + + if (d_ptr->device.isNull()) + return false; + + CFbsBitmapDevice *bitmapDevice = CFbsBitmapDevice::NewL(d_ptr->bitmap); + CBitmapContext *bitmapContext; + TInt err = bitmapDevice->CreateBitmapContext(bitmapContext); + if (err != KErrNone) { + CBase::Delete(bitmapDevice); + return false; + } + bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect)); + CBase::Delete(bitmapContext); + CBase::Delete(bitmapDevice); + return true; +} + +void QS60WindowSurface::endPaint(const QRegion & /* rgn */) +{ + if(!d_ptr->bitmap) + return; + + Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface); + unlockBitmapHeap(); + QS60WindowSurfacePrivate::lockedSurface = NULL; +} + +QPaintDevice* QS60WindowSurface::paintDevice() +{ + return &d_ptr->device; +} + +void QS60WindowSurface::setGeometry(const QRect& rect) +{ + if (rect == geometry()) + return; + + QWindowSurface::setGeometry(rect); + + TRect nativeRect(qt_QRect2TRect(rect)); + User::LeaveIfError(d_ptr->bitmap->Resize(nativeRect.Size())); + + if (!rect.isNull()) + updatePaintDeviceOnBitmap(); +} + +void QS60WindowSurface::lockBitmapHeap() +{ + if (!QS60WindowSurfacePrivate::lockedSurface) + return; + + // Get some local variables to make later code lines more clear to read + CFbsBitmap*& bitmap = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap; + QImage& device = QS60WindowSurfacePrivate::lockedSurface->d_ptr->device; + uchar*& bytes = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bytes; + + bitmap->LockHeap(); + uchar *newBytes = (uchar*)bitmap->DataAddress(); + if (newBytes != bytes) { + bytes = newBytes; + + // Get some values for QImage creation + TDisplayMode mode = bitmap->DisplayMode(); + if (mode == EColor16MA + && qt_widget_private(QS60WindowSurfacePrivate::lockedSurface->window())->isOpaque) + mode = EColor16MU; + QImage::Format format = qt_TDisplayMode2Format( mode ); + TSize bitmapSize = bitmap->SizeInPixels(); + int bytesPerLine = CFbsBitmap::ScanLineLength( bitmapSize.iWidth, mode); + + device = QImage( bytes, bitmapSize.iWidth, bitmapSize.iHeight, bytesPerLine, format ); + } +} + +void QS60WindowSurface::unlockBitmapHeap() +{ + if (!QS60WindowSurfacePrivate::lockedSurface) + return; + + QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap->UnlockHeap(); +} + +void QS60WindowSurface::updatePaintDeviceOnBitmap() +{ + // This forces the actual device to be updated based on CFbsBitmap + beginPaint(QRegion()); + endPaint(QRegion()); +} + +CFbsBitmap *QS60WindowSurface::symbianBitmap() const +{ + return d_ptr->bitmap; +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_s60_p.h b/src/gui/painting/qwindowsurface_s60_p.h new file mode 100644 index 0000000..40a866d --- /dev/null +++ b/src/gui/painting/qwindowsurface_s60_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_S60_P_H +#define QWINDOWSURFACE_S60_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qglobal.h> +#include "private/qwindowsurface_p.h" + +class CFbsBitmap; + +QT_BEGIN_NAMESPACE + +struct QS60WindowSurfacePrivate; + +class QS60WindowSurface : public QWindowSurface +{ +public: + QS60WindowSurface(QWidget *widget); + ~QS60WindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion &); + void endPaint(const QRegion &); + + void setGeometry(const QRect &rect); + + static void lockBitmapHeap(); + static void unlockBitmapHeap(); + + CFbsBitmap *symbianBitmap() const; + +private: + void updatePaintDeviceOnBitmap(); + +private: + QS60WindowSurfacePrivate* d_ptr; + +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSURFACE_S60_P_H |