summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qwindowsurface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting/qwindowsurface.cpp')
-rw-r--r--src/gui/painting/qwindowsurface.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp
new file mode 100644
index 0000000000..bcb038094f
--- /dev/null
+++ b/src/gui/painting/qwindowsurface.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** 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 <private/qwindowsurface_p.h>
+#include <qwidget.h>
+#include <private/qwidget_p.h>
+#include <private/qbackingstore_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowSurfacePrivate
+{
+public:
+ QWindowSurfacePrivate(QWidget *w) : window(w), staticContentsSupport(false) {}
+
+ QWidget *window;
+ QRect geometry;
+ QRegion staticContents;
+ QList<QImage*> bufferImages;
+ bool staticContentsSupport;
+};
+
+/*!
+ \class QWindowSurface
+ \since 4.3
+ \internal
+ \preliminary
+ \ingroup qws
+
+ \brief The QWindowSurface class provides the drawing area for top-level
+ windows.
+*/
+
+
+/*!
+ \fn void QWindowSurface::beginPaint(const QRegion &region)
+
+ This function is called before painting onto the surface begins,
+ with the \a region in which the painting will occur.
+
+ \sa endPaint(), paintDevice()
+*/
+
+/*!
+ \fn void QWindowSurface::endPaint(const QRegion &region)
+
+ This function is called after painting onto the surface has ended,
+ with the \a region in which the painting was performed.
+
+ \sa beginPaint(), paintDevice()
+*/
+
+/*!
+ \fn void QWindowSurface::flush(QWidget *widget, const QRegion &region,
+ const QPoint &offset)
+
+ Flushes the given \a region from the specified \a widget onto the
+ screen.
+
+ Note that the \a offset parameter is currently unused.
+*/
+
+/*!
+ \fn QPaintDevice* QWindowSurface::paintDevice()
+
+ Implement this function to return the appropriate paint device.
+*/
+
+/*!
+ Constructs an empty surface for the given top-level \a window.
+*/
+QWindowSurface::QWindowSurface(QWidget *window)
+ : d_ptr(new QWindowSurfacePrivate(window))
+{
+ if (window)
+ window->setWindowSurface(this);
+}
+
+/*!
+ Destroys this surface.
+*/
+QWindowSurface::~QWindowSurface()
+{
+ if (d_ptr->window)
+ d_ptr->window->d_func()->extra->topextra->windowSurface = 0;
+ delete d_ptr;
+}
+
+/*!
+ Returns a pointer to the top-level window associated with this
+ surface.
+*/
+QWidget* QWindowSurface::window() const
+{
+ return d_ptr->window;
+}
+
+void QWindowSurface::beginPaint(const QRegion &)
+{
+}
+
+void QWindowSurface::endPaint(const QRegion &)
+{
+// QApplication::syncX();
+ qDeleteAll(d_ptr->bufferImages);
+ d_ptr->bufferImages.clear();
+}
+
+/*!
+ Sets the currently allocated area to be the given \a rect.
+
+ This function is called whenever area covered by the top-level
+ window changes.
+
+ \sa geometry()
+*/
+void QWindowSurface::setGeometry(const QRect &rect)
+{
+ d_ptr->geometry = rect;
+}
+
+/*!
+ Returns the currently allocated area on the screen.
+*/
+QRect QWindowSurface::geometry() const
+{
+ return d_ptr->geometry;
+}
+
+/*!
+ Scrolls the given \a area \a dx pixels to the right and \a dy
+ downward; both \a dx and \a dy may be negative.
+
+ Returns true if the area was scrolled successfully; false otherwise.
+*/
+bool QWindowSurface::scroll(const QRegion &area, int dx, int dy)
+{
+ Q_UNUSED(area);
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+
+ return false;
+}
+
+/*!
+ Returns a QImage pointer which represents the actual buffer the \a widget
+ is drawn into or 0 if this is unavailable.
+
+ You must call beginPaint() before you call this function and the returned
+ pointer is only valid until endPaint() is called.
+*/
+QImage* QWindowSurface::buffer(const QWidget *widget)
+{
+ if (widget->window() != window())
+ return 0;
+
+ QPaintDevice *pdev = paintDevice();
+ if (!pdev || pdev->devType() != QInternal::Image)
+ return 0;
+
+ const QPoint off = offset(widget);
+ QImage *img = static_cast<QImage*>(pdev);
+
+ 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;
+}
+
+/*!
+ Returns a QPixmap generated from the part of the backing store
+ corresponding to \a widget. Returns a null QPixmap if an error
+ occurs. The contents of the pixmap are only defined for the regions
+ of \a widget that have received paint events since the last resize
+ of the backing store.
+
+ If \a rectangle is a null rectangle (the default), the entire widget
+ is grabbed. Otherwise, the grabbed area is limited to \a rectangle.
+
+ The default implementation uses QWindowSurface::buffer().
+
+ \sa QPixmap::grabWidget()
+*/
+QPixmap QWindowSurface::grabWidget(const QWidget *widget, const QRect &rectangle) const
+{
+ QPixmap result;
+
+ if (widget->window() != window())
+ return result;
+
+ const QImage *img = const_cast<QWindowSurface *>(this)->buffer(widget->window());
+
+ if (!img || img->isNull())
+ return result;
+
+ QRect rect = rectangle.isEmpty() ? widget->rect() : (widget->rect() & rectangle);
+
+ rect.translate(offset(widget) - offset(widget->window()));
+ rect &= QRect(QPoint(), img->size());
+
+ if (rect.isEmpty())
+ return result;
+
+ QImage subimg(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
+ rect.width(), rect.height(),
+ img->bytesPerLine(), img->format());
+ subimg.detach(); //### expensive -- maybe we should have a real SubImage that shares reference count
+
+ result = QPixmap::fromImage(subimg);
+ return result;
+}
+
+/*!
+ Returns the offset of \a widget in the coordinates of this
+ window surface.
+ */
+QPoint QWindowSurface::offset(const QWidget *widget) const
+{
+ QWidget *window = d_ptr->window;
+ QPoint offset = widget->mapTo(window, QPoint());
+#ifdef Q_WS_QWS
+ offset += window->geometry().topLeft() - window->frameGeometry().topLeft();
+#endif
+ return offset;
+}
+
+/*!
+ \fn QRect QWindowSurface::rect(const QWidget *widget) const
+
+ Returns the rectangle for \a widget in the coordinates of this
+ window surface.
+*/
+
+bool QWindowSurface::hasStaticContentsSupport() const
+{
+ return d_ptr->staticContentsSupport;
+}
+
+void QWindowSurface::setStaticContentsSupport(bool enable)
+{
+ d_ptr->staticContentsSupport = enable;
+}
+
+void QWindowSurface::setStaticContents(const QRegion &region)
+{
+ d_ptr->staticContents = region;
+}
+
+QRegion QWindowSurface::staticContents() const
+{
+ return d_ptr->staticContents;
+}
+
+bool QWindowSurface::hasStaticContents() const
+{
+ return d_ptr->staticContentsSupport && !d_ptr->staticContents.isEmpty();
+}
+
+void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
+{
+ // make sure we don't detach
+ uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());
+
+ int lineskip = img.bytesPerLine();
+ int depth = img.depth() >> 3;
+
+
+ const QRect r = rect & QRect(0, 0, img.width(), img.height());
+ const QPoint p = rect.topLeft() + offset;
+
+ const uchar *src;
+ uchar *dest;
+
+ if (r.top() < p.y()) {
+ src = mem + r.bottom() * lineskip + r.left() * depth;
+ dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth;
+ lineskip = -lineskip;
+ } else {
+ src = mem + r.top() * lineskip + r.left() * depth;
+ dest = mem + p.y() * lineskip + p.x() * depth;
+ }
+
+ const int w = r.width();
+ int h = r.height();
+ const int bytes = w * depth;
+
+ // overlapping segments?
+ if (offset.y() == 0 && qAbs(offset.x()) < w) {
+ do {
+ ::memmove(dest, src, bytes);
+ dest += lineskip;
+ src += lineskip;
+ } while (--h);
+ } else {
+ do {
+ ::memcpy(dest, src, bytes);
+ dest += lineskip;
+ src += lineskip;
+ } while (--h);
+ }
+}
+
+QT_END_NAMESPACE