summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qwindowsurface_s60.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting/qwindowsurface_s60.cpp')
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp254
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 &region, 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
+