| 1 | /****************************************************************************
|
|---|
| 2 | **
|
|---|
| 3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|---|
| 4 | ** All rights reserved.
|
|---|
| 5 | ** Contact: Nokia Corporation ([email protected])
|
|---|
| 6 | **
|
|---|
| 7 | ** This file is part of the QtGui module of the Qt Toolkit.
|
|---|
| 8 | **
|
|---|
| 9 | ** $QT_BEGIN_LICENSE:LGPL$
|
|---|
| 10 | ** Commercial Usage
|
|---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
|---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
|---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in
|
|---|
| 14 | ** a written agreement between you and Nokia.
|
|---|
| 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 | ** GNU General Public License Usage
|
|---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU
|
|---|
| 30 | ** General Public License version 3.0 as published by the Free Software
|
|---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 32 | ** packaging of this file. Please review the following information to
|
|---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
|---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
|---|
| 35 | **
|
|---|
| 36 | ** If you have questions regarding the use of this file, please contact
|
|---|
| 37 | ** Nokia at [email protected].
|
|---|
| 38 | ** $QT_END_LICENSE$
|
|---|
| 39 | **
|
|---|
| 40 | ****************************************************************************/
|
|---|
| 41 |
|
|---|
| 42 | #include "qplatformdefs.h"
|
|---|
| 43 | #include "qscreen_qws.h"
|
|---|
| 44 |
|
|---|
| 45 | #include "qcolormap.h"
|
|---|
| 46 | #include "qscreendriverfactory_qws.h"
|
|---|
| 47 | #include "qwindowsystem_qws.h"
|
|---|
| 48 | #include "qwidget.h"
|
|---|
| 49 | #include "qcolor.h"
|
|---|
| 50 | #include "qpixmap.h"
|
|---|
| 51 | #include "qvarlengtharray.h"
|
|---|
| 52 | #include "qwsdisplay_qws.h"
|
|---|
| 53 | #include "qpainter.h"
|
|---|
| 54 | #include <private/qdrawhelper_p.h>
|
|---|
| 55 | #include <private/qpaintengine_raster_p.h>
|
|---|
| 56 | #include <private/qpixmap_raster_p.h>
|
|---|
| 57 | #include <private/qwindowsurface_qws_p.h>
|
|---|
| 58 | #include <private/qpainter_p.h>
|
|---|
| 59 | #include <private/qwidget_p.h>
|
|---|
| 60 | #include <private/qgraphicssystem_qws_p.h>
|
|---|
| 61 |
|
|---|
| 62 | QT_BEGIN_NAMESPACE
|
|---|
| 63 |
|
|---|
| 64 | // #define QT_USE_MEMCPY_DUFF
|
|---|
| 65 |
|
|---|
| 66 | #ifndef QT_NO_QWS_CURSOR
|
|---|
| 67 | bool qt_sw_cursor=false;
|
|---|
| 68 | Q_GUI_EXPORT QScreenCursor * qt_screencursor = 0;
|
|---|
| 69 | #endif
|
|---|
| 70 | Q_GUI_EXPORT QScreen * qt_screen = 0;
|
|---|
| 71 |
|
|---|
| 72 | ClearCacheFunc QScreen::clearCacheFunc = 0;
|
|---|
| 73 |
|
|---|
| 74 | #ifndef QT_NO_QWS_CURSOR
|
|---|
| 75 | /*!
|
|---|
| 76 | \class QScreenCursor
|
|---|
| 77 | \ingroup qws
|
|---|
| 78 |
|
|---|
| 79 | \brief The QScreenCursor class is a base class for screen cursors
|
|---|
| 80 | in Qt for Embedded Linux.
|
|---|
| 81 |
|
|---|
| 82 | Note that this class is non-portable, and that it is only
|
|---|
| 83 | available in \l{Qt for Embedded Linux}.
|
|---|
| 84 |
|
|---|
| 85 | QScreenCursor implements a software cursor, but can be subclassed
|
|---|
| 86 | to support hardware cursors as well. When deriving from the
|
|---|
| 87 | QScreenCursor class it is important to maintain the cursor's
|
|---|
| 88 | image, position, hot spot (the point within the cursor's image
|
|---|
| 89 | that will be the position of the associated mouse events) and
|
|---|
| 90 | visibility as well as informing whether it is hardware accelerated
|
|---|
| 91 | or not.
|
|---|
| 92 |
|
|---|
| 93 | Note that there may only be one screen cursor at a time. Use the
|
|---|
| 94 | static instance() function to retrieve a pointer to the current
|
|---|
| 95 | screen cursor. Typically, the cursor is constructed by the QScreen
|
|---|
| 96 | class or one of its descendants when it is initializing the
|
|---|
| 97 | device; the QScreenCursor class should never be instantiated
|
|---|
| 98 | explicitly.
|
|---|
| 99 |
|
|---|
| 100 | Use the move() function to change the position of the cursor, and
|
|---|
| 101 | the set() function to alter its image or its hot spot. In
|
|---|
| 102 | addition, you can find out whether the cursor is accelerated or
|
|---|
| 103 | not, using the isAccelerated() function, and the boundingRect()
|
|---|
| 104 | function returns the cursor's bounding rectangle.
|
|---|
| 105 |
|
|---|
| 106 | The cursor's appearance can be controlled using the isVisible(),
|
|---|
| 107 | hide() and show() functions; alternatively the QWSServer class
|
|---|
| 108 | provides some means of controlling the cursor's appearance using
|
|---|
| 109 | the QWSServer::isCursorVisible() and QWSServer::setCursorVisible()
|
|---|
| 110 | functions.
|
|---|
| 111 |
|
|---|
| 112 | \sa QScreen, QWSServer
|
|---|
| 113 | */
|
|---|
| 114 |
|
|---|
| 115 | /*!
|
|---|
| 116 | \fn static QScreenCursor* QScreenCursor::instance()
|
|---|
| 117 | \since 4.2
|
|---|
| 118 |
|
|---|
| 119 | Returns a pointer to the application's unique screen cursor.
|
|---|
| 120 | */
|
|---|
| 121 |
|
|---|
| 122 | extern bool qws_sw_cursor;
|
|---|
| 123 |
|
|---|
| 124 | /*!
|
|---|
| 125 | Constructs a screen cursor
|
|---|
| 126 | */
|
|---|
| 127 | QScreenCursor::QScreenCursor()
|
|---|
| 128 | {
|
|---|
| 129 | pos = QPoint(qt_screen->deviceWidth()/2, qt_screen->deviceHeight()/2);
|
|---|
| 130 | size = QSize(0,0);
|
|---|
| 131 | enable = true;
|
|---|
| 132 | hwaccel = false;
|
|---|
| 133 | supportsAlpha = true;
|
|---|
| 134 | }
|
|---|
| 135 |
|
|---|
| 136 | /*!
|
|---|
| 137 | Destroys the screen cursor.
|
|---|
| 138 | */
|
|---|
| 139 | QScreenCursor::~QScreenCursor()
|
|---|
| 140 | {
|
|---|
| 141 | }
|
|---|
| 142 |
|
|---|
| 143 | /*!
|
|---|
| 144 | Hides the cursor from the screen.
|
|---|
| 145 |
|
|---|
| 146 | \sa show()
|
|---|
| 147 | */
|
|---|
| 148 | void QScreenCursor::hide()
|
|---|
| 149 | {
|
|---|
| 150 | if (enable) {
|
|---|
| 151 | enable = false;
|
|---|
| 152 | if (!hwaccel)
|
|---|
| 153 | qt_screen->exposeRegion(boundingRect(), 0);
|
|---|
| 154 | }
|
|---|
| 155 | }
|
|---|
| 156 |
|
|---|
| 157 | /*!
|
|---|
| 158 | Shows the mouse cursor.
|
|---|
| 159 |
|
|---|
| 160 | \sa hide()
|
|---|
| 161 | */
|
|---|
| 162 | void QScreenCursor::show()
|
|---|
| 163 | {
|
|---|
| 164 | if (!enable) {
|
|---|
| 165 | enable = true;
|
|---|
| 166 | if (!hwaccel)
|
|---|
| 167 | qt_screen->exposeRegion(boundingRect(), 0);
|
|---|
| 168 | }
|
|---|
| 169 | }
|
|---|
| 170 |
|
|---|
| 171 | /*!
|
|---|
| 172 | Sets the cursor's image to be the given \a image.
|
|---|
| 173 |
|
|---|
| 174 | The \a hotx and \a hoty parameters define the cursor's hot spot,
|
|---|
| 175 | i.e., the point within the cursor's image that will be the
|
|---|
| 176 | position of the associated mouse events.
|
|---|
| 177 |
|
|---|
| 178 | \sa move()
|
|---|
| 179 | */
|
|---|
| 180 | void QScreenCursor::set(const QImage &image, int hotx, int hoty)
|
|---|
| 181 | {
|
|---|
| 182 | const QRect r = boundingRect();
|
|---|
| 183 |
|
|---|
| 184 | hotspot = QPoint(hotx, hoty);
|
|---|
| 185 | // These are in almost all cases the fastest formats to blend
|
|---|
| 186 | QImage::Format f;
|
|---|
| 187 | switch (qt_screen->depth()) {
|
|---|
| 188 | case 12:
|
|---|
| 189 | f = QImage::Format_ARGB4444_Premultiplied;
|
|---|
| 190 | break;
|
|---|
| 191 | case 15:
|
|---|
| 192 | f = QImage::Format_ARGB8555_Premultiplied;
|
|---|
| 193 | break;
|
|---|
| 194 | case 16:
|
|---|
| 195 | f = QImage::Format_ARGB8565_Premultiplied;
|
|---|
| 196 | break;
|
|---|
| 197 | case 18:
|
|---|
| 198 | f = QImage::Format_ARGB6666_Premultiplied;
|
|---|
| 199 | break;
|
|---|
| 200 | default:
|
|---|
| 201 | f = QImage::Format_ARGB32_Premultiplied;
|
|---|
| 202 | }
|
|---|
| 203 |
|
|---|
| 204 | cursor = image.convertToFormat(f);
|
|---|
| 205 |
|
|---|
| 206 | size = image.size();
|
|---|
| 207 |
|
|---|
| 208 | if (enable && !hwaccel)
|
|---|
| 209 | qt_screen->exposeRegion(r | boundingRect(), 0);
|
|---|
| 210 | }
|
|---|
| 211 |
|
|---|
| 212 | /*!
|
|---|
| 213 | Moves the mouse cursor to the given position, i.e., (\a x, \a y).
|
|---|
| 214 |
|
|---|
| 215 | Note that the given position defines the top-left corner of the
|
|---|
| 216 | cursor's image, i.e., not the cursor's hot spot (the position of
|
|---|
| 217 | the associated mouse events).
|
|---|
| 218 |
|
|---|
| 219 | \sa set()
|
|---|
| 220 | */
|
|---|
| 221 | void QScreenCursor::move(int x, int y)
|
|---|
| 222 | {
|
|---|
| 223 | QRegion r = boundingRect();
|
|---|
| 224 | pos = QPoint(x,y);
|
|---|
| 225 | if (enable && !hwaccel) {
|
|---|
| 226 | r |= boundingRect();
|
|---|
| 227 | qt_screen->exposeRegion(r, 0);
|
|---|
| 228 | }
|
|---|
| 229 | }
|
|---|
| 230 |
|
|---|
| 231 |
|
|---|
| 232 | /*!
|
|---|
| 233 | \fn void QScreenCursor::initSoftwareCursor ()
|
|---|
| 234 |
|
|---|
| 235 | Initializes the screen cursor.
|
|---|
| 236 |
|
|---|
| 237 | This function is typically called from the screen driver when
|
|---|
| 238 | initializing the device. Alternatively, the cursor can be set
|
|---|
| 239 | directly using the pointer returned by the static instance()
|
|---|
| 240 | function.
|
|---|
| 241 |
|
|---|
| 242 | \sa QScreen::initDevice()
|
|---|
| 243 | */
|
|---|
| 244 | void QScreenCursor::initSoftwareCursor()
|
|---|
| 245 | {
|
|---|
| 246 | qt_screencursor = new QScreenCursor;
|
|---|
| 247 | }
|
|---|
| 248 |
|
|---|
| 249 |
|
|---|
| 250 | #endif // QT_NO_QWS_CURSOR
|
|---|
| 251 |
|
|---|
| 252 |
|
|---|
| 253 | /*!
|
|---|
| 254 | \fn QRect QScreenCursor::boundingRect () const
|
|---|
| 255 |
|
|---|
| 256 | Returns the cursor's bounding rectangle.
|
|---|
| 257 | */
|
|---|
| 258 |
|
|---|
| 259 | /*!
|
|---|
| 260 | \internal
|
|---|
| 261 | \fn bool QScreenCursor::enabled ()
|
|---|
| 262 | */
|
|---|
| 263 |
|
|---|
| 264 | /*!
|
|---|
| 265 | \fn QImage QScreenCursor::image () const
|
|---|
| 266 |
|
|---|
| 267 | Returns the cursor's image.
|
|---|
| 268 | */
|
|---|
| 269 |
|
|---|
| 270 |
|
|---|
| 271 | /*!
|
|---|
| 272 | \fn bool QScreenCursor::isAccelerated () const
|
|---|
| 273 |
|
|---|
| 274 | Returns true if the cursor is accelerated; otherwise false.
|
|---|
| 275 | */
|
|---|
| 276 |
|
|---|
| 277 | /*!
|
|---|
| 278 | \fn bool QScreenCursor::isVisible () const
|
|---|
| 279 |
|
|---|
| 280 | Returns true if the cursor is visible; otherwise false.
|
|---|
| 281 | */
|
|---|
| 282 |
|
|---|
| 283 | /*!
|
|---|
| 284 | \internal
|
|---|
| 285 | \fn bool QScreenCursor::supportsAlphaCursor () const
|
|---|
| 286 | */
|
|---|
| 287 |
|
|---|
| 288 | /*
|
|---|
| 289 | \variable QScreenCursor::cursor
|
|---|
| 290 |
|
|---|
| 291 | \brief the cursor's image.
|
|---|
| 292 |
|
|---|
| 293 | \sa image()
|
|---|
| 294 | */
|
|---|
| 295 |
|
|---|
| 296 | /*
|
|---|
| 297 | \variable QScreenCursor::size
|
|---|
| 298 |
|
|---|
| 299 | \brief the cursor's size
|
|---|
| 300 | */
|
|---|
| 301 |
|
|---|
| 302 | /*
|
|---|
| 303 | \variable QScreenCursor::pos
|
|---|
| 304 |
|
|---|
| 305 | \brief the cursor's position, i.e., the position of the top-left
|
|---|
| 306 | corner of the crsor's image
|
|---|
| 307 |
|
|---|
| 308 | \sa set(), move()
|
|---|
| 309 | */
|
|---|
| 310 |
|
|---|
| 311 | /*
|
|---|
| 312 | \variable QScreenCursor::hotspot
|
|---|
| 313 |
|
|---|
| 314 | \brief the cursor's hotspot, i.e., the point within the cursor's
|
|---|
| 315 | image that will be the position of the associated mouse events.
|
|---|
| 316 |
|
|---|
| 317 | \sa set(), move()
|
|---|
| 318 | */
|
|---|
| 319 |
|
|---|
| 320 | /*
|
|---|
| 321 | \variable QScreenCursor::enable
|
|---|
| 322 |
|
|---|
| 323 | \brief whether the cursor is visible or not
|
|---|
| 324 |
|
|---|
| 325 | \sa isVisible()
|
|---|
| 326 | */
|
|---|
| 327 |
|
|---|
| 328 | /*
|
|---|
| 329 | \variable QScreenCursor::hwaccel
|
|---|
| 330 |
|
|---|
| 331 | \brief holds whether the cursor is accelerated or not
|
|---|
| 332 |
|
|---|
| 333 | If the cursor is not accelerated, its image will be included by
|
|---|
| 334 | the screen when it composites the window surfaces.
|
|---|
| 335 |
|
|---|
| 336 | \sa isAccelerated()
|
|---|
| 337 |
|
|---|
| 338 | */
|
|---|
| 339 |
|
|---|
| 340 | /*
|
|---|
| 341 | \variable QScreenCursor::supportsAlpha
|
|---|
| 342 | */
|
|---|
| 343 |
|
|---|
| 344 | /*!
|
|---|
| 345 | \internal
|
|---|
| 346 | \macro qt_screencursor
|
|---|
| 347 | \relates QScreenCursor
|
|---|
| 348 |
|
|---|
| 349 | A global pointer referring to the unique screen cursor. It is
|
|---|
| 350 | equivalent to the pointer returned by the
|
|---|
| 351 | QScreenCursor::instance() function.
|
|---|
| 352 | */
|
|---|
| 353 |
|
|---|
| 354 |
|
|---|
| 355 |
|
|---|
| 356 | class QScreenPrivate
|
|---|
| 357 | {
|
|---|
| 358 | public:
|
|---|
| 359 | QScreenPrivate(QScreen *parent, QScreen::ClassId id = QScreen::CustomClass);
|
|---|
| 360 | ~QScreenPrivate();
|
|---|
| 361 |
|
|---|
| 362 | inline QImage::Format preferredImageFormat() const;
|
|---|
| 363 |
|
|---|
| 364 | typedef void (*SolidFillFunc)(QScreen*, const QColor&, const QRegion&);
|
|---|
| 365 | typedef void (*BlitFunc)(QScreen*, const QImage&, const QPoint&, const QRegion&);
|
|---|
| 366 |
|
|---|
| 367 | SolidFillFunc solidFill;
|
|---|
| 368 | BlitFunc blit;
|
|---|
| 369 |
|
|---|
| 370 | QPoint offset;
|
|---|
| 371 | QList<QScreen*> subScreens;
|
|---|
| 372 | QPixmapDataFactory* pixmapFactory;
|
|---|
| 373 | QGraphicsSystem* graphicsSystem;
|
|---|
| 374 | QWSGraphicsSystem defaultGraphicsSystem; //###
|
|---|
| 375 | QImage::Format pixelFormat;
|
|---|
| 376 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
|---|
| 377 | bool fb_is_littleEndian;
|
|---|
| 378 | #endif
|
|---|
| 379 | #ifdef QT_QWS_CLIENTBLIT
|
|---|
| 380 | bool supportsBlitInClients;
|
|---|
| 381 | #endif
|
|---|
| 382 | int classId;
|
|---|
| 383 | QScreen *q_ptr;
|
|---|
| 384 | };
|
|---|
| 385 |
|
|---|
| 386 | template <typename T>
|
|---|
| 387 | static void solidFill_template(QScreen *screen, const QColor &color,
|
|---|
| 388 | const QRegion ®ion)
|
|---|
| 389 | {
|
|---|
| 390 | T *dest = reinterpret_cast<T*>(screen->base());
|
|---|
| 391 | const T c = qt_colorConvert<T, quint32>(color.rgba(), 0);
|
|---|
| 392 | const int stride = screen->linestep();
|
|---|
| 393 | const QVector<QRect> rects = region.rects();
|
|---|
| 394 |
|
|---|
| 395 | for (int i = 0; i < rects.size(); ++i) {
|
|---|
| 396 | const QRect r = rects.at(i);
|
|---|
| 397 | qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
|
|---|
| 398 | }
|
|---|
| 399 | }
|
|---|
| 400 |
|
|---|
| 401 | #ifdef QT_QWS_DEPTH_GENERIC
|
|---|
| 402 | static void solidFill_rgb_32bpp(QScreen *screen, const QColor &color,
|
|---|
| 403 | const QRegion ®ion)
|
|---|
| 404 | {
|
|---|
| 405 | quint32 *dest = reinterpret_cast<quint32*>(screen->base());
|
|---|
| 406 | const quint32 c = qt_convertToRgb<quint32>(color.rgba());
|
|---|
| 407 |
|
|---|
| 408 | const int stride = screen->linestep();
|
|---|
| 409 | const QVector<QRect> rects = region.rects();
|
|---|
| 410 |
|
|---|
| 411 | for (int i = 0; i < rects.size(); ++i) {
|
|---|
| 412 | const QRect r = rects.at(i);
|
|---|
| 413 | qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
|
|---|
| 414 | }
|
|---|
| 415 | }
|
|---|
| 416 |
|
|---|
| 417 | static void solidFill_rgb_16bpp(QScreen *screen, const QColor &color,
|
|---|
| 418 | const QRegion ®ion)
|
|---|
| 419 | {
|
|---|
| 420 | quint16 *dest = reinterpret_cast<quint16*>(screen->base());
|
|---|
| 421 | const quint16 c = qt_convertToRgb<quint32>(color.rgba());
|
|---|
| 422 |
|
|---|
| 423 | const int stride = screen->linestep();
|
|---|
| 424 | const QVector<QRect> rects = region.rects();
|
|---|
| 425 |
|
|---|
| 426 | for (int i = 0; i < rects.size(); ++i) {
|
|---|
| 427 | const QRect r = rects.at(i);
|
|---|
| 428 | qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
|
|---|
| 429 | }
|
|---|
| 430 | }
|
|---|
| 431 | #endif // QT_QWS_DEPTH_GENERIC
|
|---|
| 432 |
|
|---|
| 433 | #ifdef QT_QWS_DEPTH_4
|
|---|
| 434 | static inline void qt_rectfill_gray4(quint8 *dest, quint8 value,
|
|---|
| 435 | int x, int y, int width, int height,
|
|---|
| 436 | int stride)
|
|---|
| 437 | {
|
|---|
| 438 | const int pixelsPerByte = 2;
|
|---|
| 439 | dest += y * stride + x / pixelsPerByte;
|
|---|
| 440 | const int doAlign = x & 1;
|
|---|
| 441 | const int doTail = (width - doAlign) & 1;
|
|---|
| 442 | const int width8 = (width - doAlign) / pixelsPerByte;
|
|---|
| 443 |
|
|---|
| 444 | for (int j = 0; j < height; ++j) {
|
|---|
| 445 | if (doAlign)
|
|---|
| 446 | *dest = (*dest & 0xf0) | (value & 0x0f);
|
|---|
| 447 | if (width8)
|
|---|
| 448 | qt_memfill<quint8>(dest + doAlign, value, width8);
|
|---|
| 449 | if (doTail) {
|
|---|
| 450 | quint8 *d = dest + doAlign + width8;
|
|---|
| 451 | *d = (*d & 0x0f) | (value & 0xf0);
|
|---|
| 452 | }
|
|---|
| 453 | dest += stride;
|
|---|
| 454 | }
|
|---|
| 455 | }
|
|---|
| 456 |
|
|---|
| 457 | static void solidFill_gray4(QScreen *screen, const QColor &color,
|
|---|
| 458 | const QRegion ®ion)
|
|---|
| 459 | {
|
|---|
| 460 | quint8 *dest = reinterpret_cast<quint8*>(screen->base());
|
|---|
| 461 | const quint8 c = qGray(color.rgba()) >> 4;
|
|---|
| 462 | const quint8 c8 = (c << 4) | c;
|
|---|
| 463 |
|
|---|
| 464 | const int stride = screen->linestep();
|
|---|
| 465 | const QVector<QRect> rects = region.rects();
|
|---|
| 466 |
|
|---|
| 467 | for (int i = 0; i < rects.size(); ++i) {
|
|---|
| 468 | const QRect r = rects.at(i);
|
|---|
| 469 | qt_rectfill_gray4(dest, c8, r.x(), r.y(), r.width(), r.height(),
|
|---|
| 470 | stride);
|
|---|
| 471 | }
|
|---|
| 472 | }
|
|---|
| 473 | #endif // QT_QWS_DEPTH_4
|
|---|
| 474 |
|
|---|
| 475 | #ifdef QT_QWS_DEPTH_1
|
|---|
| 476 | static inline void qt_rectfill_mono(quint8 *dest, quint8 value,
|
|---|
| 477 | int x, int y, int width, int height,
|
|---|
| 478 | int stride)
|
|---|
| 479 | {
|
|---|
| 480 | const int pixelsPerByte = 8;
|
|---|
| 481 | const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
|
|---|
| 482 | const int doAlign = (alignWidth > 0 ? 1 : 0);
|
|---|
| 483 | const int alignStart = pixelsPerByte - 1 - (x & 7);
|
|---|
| 484 | const int alignStop = alignStart - (alignWidth - 1);
|
|---|
| 485 | const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
|
|---|
| 486 | const int tailWidth = (width - alignWidth) & 7;
|
|---|
| 487 | const int doTail = (tailWidth > 0 ? 1 : 0);
|
|---|
| 488 | const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
|
|---|
| 489 | const int width8 = (width - alignWidth) / pixelsPerByte;
|
|---|
| 490 |
|
|---|
| 491 | dest += y * stride + x / pixelsPerByte;
|
|---|
| 492 | stride -= (doAlign + width8);
|
|---|
| 493 |
|
|---|
| 494 | for (int j = 0; j < height; ++j) {
|
|---|
| 495 | if (doAlign) {
|
|---|
| 496 | *dest = (*dest & ~alignMask) | (value & alignMask);
|
|---|
| 497 | ++dest;
|
|---|
| 498 | }
|
|---|
| 499 | if (width8) {
|
|---|
| 500 | qt_memfill<quint8>(dest, value, width8);
|
|---|
| 501 | dest += width8;
|
|---|
| 502 | }
|
|---|
| 503 | if (doTail)
|
|---|
| 504 | *dest = (*dest & tailMask) | (value & ~tailMask);
|
|---|
| 505 | dest += stride;
|
|---|
| 506 | }
|
|---|
| 507 | }
|
|---|
| 508 |
|
|---|
| 509 | static void solidFill_mono(QScreen *screen, const QColor &color,
|
|---|
| 510 | const QRegion ®ion)
|
|---|
| 511 | {
|
|---|
| 512 | quint8 *dest = reinterpret_cast<quint8*>(screen->base());
|
|---|
| 513 | const quint8 c8 = (qGray(color.rgba()) >> 7) * 0xff;
|
|---|
| 514 |
|
|---|
| 515 | const int stride = screen->linestep();
|
|---|
| 516 | const QVector<QRect> rects = region.rects();
|
|---|
| 517 |
|
|---|
| 518 | for (int i = 0; i < rects.size(); ++i) {
|
|---|
| 519 | const QRect r = rects.at(i);
|
|---|
| 520 | qt_rectfill_mono(dest, c8, r.x(), r.y(), r.width(), r.height(),
|
|---|
| 521 | stride);
|
|---|
| 522 | }
|
|---|
| 523 | }
|
|---|
| 524 | #endif // QT_QWS_DEPTH_1
|
|---|
| 525 |
|
|---|
| 526 | void qt_solidFill_setup(QScreen *screen, const QColor &color,
|
|---|
| 527 | const QRegion ®ion)
|
|---|
| 528 | {
|
|---|
| 529 | switch (screen->depth()) {
|
|---|
| 530 | #ifdef QT_QWS_DEPTH_32
|
|---|
| 531 | case 32:
|
|---|
| 532 | if (screen->pixelType() == QScreen::NormalPixel)
|
|---|
| 533 | screen->d_ptr->solidFill = solidFill_template<quint32>;
|
|---|
| 534 | else
|
|---|
| 535 | screen->d_ptr->solidFill = solidFill_template<qabgr8888>;
|
|---|
| 536 | break;
|
|---|
| 537 | #endif
|
|---|
| 538 | #ifdef QT_QWS_DEPTH_24
|
|---|
| 539 | case 24:
|
|---|
| 540 | if (screen->pixelType() == QScreen::NormalPixel)
|
|---|
| 541 | screen->d_ptr->solidFill = solidFill_template<qrgb888>;
|
|---|
| 542 | else
|
|---|
| 543 | screen->d_ptr->solidFill = solidFill_template<quint24>;
|
|---|
| 544 | break;
|
|---|
| 545 | #endif
|
|---|
| 546 | #ifdef QT_QWS_DEPTH_18
|
|---|
| 547 | case 18:
|
|---|
| 548 | screen->d_ptr->solidFill = solidFill_template<quint18>;
|
|---|
| 549 | break;
|
|---|
| 550 | #endif
|
|---|
| 551 | #ifdef QT_QWS_DEPTH_16
|
|---|
| 552 | case 16:
|
|---|
| 553 | if (screen->pixelType() == QScreen::NormalPixel)
|
|---|
| 554 | screen->d_ptr->solidFill = solidFill_template<quint16>;
|
|---|
| 555 | else
|
|---|
| 556 | screen->d_ptr->solidFill = solidFill_template<qbgr565>;
|
|---|
| 557 | break;
|
|---|
| 558 | #endif
|
|---|
| 559 | #ifdef QT_QWS_DEPTH_15
|
|---|
| 560 | case 15:
|
|---|
| 561 | if (screen->pixelType() == QScreen::NormalPixel)
|
|---|
| 562 | screen->d_ptr->solidFill = solidFill_template<qrgb555>;
|
|---|
| 563 | else
|
|---|
| 564 | screen->d_ptr->solidFill = solidFill_template<qbgr555>;
|
|---|
| 565 | break;
|
|---|
| 566 | #endif
|
|---|
| 567 | #ifdef QT_QWS_DEPTH_12
|
|---|
| 568 | case 12:
|
|---|
| 569 | screen->d_ptr->solidFill = solidFill_template<qrgb444>;
|
|---|
| 570 | break;
|
|---|
| 571 | #endif
|
|---|
| 572 | #ifdef QT_QWS_DEPTH_8
|
|---|
| 573 | case 8:
|
|---|
| 574 | screen->d_ptr->solidFill = solidFill_template<quint8>;
|
|---|
| 575 | break;
|
|---|
| 576 | #endif
|
|---|
| 577 | #ifdef QT_QWS_DEPTH_4
|
|---|
| 578 | case 4:
|
|---|
| 579 | screen->d_ptr->solidFill = solidFill_gray4;
|
|---|
| 580 | break;
|
|---|
| 581 | #endif
|
|---|
| 582 | #ifdef QT_QWS_DEPTH_1
|
|---|
| 583 | case 1:
|
|---|
| 584 | screen->d_ptr->solidFill = solidFill_mono;
|
|---|
| 585 | break;
|
|---|
| 586 | #endif
|
|---|
| 587 | default:
|
|---|
| 588 | qFatal("solidFill_setup(): Screen depth %d not supported!",
|
|---|
| 589 | screen->depth());
|
|---|
| 590 | screen->d_ptr->solidFill = 0;
|
|---|
| 591 | break;
|
|---|
| 592 | }
|
|---|
| 593 | screen->d_ptr->solidFill(screen, color, region);
|
|---|
| 594 | }
|
|---|
| 595 |
|
|---|
| 596 | template <typename DST, typename SRC>
|
|---|
| 597 | static void blit_template(QScreen *screen, const QImage &image,
|
|---|
| 598 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 599 | {
|
|---|
| 600 | DST *dest = reinterpret_cast<DST*>(screen->base());
|
|---|
| 601 | const int screenStride = screen->linestep();
|
|---|
| 602 | const int imageStride = image.bytesPerLine();
|
|---|
| 603 |
|
|---|
| 604 | if (region.rectCount() == 1) {
|
|---|
| 605 | const QRect r = region.boundingRect();
|
|---|
| 606 | const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
|
|---|
| 607 | + r.x();
|
|---|
| 608 | qt_rectconvert<DST, SRC>(dest, src,
|
|---|
| 609 | r.x() + topLeft.x(), r.y() + topLeft.y(),
|
|---|
| 610 | r.width(), r.height(),
|
|---|
| 611 | screenStride, imageStride);
|
|---|
| 612 | } else {
|
|---|
| 613 | const QVector<QRect> rects = region.rects();
|
|---|
| 614 |
|
|---|
| 615 | for (int i = 0; i < rects.size(); ++i) {
|
|---|
| 616 | const QRect r = rects.at(i);
|
|---|
| 617 | const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
|
|---|
| 618 | + r.x();
|
|---|
| 619 | qt_rectconvert<DST, SRC>(dest, src,
|
|---|
| 620 | r.x() + topLeft.x(), r.y() + topLeft.y(),
|
|---|
| 621 | r.width(), r.height(),
|
|---|
| 622 | screenStride, imageStride);
|
|---|
| 623 | }
|
|---|
| 624 | }
|
|---|
| 625 | }
|
|---|
| 626 |
|
|---|
| 627 | #ifdef QT_QWS_DEPTH_32
|
|---|
| 628 | static void blit_32(QScreen *screen, const QImage &image,
|
|---|
| 629 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 630 | {
|
|---|
| 631 | switch (image.format()) {
|
|---|
| 632 | case QImage::Format_RGB32:
|
|---|
| 633 | case QImage::Format_ARGB32:
|
|---|
| 634 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 635 | blit_template<quint32, quint32>(screen, image, topLeft, region);
|
|---|
| 636 | return;
|
|---|
| 637 | #ifdef QT_QWS_DEPTH_16
|
|---|
| 638 | case QImage::Format_RGB16:
|
|---|
| 639 | blit_template<quint32, quint16>(screen, image, topLeft, region);
|
|---|
| 640 | return;
|
|---|
| 641 | #endif
|
|---|
| 642 | default:
|
|---|
| 643 | qCritical("blit_32(): Image format %d not supported!", image.format());
|
|---|
| 644 | }
|
|---|
| 645 | }
|
|---|
| 646 | #endif // QT_QWS_DEPTH_32
|
|---|
| 647 |
|
|---|
| 648 | #ifdef QT_QWS_DEPTH_24
|
|---|
| 649 | static void blit_24(QScreen *screen, const QImage &image,
|
|---|
| 650 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 651 | {
|
|---|
| 652 | switch (image.format()) {
|
|---|
| 653 | case QImage::Format_RGB32:
|
|---|
| 654 | case QImage::Format_ARGB32:
|
|---|
| 655 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 656 | blit_template<quint24, quint32>(screen, image, topLeft, region);
|
|---|
| 657 | return;
|
|---|
| 658 | case QImage::Format_RGB888:
|
|---|
| 659 | blit_template<quint24, qrgb888>(screen, image, topLeft, region);
|
|---|
| 660 | return;
|
|---|
| 661 | #ifdef QT_QWS_DEPTH_16
|
|---|
| 662 | case QImage::Format_RGB16:
|
|---|
| 663 | blit_template<quint24, quint16>(screen, image, topLeft, region);
|
|---|
| 664 | return;
|
|---|
| 665 | #endif
|
|---|
| 666 | default:
|
|---|
| 667 | qCritical("blit_24(): Image format %d not supported!", image.format());
|
|---|
| 668 | }
|
|---|
| 669 | }
|
|---|
| 670 |
|
|---|
| 671 | static void blit_qrgb888(QScreen *screen, const QImage &image,
|
|---|
| 672 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 673 | {
|
|---|
| 674 | switch (image.format()) {
|
|---|
| 675 | case QImage::Format_RGB32:
|
|---|
| 676 | case QImage::Format_ARGB32:
|
|---|
| 677 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 678 | blit_template<qrgb888, quint32>(screen, image, topLeft, region);
|
|---|
| 679 | return;
|
|---|
| 680 | case QImage::Format_RGB888:
|
|---|
| 681 | blit_template<qrgb888, qrgb888>(screen, image, topLeft, region);
|
|---|
| 682 | return;
|
|---|
| 683 | #ifdef QT_QWS_DEPTH_16
|
|---|
| 684 | case QImage::Format_RGB16:
|
|---|
| 685 | blit_template<qrgb888, quint16>(screen, image, topLeft, region);
|
|---|
| 686 | return;
|
|---|
| 687 | #endif
|
|---|
| 688 | default:
|
|---|
| 689 | qCritical("blit_24(): Image format %d not supported!", image.format());
|
|---|
| 690 | break;
|
|---|
| 691 | }
|
|---|
| 692 | }
|
|---|
| 693 | #endif // QT_QWS_DEPTH_24
|
|---|
| 694 |
|
|---|
| 695 | #ifdef QT_QWS_DEPTH_18
|
|---|
| 696 | static void blit_18(QScreen *screen, const QImage &image,
|
|---|
| 697 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 698 | {
|
|---|
| 699 | switch (image.format()) {
|
|---|
| 700 | case QImage::Format_RGB32:
|
|---|
| 701 | case QImage::Format_ARGB32:
|
|---|
| 702 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 703 | blit_template<qrgb666, quint32>(screen, image, topLeft, region);
|
|---|
| 704 | return;
|
|---|
| 705 | case QImage::Format_RGB666:
|
|---|
| 706 | blit_template<qrgb666, qrgb666>(screen, image, topLeft, region);
|
|---|
| 707 | return;
|
|---|
| 708 | #ifdef QT_QWS_DEPTH_16
|
|---|
| 709 | case QImage::Format_RGB16:
|
|---|
| 710 | blit_template<qrgb666, quint16>(screen, image, topLeft, region);
|
|---|
| 711 | return;
|
|---|
| 712 | #endif
|
|---|
| 713 | default:
|
|---|
| 714 | qCritical("blit_18(): Image format %d not supported!", image.format());
|
|---|
| 715 | }
|
|---|
| 716 | }
|
|---|
| 717 | #endif // QT_QWS_DEPTH_18
|
|---|
| 718 |
|
|---|
| 719 | #if (Q_BYTE_ORDER == Q_BIG_ENDIAN) && (defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15))
|
|---|
| 720 | class quint16LE
|
|---|
| 721 | {
|
|---|
| 722 | public:
|
|---|
| 723 | inline quint16LE(quint32 v) {
|
|---|
| 724 | data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
|
|---|
| 725 | }
|
|---|
| 726 |
|
|---|
| 727 | inline quint16LE(int v) {
|
|---|
| 728 | data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
|
|---|
| 729 | }
|
|---|
| 730 |
|
|---|
| 731 | inline quint16LE(quint16 v) {
|
|---|
| 732 | data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
|
|---|
| 733 | }
|
|---|
| 734 |
|
|---|
| 735 | inline quint16LE(qrgb555 v) {
|
|---|
| 736 | data = (( (quint16)v & 0xff00) >> 8) |
|
|---|
| 737 | (( (quint16)v & 0x00ff) << 8);
|
|---|
| 738 | }
|
|---|
| 739 |
|
|---|
| 740 | inline bool operator==(const quint16LE &v) const
|
|---|
| 741 | {
|
|---|
| 742 | return data == v.data;
|
|---|
| 743 | }
|
|---|
| 744 |
|
|---|
| 745 | private:
|
|---|
| 746 | quint16 data;
|
|---|
| 747 | };
|
|---|
| 748 | #endif
|
|---|
| 749 |
|
|---|
| 750 | #ifdef QT_QWS_DEPTH_16
|
|---|
| 751 | static void blit_16(QScreen *screen, const QImage &image,
|
|---|
| 752 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 753 | {
|
|---|
| 754 | switch (image.format()) {
|
|---|
| 755 | case QImage::Format_RGB32:
|
|---|
| 756 | case QImage::Format_ARGB32:
|
|---|
| 757 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 758 | // ### This probably doesn't work but it's a case which should never happen
|
|---|
| 759 | blit_template<quint16, quint32>(screen, image, topLeft, region);
|
|---|
| 760 | return;
|
|---|
| 761 | case QImage::Format_RGB16:
|
|---|
| 762 | blit_template<quint16, quint16>(screen, image, topLeft, region);
|
|---|
| 763 | return;
|
|---|
| 764 | default:
|
|---|
| 765 | qCritical("blit_16(): Image format %d not supported!", image.format());
|
|---|
| 766 | }
|
|---|
| 767 | }
|
|---|
| 768 |
|
|---|
| 769 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
|---|
| 770 | static void blit_16_bigToLittleEndian(QScreen *screen, const QImage &image,
|
|---|
| 771 | const QPoint &topLeft,
|
|---|
| 772 | const QRegion ®ion)
|
|---|
| 773 | {
|
|---|
| 774 | switch (image.format()) {
|
|---|
| 775 | case QImage::Format_RGB32:
|
|---|
| 776 | case QImage::Format_ARGB32:
|
|---|
| 777 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 778 | blit_template<quint16LE, quint32>(screen, image, topLeft, region);
|
|---|
| 779 | return;
|
|---|
| 780 | case QImage::Format_RGB16:
|
|---|
| 781 | blit_template<quint16LE, quint16>(screen, image, topLeft, region);
|
|---|
| 782 | return;
|
|---|
| 783 | default:
|
|---|
| 784 | qCritical("blit_16_bigToLittleEndian(): Image format %d not supported!", image.format());
|
|---|
| 785 | }
|
|---|
| 786 | }
|
|---|
| 787 |
|
|---|
| 788 | #endif // Q_BIG_ENDIAN
|
|---|
| 789 | #endif // QT_QWS_DEPTH_16
|
|---|
| 790 |
|
|---|
| 791 | #ifdef QT_QWS_DEPTH_15
|
|---|
| 792 | static void blit_15(QScreen *screen, const QImage &image,
|
|---|
| 793 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 794 | {
|
|---|
| 795 | switch (image.format()) {
|
|---|
| 796 | case QImage::Format_RGB32:
|
|---|
| 797 | case QImage::Format_ARGB32:
|
|---|
| 798 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 799 | blit_template<qrgb555, quint32>(screen, image, topLeft, region);
|
|---|
| 800 | return;
|
|---|
| 801 | case QImage::Format_RGB555:
|
|---|
| 802 | blit_template<qrgb555, qrgb555>(screen, image, topLeft, region);
|
|---|
| 803 | return;
|
|---|
| 804 | case QImage::Format_RGB16:
|
|---|
| 805 | blit_template<qrgb555, quint16>(screen, image, topLeft, region);
|
|---|
| 806 | return;
|
|---|
| 807 | default:
|
|---|
| 808 | qCritical("blit_15(): Image format %d not supported!", image.format());
|
|---|
| 809 | }
|
|---|
| 810 | }
|
|---|
| 811 |
|
|---|
| 812 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
|---|
| 813 | static void blit_15_bigToLittleEndian(QScreen *screen, const QImage &image,
|
|---|
| 814 | const QPoint &topLeft,
|
|---|
| 815 | const QRegion ®ion)
|
|---|
| 816 | {
|
|---|
| 817 | switch (image.format()) {
|
|---|
| 818 | case QImage::Format_RGB555:
|
|---|
| 819 | blit_template<quint16LE, qrgb555>(screen, image, topLeft, region);
|
|---|
| 820 | return;
|
|---|
| 821 | default:
|
|---|
| 822 | qCritical("blit_15_bigToLittleEndian(): Image format %d not supported!", image.format());
|
|---|
| 823 | }
|
|---|
| 824 | }
|
|---|
| 825 | #endif // Q_BIG_ENDIAN
|
|---|
| 826 | #endif // QT_QWS_DEPTH_15
|
|---|
| 827 |
|
|---|
| 828 |
|
|---|
| 829 | #ifdef QT_QWS_DEPTH_12
|
|---|
| 830 | static void blit_12(QScreen *screen, const QImage &image,
|
|---|
| 831 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 832 | {
|
|---|
| 833 | switch (image.format()) {
|
|---|
| 834 | case QImage::Format_ARGB4444_Premultiplied:
|
|---|
| 835 | blit_template<qrgb444, qargb4444>(screen, image, topLeft, region);
|
|---|
| 836 | return;
|
|---|
| 837 | case QImage::Format_RGB444:
|
|---|
| 838 | blit_template<qrgb444, qrgb444>(screen, image, topLeft, region);
|
|---|
| 839 | return;
|
|---|
| 840 | default:
|
|---|
| 841 | qCritical("blit_12(): Image format %d not supported!", image.format());
|
|---|
| 842 | }
|
|---|
| 843 | }
|
|---|
| 844 | #endif // QT_QWS_DEPTH_12
|
|---|
| 845 |
|
|---|
| 846 | #ifdef QT_QWS_DEPTH_8
|
|---|
| 847 | static void blit_8(QScreen *screen, const QImage &image,
|
|---|
| 848 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 849 | {
|
|---|
| 850 | switch (image.format()) {
|
|---|
| 851 | case QImage::Format_RGB32:
|
|---|
| 852 | case QImage::Format_ARGB32:
|
|---|
| 853 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 854 | blit_template<quint8, quint32>(screen, image, topLeft, region);
|
|---|
| 855 | return;
|
|---|
| 856 | case QImage::Format_RGB16:
|
|---|
| 857 | blit_template<quint8, quint16>(screen, image, topLeft, region);
|
|---|
| 858 | return;
|
|---|
| 859 | case QImage::Format_ARGB4444_Premultiplied:
|
|---|
| 860 | blit_template<quint8, qargb4444>(screen, image, topLeft, region);
|
|---|
| 861 | return;
|
|---|
| 862 | case QImage::Format_RGB444:
|
|---|
| 863 | blit_template<quint8, qrgb444>(screen, image, topLeft, region);
|
|---|
| 864 | return;
|
|---|
| 865 | default:
|
|---|
| 866 | qCritical("blit_8(): Image format %d not supported!", image.format());
|
|---|
| 867 | }
|
|---|
| 868 | }
|
|---|
| 869 | #endif // QT_QWS_DEPTH_8
|
|---|
| 870 |
|
|---|
| 871 | #ifdef QT_QWS_DEPTH_4
|
|---|
| 872 |
|
|---|
| 873 | struct qgray4 { quint8 dummy; } Q_PACKED;
|
|---|
| 874 |
|
|---|
| 875 | template <typename SRC>
|
|---|
| 876 | Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToGray4(SRC color);
|
|---|
| 877 |
|
|---|
| 878 | template <>
|
|---|
| 879 | inline quint8 qt_convertToGray4(quint32 color)
|
|---|
| 880 | {
|
|---|
| 881 | return qGray(color) >> 4;
|
|---|
| 882 | }
|
|---|
| 883 |
|
|---|
| 884 | template <>
|
|---|
| 885 | inline quint8 qt_convertToGray4(quint16 color)
|
|---|
| 886 | {
|
|---|
| 887 | const int r = (color & 0xf800) >> 11;
|
|---|
| 888 | const int g = (color & 0x07e0) >> 6; // only keep 5 bit
|
|---|
| 889 | const int b = (color & 0x001f);
|
|---|
| 890 | return (r * 11 + g * 16 + b * 5) >> 6;
|
|---|
| 891 | }
|
|---|
| 892 |
|
|---|
| 893 | template <>
|
|---|
| 894 | inline quint8 qt_convertToGray4(qrgb444 color)
|
|---|
| 895 | {
|
|---|
| 896 | return qt_convertToGray4(quint32(color));
|
|---|
| 897 | }
|
|---|
| 898 |
|
|---|
| 899 | template <>
|
|---|
| 900 | inline quint8 qt_convertToGray4(qargb4444 color)
|
|---|
| 901 | {
|
|---|
| 902 | return qt_convertToGray4(quint32(color));
|
|---|
| 903 | }
|
|---|
| 904 |
|
|---|
| 905 | template <typename SRC>
|
|---|
| 906 | Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectconvert_gray4(qgray4 *dest4, const SRC *src,
|
|---|
| 907 | int x, int y, int width, int height,
|
|---|
| 908 | int dstStride, int srcStride)
|
|---|
| 909 | {
|
|---|
| 910 | const int pixelsPerByte = 2;
|
|---|
| 911 | quint8 *dest8 = reinterpret_cast<quint8*>(dest4)
|
|---|
| 912 | + y * dstStride + x / pixelsPerByte;
|
|---|
| 913 | const int doAlign = x & 1;
|
|---|
| 914 | const int doTail = (width - doAlign) & 1;
|
|---|
| 915 | const int width8 = (width - doAlign) / pixelsPerByte;
|
|---|
| 916 | const int count8 = (width8 + 3) / 4;
|
|---|
| 917 |
|
|---|
| 918 | srcStride = srcStride / sizeof(SRC) - width;
|
|---|
| 919 | dstStride -= (width8 + doAlign);
|
|---|
| 920 |
|
|---|
| 921 | for (int i = 0; i < height; ++i) {
|
|---|
| 922 | if (doAlign) {
|
|---|
| 923 | *dest8 = (*dest8 & 0xf0) | qt_convertToGray4<SRC>(*src++);
|
|---|
| 924 | ++dest8;
|
|---|
| 925 | }
|
|---|
| 926 | if (count8) {
|
|---|
| 927 | int n = count8;
|
|---|
| 928 | switch (width8 & 0x03) // duff's device
|
|---|
| 929 | {
|
|---|
| 930 | case 0: do { *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
|
|---|
| 931 | | qt_convertToGray4<SRC>(src[1]);
|
|---|
| 932 | src += 2;
|
|---|
| 933 | case 3: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
|
|---|
| 934 | | qt_convertToGray4<SRC>(src[1]);
|
|---|
| 935 | src += 2;
|
|---|
| 936 | case 2: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
|
|---|
| 937 | | qt_convertToGray4<SRC>(src[1]);
|
|---|
| 938 | src += 2;
|
|---|
| 939 | case 1: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
|
|---|
| 940 | | qt_convertToGray4<SRC>(src[1]);
|
|---|
| 941 | src += 2;
|
|---|
| 942 | } while (--n > 0);
|
|---|
| 943 | }
|
|---|
| 944 | }
|
|---|
| 945 |
|
|---|
| 946 | if (doTail)
|
|---|
| 947 | *dest8 = qt_convertToGray4<SRC>(*src++) << 4 | (*dest8 & 0x0f);
|
|---|
| 948 |
|
|---|
| 949 | dest8 += dstStride;
|
|---|
| 950 | src += srcStride;
|
|---|
| 951 | }
|
|---|
| 952 | }
|
|---|
| 953 |
|
|---|
| 954 | template <>
|
|---|
| 955 | void qt_rectconvert(qgray4 *dest, const quint32 *src,
|
|---|
| 956 | int x, int y, int width, int height,
|
|---|
| 957 | int dstStride, int srcStride)
|
|---|
| 958 | {
|
|---|
| 959 | qt_rectconvert_gray4<quint32>(dest, src, x, y, width, height,
|
|---|
| 960 | dstStride, srcStride);
|
|---|
| 961 | }
|
|---|
| 962 |
|
|---|
| 963 | template <>
|
|---|
| 964 | void qt_rectconvert(qgray4 *dest, const quint16 *src,
|
|---|
| 965 | int x, int y, int width, int height,
|
|---|
| 966 | int dstStride, int srcStride)
|
|---|
| 967 | {
|
|---|
| 968 | qt_rectconvert_gray4<quint16>(dest, src, x, y, width, height,
|
|---|
| 969 | dstStride, srcStride);
|
|---|
| 970 | }
|
|---|
| 971 |
|
|---|
| 972 | template <>
|
|---|
| 973 | void qt_rectconvert(qgray4 *dest, const qrgb444 *src,
|
|---|
| 974 | int x, int y, int width, int height,
|
|---|
| 975 | int dstStride, int srcStride)
|
|---|
| 976 | {
|
|---|
| 977 | qt_rectconvert_gray4<qrgb444>(dest, src, x, y, width, height,
|
|---|
| 978 | dstStride, srcStride);
|
|---|
| 979 | }
|
|---|
| 980 |
|
|---|
| 981 | template <>
|
|---|
| 982 | void qt_rectconvert(qgray4 *dest, const qargb4444 *src,
|
|---|
| 983 | int x, int y, int width, int height,
|
|---|
| 984 | int dstStride, int srcStride)
|
|---|
| 985 | {
|
|---|
| 986 | qt_rectconvert_gray4<qargb4444>(dest, src, x, y, width, height,
|
|---|
| 987 | dstStride, srcStride);
|
|---|
| 988 | }
|
|---|
| 989 |
|
|---|
| 990 | static void blit_4(QScreen *screen, const QImage &image,
|
|---|
| 991 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 992 | {
|
|---|
| 993 | switch (image.format()) {
|
|---|
| 994 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 995 | blit_template<qgray4, quint32>(screen, image, topLeft, region);
|
|---|
| 996 | return;
|
|---|
| 997 | case QImage::Format_RGB16:
|
|---|
| 998 | blit_template<qgray4, quint16>(screen, image, topLeft, region);
|
|---|
| 999 | return;
|
|---|
| 1000 | case QImage::Format_RGB444:
|
|---|
| 1001 | blit_template<qgray4, qrgb444>(screen, image, topLeft, region);
|
|---|
| 1002 | return;
|
|---|
| 1003 | case QImage::Format_ARGB4444_Premultiplied:
|
|---|
| 1004 | blit_template<qgray4, qargb4444>(screen, image, topLeft, region);
|
|---|
| 1005 | return;
|
|---|
| 1006 | default:
|
|---|
| 1007 | qCritical("blit_4(): Image format %d not supported!", image.format());
|
|---|
| 1008 | }
|
|---|
| 1009 | }
|
|---|
| 1010 | #endif // QT_QWS_DEPTH_4
|
|---|
| 1011 |
|
|---|
| 1012 | #ifdef QT_QWS_DEPTH_1
|
|---|
| 1013 |
|
|---|
| 1014 | struct qmono { quint8 dummy; } Q_PACKED;
|
|---|
| 1015 |
|
|---|
| 1016 | template <typename SRC>
|
|---|
| 1017 | Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToMono(SRC color);
|
|---|
| 1018 |
|
|---|
| 1019 | template <>
|
|---|
| 1020 | inline quint8 qt_convertToMono(quint32 color)
|
|---|
| 1021 | {
|
|---|
| 1022 | return qGray(color) >> 7;
|
|---|
| 1023 | }
|
|---|
| 1024 |
|
|---|
| 1025 | template <>
|
|---|
| 1026 | inline quint8 qt_convertToMono(quint16 color)
|
|---|
| 1027 | {
|
|---|
| 1028 | return (qGray(qt_colorConvert<quint32, quint16>(color, 0)) >> 7);
|
|---|
| 1029 | }
|
|---|
| 1030 |
|
|---|
| 1031 | template <>
|
|---|
| 1032 | inline quint8 qt_convertToMono(qargb4444 color)
|
|---|
| 1033 | {
|
|---|
| 1034 | return (qGray(quint32(color)) >> 7);
|
|---|
| 1035 | }
|
|---|
| 1036 |
|
|---|
| 1037 | template <>
|
|---|
| 1038 | inline quint8 qt_convertToMono(qrgb444 color)
|
|---|
| 1039 | {
|
|---|
| 1040 | return (qGray(quint32(color)) >> 7);
|
|---|
| 1041 | }
|
|---|
| 1042 |
|
|---|
| 1043 | template <typename SRC>
|
|---|
| 1044 | inline void qt_rectconvert_mono(qmono *dest, const SRC *src,
|
|---|
| 1045 | int x, int y, int width, int height,
|
|---|
| 1046 | int dstStride, int srcStride)
|
|---|
| 1047 | {
|
|---|
| 1048 | const int pixelsPerByte = 8;
|
|---|
| 1049 | quint8 *dest8 = reinterpret_cast<quint8*>(dest)
|
|---|
| 1050 | + y * dstStride + x / pixelsPerByte;
|
|---|
| 1051 | const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
|
|---|
| 1052 | const int doAlign = (alignWidth > 0 ? 1 : 0);
|
|---|
| 1053 | const int alignStart = pixelsPerByte - 1 - (x & 7);
|
|---|
| 1054 | const int alignStop = alignStart - (alignWidth - 1);
|
|---|
| 1055 | const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
|
|---|
| 1056 | const int tailWidth = (width - alignWidth) & 7;
|
|---|
| 1057 | const int doTail = (tailWidth > 0 ? 1 : 0);
|
|---|
| 1058 | const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
|
|---|
| 1059 | const int width8 = (width - alignWidth) / pixelsPerByte;
|
|---|
| 1060 |
|
|---|
| 1061 | srcStride = srcStride / sizeof(SRC) - (width8 * 8 + alignWidth);
|
|---|
| 1062 | dstStride -= (width8 + doAlign);
|
|---|
| 1063 |
|
|---|
| 1064 | for (int j = 0; j < height; ++j) {
|
|---|
| 1065 | if (doAlign) {
|
|---|
| 1066 | quint8 d = *dest8 & ~alignMask;
|
|---|
| 1067 | for (int i = alignStart; i >= alignStop; --i)
|
|---|
| 1068 | d |= qt_convertToMono<SRC>(*src++) << i;
|
|---|
| 1069 | *dest8++ = d;
|
|---|
| 1070 | }
|
|---|
| 1071 | for (int i = 0; i < width8; ++i) {
|
|---|
| 1072 | *dest8 = (qt_convertToMono<SRC>(src[0]) << 7)
|
|---|
| 1073 | | (qt_convertToMono<SRC>(src[1]) << 6)
|
|---|
| 1074 | | (qt_convertToMono<SRC>(src[2]) << 5)
|
|---|
| 1075 | | (qt_convertToMono<SRC>(src[3]) << 4)
|
|---|
| 1076 | | (qt_convertToMono<SRC>(src[4]) << 3)
|
|---|
| 1077 | | (qt_convertToMono<SRC>(src[5]) << 2)
|
|---|
| 1078 | | (qt_convertToMono<SRC>(src[6]) << 1)
|
|---|
| 1079 | | (qt_convertToMono<SRC>(src[7]));
|
|---|
| 1080 | src += 8;
|
|---|
| 1081 | ++dest8;
|
|---|
| 1082 | }
|
|---|
| 1083 | if (doTail) {
|
|---|
| 1084 | quint8 d = *dest8 & tailMask;
|
|---|
| 1085 | switch (tailWidth) {
|
|---|
| 1086 | case 7: d |= qt_convertToMono<SRC>(src[6]) << 1;
|
|---|
| 1087 | case 6: d |= qt_convertToMono<SRC>(src[5]) << 2;
|
|---|
| 1088 | case 5: d |= qt_convertToMono<SRC>(src[4]) << 3;
|
|---|
| 1089 | case 4: d |= qt_convertToMono<SRC>(src[3]) << 4;
|
|---|
| 1090 | case 3: d |= qt_convertToMono<SRC>(src[2]) << 5;
|
|---|
| 1091 | case 2: d |= qt_convertToMono<SRC>(src[1]) << 6;
|
|---|
| 1092 | case 1: d |= qt_convertToMono<SRC>(src[0]) << 7;
|
|---|
| 1093 | }
|
|---|
| 1094 | *dest8 = d;
|
|---|
| 1095 | }
|
|---|
| 1096 |
|
|---|
| 1097 | dest8 += dstStride;
|
|---|
| 1098 | src += srcStride;
|
|---|
| 1099 | }
|
|---|
| 1100 | }
|
|---|
| 1101 |
|
|---|
| 1102 | template <>
|
|---|
| 1103 | void qt_rectconvert(qmono *dest, const quint32 *src,
|
|---|
| 1104 | int x, int y, int width, int height,
|
|---|
| 1105 | int dstStride, int srcStride)
|
|---|
| 1106 | {
|
|---|
| 1107 | qt_rectconvert_mono<quint32>(dest, src, x, y, width, height,
|
|---|
| 1108 | dstStride, srcStride);
|
|---|
| 1109 | }
|
|---|
| 1110 |
|
|---|
| 1111 | template <>
|
|---|
| 1112 | void qt_rectconvert(qmono *dest, const quint16 *src,
|
|---|
| 1113 | int x, int y, int width, int height,
|
|---|
| 1114 | int dstStride, int srcStride)
|
|---|
| 1115 | {
|
|---|
| 1116 | qt_rectconvert_mono<quint16>(dest, src, x, y, width, height,
|
|---|
| 1117 | dstStride, srcStride);
|
|---|
| 1118 | }
|
|---|
| 1119 |
|
|---|
| 1120 | template <>
|
|---|
| 1121 | void qt_rectconvert(qmono *dest, const qrgb444 *src,
|
|---|
| 1122 | int x, int y, int width, int height,
|
|---|
| 1123 | int dstStride, int srcStride)
|
|---|
| 1124 | {
|
|---|
| 1125 | qt_rectconvert_mono<qrgb444>(dest, src, x, y, width, height,
|
|---|
| 1126 | dstStride, srcStride);
|
|---|
| 1127 | }
|
|---|
| 1128 |
|
|---|
| 1129 | template <>
|
|---|
| 1130 | void qt_rectconvert(qmono *dest, const qargb4444 *src,
|
|---|
| 1131 | int x, int y, int width, int height,
|
|---|
| 1132 | int dstStride, int srcStride)
|
|---|
| 1133 | {
|
|---|
| 1134 | qt_rectconvert_mono<qargb4444>(dest, src, x, y, width, height,
|
|---|
| 1135 | dstStride, srcStride);
|
|---|
| 1136 | }
|
|---|
| 1137 |
|
|---|
| 1138 | static void blit_1(QScreen *screen, const QImage &image,
|
|---|
| 1139 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 1140 | {
|
|---|
| 1141 | switch (image.format()) {
|
|---|
| 1142 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 1143 | blit_template<qmono, quint32>(screen, image, topLeft, region);
|
|---|
| 1144 | return;
|
|---|
| 1145 | case QImage::Format_RGB16:
|
|---|
| 1146 | blit_template<qmono, quint16>(screen, image, topLeft, region);
|
|---|
| 1147 | return;
|
|---|
| 1148 | case QImage::Format_RGB444:
|
|---|
| 1149 | blit_template<qmono, qrgb444>(screen, image, topLeft, region);
|
|---|
| 1150 | return;
|
|---|
| 1151 | case QImage::Format_ARGB4444_Premultiplied:
|
|---|
| 1152 | blit_template<qmono, qargb4444>(screen, image, topLeft, region);
|
|---|
| 1153 | return;
|
|---|
| 1154 | default:
|
|---|
| 1155 | qCritical("blit_1(): Image format %d not supported!", image.format());
|
|---|
| 1156 | }
|
|---|
| 1157 | }
|
|---|
| 1158 | #endif // QT_QWS_DEPTH_1
|
|---|
| 1159 |
|
|---|
| 1160 | #ifdef QT_QWS_DEPTH_GENERIC
|
|---|
| 1161 |
|
|---|
| 1162 | static void blit_rgb(QScreen *screen, const QImage &image,
|
|---|
| 1163 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 1164 | {
|
|---|
| 1165 | switch (image.format()) {
|
|---|
| 1166 | case QImage::Format_ARGB32_Premultiplied:
|
|---|
| 1167 | blit_template<qrgb, quint32>(screen, image, topLeft, region);
|
|---|
| 1168 | return;
|
|---|
| 1169 | case QImage::Format_RGB16:
|
|---|
| 1170 | blit_template<qrgb, quint16>(screen, image, topLeft, region);
|
|---|
| 1171 | return;
|
|---|
| 1172 | default:
|
|---|
| 1173 | qCritical("blit_rgb(): Image format %d not supported!", image.format());
|
|---|
| 1174 | }
|
|---|
| 1175 | }
|
|---|
| 1176 |
|
|---|
| 1177 | void qt_set_generic_blit(QScreen *screen, int bpp,
|
|---|
| 1178 | int len_red, int len_green, int len_blue, int len_alpha,
|
|---|
| 1179 | int off_red, int off_green, int off_blue, int off_alpha)
|
|---|
| 1180 | {
|
|---|
| 1181 | qrgb::bpp = bpp / 8;
|
|---|
| 1182 | qrgb::len_red = len_red;
|
|---|
| 1183 | qrgb::len_green = len_green;
|
|---|
| 1184 | qrgb::len_blue = len_blue;
|
|---|
| 1185 | qrgb::len_alpha = len_alpha;
|
|---|
| 1186 | qrgb::off_red = off_red;
|
|---|
| 1187 | qrgb::off_green = off_green;
|
|---|
| 1188 | qrgb::off_blue = off_blue;
|
|---|
| 1189 | qrgb::off_alpha = off_alpha;
|
|---|
| 1190 | screen->d_ptr->blit = blit_rgb;
|
|---|
| 1191 | if (bpp == 16)
|
|---|
| 1192 | screen->d_ptr->solidFill = solidFill_rgb_16bpp;
|
|---|
| 1193 | else if (bpp == 32)
|
|---|
| 1194 | screen->d_ptr->solidFill = solidFill_rgb_32bpp;
|
|---|
| 1195 | }
|
|---|
| 1196 |
|
|---|
| 1197 | #endif // QT_QWS_DEPTH_GENERIC
|
|---|
| 1198 |
|
|---|
| 1199 | void qt_blit_setup(QScreen *screen, const QImage &image,
|
|---|
| 1200 | const QPoint &topLeft, const QRegion ®ion)
|
|---|
| 1201 | {
|
|---|
| 1202 | switch (screen->depth()) {
|
|---|
| 1203 | #ifdef QT_QWS_DEPTH_32
|
|---|
| 1204 | case 32:
|
|---|
| 1205 | if (screen->pixelType() == QScreen::NormalPixel)
|
|---|
| 1206 | screen->d_ptr->blit = blit_32;
|
|---|
| 1207 | else
|
|---|
| 1208 | screen->d_ptr->blit = blit_template<qabgr8888, quint32>;
|
|---|
| 1209 | break;
|
|---|
| 1210 | #endif
|
|---|
| 1211 | #ifdef QT_QWS_DEPTH_24
|
|---|
| 1212 | case 24:
|
|---|
| 1213 | if (screen->pixelType() == QScreen::NormalPixel)
|
|---|
| 1214 | screen->d_ptr->blit = blit_qrgb888;
|
|---|
| 1215 | else
|
|---|
| 1216 | screen->d_ptr->blit = blit_24;
|
|---|
| 1217 | break;
|
|---|
| 1218 | #endif
|
|---|
| 1219 | #ifdef QT_QWS_DEPTH_18
|
|---|
| 1220 | case 18:
|
|---|
| 1221 | screen->d_ptr->blit = blit_18;
|
|---|
|
|---|