diff options
Diffstat (limited to 'src/gui/painting/qwindowsurface_s60.cpp')
-rw-r--r-- | src/gui/painting/qwindowsurface_s60.cpp | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp new file mode 100644 index 0000000000..9fa01edf7d --- /dev/null +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> // for Q_WS_WIN define (non-PCH) + +#include <QtGui/qpaintdevice.h> +#include <private/qwidget_p.h> +#include <private/qwindowsurface_s60_p.h> +#include <private/qpixmap_s60_p.h> +#include <private/qt_s60_p.h> +#include <private/qapplication_p.h> +#include <private/qdrawhelper_p.h> + +#ifdef QT_GRAPHICSSYSTEM_RUNTIME +#include <private/qgraphicssystem_runtime_p.h> +#endif + +QT_BEGIN_NAMESPACE + +struct QS60WindowSurfacePrivate +{ + QPixmap device; + QList<QImage*> bufferImages; +}; + +TDisplayMode displayMode(bool opaque) +{ + TDisplayMode mode = S60->screenDevice()->DisplayMode(); + if (opaque) { + mode = EColor16MU; + } else { + if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) + mode = Q_SYMBIAN_ECOLOR16MAP; // Symbian^3 WServ has support for ARGB32_PRE + else + mode = EColor16MA; // Symbian prior to Symbian^3 sw accelerates EColor16MA + } + return mode; +} + +bool blitWriteAlpha(QWidgetPrivate *widgetPrivate) +{ + QWExtra *extra = widgetPrivate->extraData(); + return extra ? extra->nativePaintMode == QWExtra::BlitWriteAlpha : false; +} + +QS60WindowSurface::QS60WindowSurface(QWidget* widget) + : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) +{ + QWidgetPrivate *widgetPrivate = qt_widget_private(widget); + const bool opaque = widgetPrivate->isOpaque && !blitWriteAlpha(widgetPrivate); + TDisplayMode mode = displayMode(opaque); + // We create empty CFbsBitmap here -> it will be resized in setGeometry + CFbsBitmap *bitmap = new CFbsBitmap; // CBase derived object needs check on new + Q_CHECK_PTR(bitmap); + qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); + + QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType); + if (data) { + data->fromSymbianBitmap(bitmap, true); + d_ptr->device = QPixmap(data); + } +} + +QS60WindowSurface::~QS60WindowSurface() +{ +#if defined(QT_GRAPHICSSYSTEM_RUNTIME) && defined(Q_SYMBIAN_SUPPORTS_SURFACES) + if(QApplicationPrivate::runtime_graphics_system) { + QRuntimeGraphicsSystem *runtimeGraphicsSystem = + static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system); + if(runtimeGraphicsSystem->graphicsSystemName() == QLatin1String("openvg")) { + + // Graphics system has been switched from raster to openvg. + // Issue empty redraw to clear the UI surface + + QWidget *w = window(); + if (w->testAttribute(Qt::WA_WState_Created)) { + RWindow *const window = static_cast<RWindow *>(w->winId()->DrawableWindow()); + window->BeginRedraw(); + window->EndRedraw(); + } + } + } +#endif + + delete d_ptr; +} + +void QS60WindowSurface::beginPaint(const QRegion &rgn) +{ +#ifdef Q_SYMBIAN_SUPPORTS_SURFACES + S60->wsSession().Finish(); +#endif + + QWidgetPrivate *windowPrivate = qt_widget_private(window()); + if (!windowPrivate->isOpaque || blitWriteAlpha(windowPrivate)) { + QS60PixmapData *pixmapData = static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data()); + + TDisplayMode mode = displayMode(false); + if (pixmapData->cfbsBitmap->DisplayMode() != mode) + pixmapData->convertToDisplayMode(mode); + + pixmapData->beginDataAccess(); + + if (!windowPrivate->isOpaque) { + QPainter p(&pixmapData->image); + p.setCompositionMode(QPainter::CompositionMode_Source); + const QVector<QRect> rects = rgn.rects(); + const QColor blank = Qt::transparent; + for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { + p.fillRect(*it, blank); + } + } + + pixmapData->endDataAccess(); + } +} + +void QS60WindowSurface::endPaint(const QRegion &) +{ + qDeleteAll(d_ptr->bufferImages); + d_ptr->bufferImages.clear(); +} + +QImage* QS60WindowSurface::buffer(const QWidget *widget) +{ + if (widget->window() != window()) + return 0; + + QPaintDevice *pdev = paintDevice(); + if (!pdev) + return 0; + + const QPoint off = offset(widget); + QImage *img = &(static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data())->image); + + QRect rect(off, widget->size()); + rect &= QRect(QPoint(), img->size()); + + if (rect.isEmpty()) + return 0; + + img = new QImage(img->scanLine(rect.y()) + rect.x() * img->depth() / 8, + rect.width(), rect.height(), + img->bytesPerLine(), img->format()); + d_ptr->bufferImages.append(img); + + return img; +} + +void QS60WindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &) +{ + QWidget *window = widget->window(); + Q_ASSERT(window); + QTLWExtra *topExtra = window->d_func()->maybeTopData(); + Q_ASSERT(topExtra); + QRect qr = region.boundingRect(); + if (!topExtra->inExpose) { + topExtra->inExpose = true; // Prevent DrawNow() from calling syncBackingStore() again + TRect tr = qt_QRect2TRect(qr); + widget->winId()->DrawNow(tr); + topExtra->inExpose = false; + } else { + // This handles the case when syncBackingStore updates content outside of the + // original drawing rectangle. This might happen if there are pending update() + // events at the same time as we get a Draw() from Symbian. + QRect drawRect = qt_TRect2QRect(widget->winId()->DrawableWindow()->GetDrawRect()); + if (!drawRect.contains(qr)) + widget->winId()->DrawDeferred(); + } +} + +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; + + QS60PixmapData *data = static_cast<QS60PixmapData*>(d_ptr->device.data_ptr().data()); + data->scroll(dx, dy, rect); + + return true; +} + +QPaintDevice* QS60WindowSurface::paintDevice() +{ + return &d_ptr->device; +} + +void QS60WindowSurface::setGeometry(const QRect& rect) +{ + if (rect == geometry()) + return; + + QS60PixmapData *data = static_cast<QS60PixmapData*>(d_ptr->device.data_ptr().data()); + data->resize(rect.width(), rect.height()); + + QWindowSurface::setGeometry(rect); +} + +QWindowSurface::WindowSurfaceFeatures QS60WindowSurface::features() const +{ + return QWindowSurface::AllFeatures; +} + +CFbsBitmap* QS60WindowSurface::symbianBitmap() const +{ + QS60PixmapData *data = static_cast<QS60PixmapData*>(d_ptr->device.data_ptr().data()); + return data->cfbsBitmap; +} + +QT_END_NAMESPACE + |