src/gui/painting/qwindowsurface.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <private/qwindowsurface_p.h>
       
    43 #include <qwidget.h>
       
    44 #include <private/qwidget_p.h>
       
    45 #include <private/qbackingstore_p.h>
       
    46 
       
    47 QT_BEGIN_NAMESPACE
       
    48 
       
    49 class QWindowSurfacePrivate
       
    50 {
       
    51 public:
       
    52     QWindowSurfacePrivate(QWidget *w) : window(w), staticContentsSupport(false) {}
       
    53 
       
    54     QWidget *window;
       
    55     QRect geometry;
       
    56     QRegion staticContents;
       
    57     QList<QImage*> bufferImages;
       
    58     bool staticContentsSupport;
       
    59 };
       
    60 
       
    61 /*!
       
    62     \class QWindowSurface
       
    63     \since 4.3
       
    64     \internal
       
    65     \preliminary
       
    66     \ingroup qws
       
    67 
       
    68     \brief The QWindowSurface class provides the drawing area for top-level
       
    69     windows.
       
    70 */
       
    71 
       
    72 
       
    73 /*!
       
    74     \fn void QWindowSurface::beginPaint(const QRegion &region)
       
    75 
       
    76     This function is called before painting onto the surface begins,
       
    77     with the \a region in which the painting will occur.
       
    78 
       
    79     \sa endPaint(), paintDevice()
       
    80 */
       
    81 
       
    82 /*!
       
    83     \fn void QWindowSurface::endPaint(const QRegion &region)
       
    84 
       
    85     This function is called after painting onto the surface has ended,
       
    86     with the \a region in which the painting was performed.
       
    87 
       
    88     \sa beginPaint(), paintDevice()
       
    89 */
       
    90 
       
    91 /*!
       
    92     \fn void QWindowSurface::flush(QWidget *widget, const QRegion &region,
       
    93                                   const QPoint &offset)
       
    94 
       
    95     Flushes the given \a region from the specified \a widget onto the
       
    96     screen.
       
    97 
       
    98     Note that the \a offset parameter is currently unused.
       
    99 */
       
   100 
       
   101 /*!
       
   102     \fn QPaintDevice* QWindowSurface::paintDevice()
       
   103 
       
   104     Implement this function to return the appropriate paint device.
       
   105 */
       
   106 
       
   107 /*!
       
   108     Constructs an empty surface for the given top-level \a window.
       
   109 */
       
   110 QWindowSurface::QWindowSurface(QWidget *window)
       
   111     : d_ptr(new QWindowSurfacePrivate(window))
       
   112 {
       
   113     if (window)
       
   114         window->setWindowSurface(this);
       
   115 }
       
   116 
       
   117 /*!
       
   118     Destroys this surface.
       
   119 */
       
   120 QWindowSurface::~QWindowSurface()
       
   121 {
       
   122     if (d_ptr->window)
       
   123         d_ptr->window->d_func()->extra->topextra->windowSurface = 0;
       
   124     delete d_ptr;
       
   125 }
       
   126 
       
   127 /*!
       
   128     Returns a pointer to the top-level window associated with this
       
   129     surface.
       
   130 */
       
   131 QWidget* QWindowSurface::window() const
       
   132 {
       
   133     return d_ptr->window;
       
   134 }
       
   135 
       
   136 void QWindowSurface::beginPaint(const QRegion &)
       
   137 {
       
   138 }
       
   139 
       
   140 void QWindowSurface::endPaint(const QRegion &)
       
   141 {
       
   142 //     QApplication::syncX();
       
   143     qDeleteAll(d_ptr->bufferImages);
       
   144     d_ptr->bufferImages.clear();
       
   145 }
       
   146 
       
   147 /*!
       
   148     Sets the currently allocated area to be the given \a rect.
       
   149 
       
   150     This function is called whenever area covered by the top-level
       
   151     window changes.
       
   152 
       
   153     \sa geometry()
       
   154 */
       
   155 void QWindowSurface::setGeometry(const QRect &rect)
       
   156 {
       
   157     d_ptr->geometry = rect;
       
   158 }
       
   159 
       
   160 /*!
       
   161     Returns the currently allocated area on the screen.
       
   162 */
       
   163 QRect QWindowSurface::geometry() const
       
   164 {
       
   165     return d_ptr->geometry;
       
   166 }
       
   167 
       
   168 /*!
       
   169     Scrolls the given \a area \a dx pixels to the right and \a dy
       
   170     downward; both \a dx and \a dy may be negative.
       
   171 
       
   172     Returns true if the area was scrolled successfully; false otherwise.
       
   173 */
       
   174 bool QWindowSurface::scroll(const QRegion &area, int dx, int dy)
       
   175 {
       
   176     Q_UNUSED(area);
       
   177     Q_UNUSED(dx);
       
   178     Q_UNUSED(dy);
       
   179 
       
   180     return false;
       
   181 }
       
   182 
       
   183 /*!
       
   184     Returns a QImage pointer which represents the actual buffer the \a widget
       
   185     is drawn into or 0 if this is unavailable.
       
   186 
       
   187     You must call beginPaint() before you call this function and the returned
       
   188     pointer is only valid until endPaint() is called.
       
   189 */
       
   190 QImage* QWindowSurface::buffer(const QWidget *widget)
       
   191 {
       
   192     if (widget->window() != window())
       
   193         return 0;
       
   194 
       
   195     QPaintDevice *pdev = paintDevice();
       
   196     if (!pdev || pdev->devType() != QInternal::Image)
       
   197         return 0;
       
   198 
       
   199     const QPoint off = offset(widget);
       
   200     QImage *img = static_cast<QImage*>(pdev);
       
   201 
       
   202     QRect rect(off, widget->size());
       
   203     rect &= QRect(QPoint(), img->size());
       
   204 
       
   205     if (rect.isEmpty())
       
   206         return 0;
       
   207 
       
   208     img = new QImage(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
       
   209                      rect.width(), rect.height(),
       
   210                      img->bytesPerLine(), img->format());
       
   211     d_ptr->bufferImages.append(img);
       
   212 
       
   213     return img;
       
   214 }
       
   215 
       
   216 /*!
       
   217   Returns a QPixmap generated from the part of the backing store
       
   218   corresponding to \a widget. Returns a null QPixmap if an error
       
   219   occurs. The contents of the pixmap are only defined for the regions
       
   220   of \a widget that have received paint events since the last resize
       
   221   of the backing store.
       
   222 
       
   223   If \a rectangle is a null rectangle (the default), the entire widget
       
   224   is grabbed. Otherwise, the grabbed area is limited to \a rectangle.
       
   225 
       
   226   The default implementation uses QWindowSurface::buffer().
       
   227 
       
   228   \sa QPixmap::grabWidget()
       
   229 */
       
   230 QPixmap QWindowSurface::grabWidget(const QWidget *widget, const QRect &rectangle) const
       
   231 {
       
   232     QPixmap result;
       
   233 
       
   234     if (widget->window() != window())
       
   235         return result;
       
   236 
       
   237     const QImage *img = const_cast<QWindowSurface *>(this)->buffer(widget->window());
       
   238 
       
   239     if (!img || img->isNull())
       
   240         return result;
       
   241 
       
   242     QRect rect = rectangle.isEmpty() ? widget->rect() : (widget->rect() & rectangle);
       
   243 
       
   244     rect.translate(offset(widget) - offset(widget->window()));
       
   245     rect &= QRect(QPoint(), img->size());
       
   246 
       
   247     if (rect.isEmpty())
       
   248         return result;
       
   249 
       
   250     QImage subimg(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
       
   251                   rect.width(), rect.height(),
       
   252                   img->bytesPerLine(), img->format());
       
   253     subimg.detach(); //### expensive -- maybe we should have a real SubImage that shares reference count
       
   254 
       
   255     result = QPixmap::fromImage(subimg);
       
   256     return result;
       
   257 }
       
   258 
       
   259 /*!
       
   260   Returns the offset of \a widget in the coordinates of this
       
   261   window surface.
       
   262  */
       
   263 QPoint QWindowSurface::offset(const QWidget *widget) const
       
   264 {
       
   265     QWidget *window = d_ptr->window;
       
   266     QPoint offset = widget->mapTo(window, QPoint());
       
   267 #ifdef Q_WS_QWS
       
   268     offset += window->geometry().topLeft() - window->frameGeometry().topLeft();
       
   269 #endif
       
   270     return offset;
       
   271 }
       
   272 
       
   273 /*!
       
   274   \fn QRect QWindowSurface::rect(const QWidget *widget) const
       
   275 
       
   276   Returns the rectangle for \a widget in the coordinates of this
       
   277   window surface.
       
   278 */
       
   279 
       
   280 bool QWindowSurface::hasStaticContentsSupport() const
       
   281 {
       
   282     return d_ptr->staticContentsSupport;
       
   283 }
       
   284 
       
   285 void QWindowSurface::setStaticContentsSupport(bool enable)
       
   286 {
       
   287     d_ptr->staticContentsSupport = enable;
       
   288 }
       
   289 
       
   290 void QWindowSurface::setStaticContents(const QRegion &region)
       
   291 {
       
   292     d_ptr->staticContents = region;
       
   293 }
       
   294 
       
   295 QRegion QWindowSurface::staticContents() const
       
   296 {
       
   297     return d_ptr->staticContents;
       
   298 }
       
   299 
       
   300 bool QWindowSurface::hasStaticContents() const
       
   301 {
       
   302     return d_ptr->staticContentsSupport && !d_ptr->staticContents.isEmpty();
       
   303 }
       
   304 
       
   305 void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
       
   306 {
       
   307     // make sure we don't detach
       
   308     uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());
       
   309 
       
   310     int lineskip = img.bytesPerLine();
       
   311     int depth = img.depth() >> 3;
       
   312 
       
   313     const QRect imageRect(0, 0, img.width(), img.height());
       
   314     const QRect r = rect & imageRect & imageRect.translated(-offset);
       
   315     const QPoint p = rect.topLeft() + offset;
       
   316 
       
   317     if (r.isEmpty())
       
   318         return;
       
   319 
       
   320     const uchar *src;
       
   321     uchar *dest;
       
   322 
       
   323     if (r.top() < p.y()) {
       
   324         src = mem + r.bottom() * lineskip + r.left() * depth;
       
   325         dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth;
       
   326         lineskip = -lineskip;
       
   327     } else {
       
   328         src = mem + r.top() * lineskip + r.left() * depth;
       
   329         dest = mem + p.y() * lineskip + p.x() * depth;
       
   330     }
       
   331 
       
   332     const int w = r.width();
       
   333     int h = r.height();
       
   334     const int bytes = w * depth;
       
   335 
       
   336     // overlapping segments?
       
   337     if (offset.y() == 0 && qAbs(offset.x()) < w) {
       
   338         do {
       
   339             ::memmove(dest, src, bytes);
       
   340             dest += lineskip;
       
   341             src += lineskip;
       
   342         } while (--h);
       
   343     } else {
       
   344         do {
       
   345             ::memcpy(dest, src, bytes);
       
   346             dest += lineskip;
       
   347             src += lineskip;
       
   348         } while (--h);
       
   349     }
       
   350 }
       
   351 
       
   352 QT_END_NAMESPACE