/**************************************************************************** | |
** | |
** 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$ | |
** GNU Lesser General Public License Usage | |
** 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. | |
** | |
** 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. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $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_raster_symbian_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 = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new | |
qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); | |
QSymbianRasterPixmapData *data = new QSymbianRasterPixmapData(QPixmapData::PixmapType); | |
if (data) { | |
data->fromSymbianBitmap(bitmap, true); | |
d_ptr->device = QPixmap(data); | |
} | |
setStaticContentsSupport(true); | |
} | |
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)) { | |
QSymbianRasterPixmapData *pixmapData = static_cast<QSymbianRasterPixmapData *>(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<QSymbianRasterPixmapData *>(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; | |
QSymbianRasterPixmapData *data = static_cast<QSymbianRasterPixmapData*>(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; | |
QSymbianRasterPixmapData *data = static_cast<QSymbianRasterPixmapData*>(d_ptr->device.data_ptr().data()); | |
data->resize(rect.width(), rect.height()); | |
QWindowSurface::setGeometry(rect); | |
} | |
CFbsBitmap* QS60WindowSurface::symbianBitmap() const | |
{ | |
QSymbianRasterPixmapData *data = static_cast<QSymbianRasterPixmapData*>(d_ptr->device.data_ptr().data()); | |
return data->cfbsBitmap; | |
} | |
QT_END_NAMESPACE | |