Merge remote branch 'staging/master' into refactor
[profile/ivi/qtbase.git] / src / gui / painting / qmemrotate.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qmemrotate_p.h"
43
44 QT_BEGIN_NAMESPACE
45
46 #if QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
47 static const int tileSize = 32;
48 #endif
49
50 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
51 #if QT_ROTATION_ALGORITHM == QT_ROTATION_PACKED || QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
52 #error Big endian version not implemented for the transformed driver!
53 #endif
54 #endif
55
56 template <class DST, class SRC>
57 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_cachedRead(const SRC *src, int w, int h,
58                                              int sstride,
59                                              DST *dest, int dstride)
60 {
61     const char *s = reinterpret_cast<const char*>(src);
62     char *d = reinterpret_cast<char*>(dest);
63     for (int y = 0; y < h; ++y) {
64         for (int x = w - 1; x >= 0; --x) {
65             DST *destline = reinterpret_cast<DST*>(d + (w - x - 1) * dstride);
66             destline[y] = qt_colorConvert<DST,SRC>(src[x], 0);
67         }
68         s += sstride;
69         src = reinterpret_cast<const SRC*>(s);
70     }
71 }
72
73 template <class DST, class SRC>
74 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_cachedRead(const SRC *src, int w, int h,
75                                               int sstride,
76                                               DST *dest, int dstride)
77 {
78     const char *s = reinterpret_cast<const char*>(src);
79     char *d = reinterpret_cast<char*>(dest);
80     s += (h - 1) * sstride;
81     for (int y = h - 1; y >= 0; --y) {
82         src = reinterpret_cast<const SRC*>(s);
83         for (int x = 0; x < w; ++x) {
84             DST *destline = reinterpret_cast<DST*>(d + x * dstride);
85             destline[h - y - 1] = qt_colorConvert<DST,SRC>(src[x], 0);
86         }
87         s -= sstride;
88     }
89 }
90
91 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
92
93 template <class DST, class SRC>
94 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_cachedWrite(const SRC *src, int w, int h,
95                                               int sstride,
96                                               DST *dest, int dstride)
97 {
98     for (int x = w - 1; x >= 0; --x) {
99         DST *d = dest + (w - x - 1) * dstride;
100         for (int y = 0; y < h; ++y) {
101             *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
102         }
103     }
104
105 }
106
107 template <class DST, class SRC>
108 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_cachedWrite(const SRC *src, int w, int h,
109                                                int sstride,
110                                                DST *dest, int dstride)
111 {
112     for (int x = 0; x < w; ++x) {
113         DST *d = dest + x * dstride;
114         for (int y = h - 1; y >= 0; --y) {
115             *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
116         }
117     }
118 }
119
120 #endif // QT_ROTATION_CACHEDWRITE
121
122 #if QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
123
124 // TODO: packing algorithms should probably be modified on 64-bit architectures
125
126 template <class DST, class SRC>
127 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_packing(const SRC *src, int w, int h,
128                                           int sstride,
129                                           DST *dest, int dstride)
130 {
131     sstride /= sizeof(SRC);
132     dstride /= sizeof(DST);
133
134     const int pack = sizeof(quint32) / sizeof(DST);
135     const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(DST);
136
137     for (int x = w - 1; x >= 0; --x) {
138         int y = 0;
139
140         for (int i = 0; i < unaligned; ++i) {
141             dest[(w - x - 1) * dstride + y]
142                 = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
143             ++y;
144         }
145
146         quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride
147                                                 + unaligned);
148         const int rest = (h - unaligned) % pack;
149         while (y < h - rest) {
150             quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
151             for (int i = 1; i < pack; ++i) {
152                 c |= qt_colorConvert<DST,SRC>(src[(y + i) * sstride + x], 0)
153                      << (sizeof(int) * 8 / pack * i);
154             }
155             *d++ = c;
156             y += pack;
157         }
158
159         while (y < h) {
160             dest[(w - x - 1) * dstride + y]
161                 = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
162             ++y;
163         }
164     }
165 }
166
167 template <class DST, class SRC>
168 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_packing(const SRC *src, int w, int h,
169                                            int sstride,
170                                            DST *dest, int dstride)
171 {
172     sstride /= sizeof(SRC);
173     dstride /= sizeof(DST);
174
175     const int pack = sizeof(quint32) / sizeof(DST);
176     const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(DST);
177
178     for (int x = 0; x < w; ++x) {
179         int y = h - 1;
180
181         for (int i = 0; i < unaligned; ++i) {
182             dest[x * dstride + h - y - 1]
183                 = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
184             --y;
185         }
186
187         quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
188                                                 + unaligned);
189         const int rest = (h - unaligned) % pack;
190         while (y > rest) {
191             quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
192             for (int i = 1; i < pack; ++i) {
193                 c |= qt_colorConvert<DST,SRC>(src[(y - i) * sstride + x], 0)
194                      << (sizeof(int) * 8 / pack * i);
195             }
196             *d++ = c;
197             y -= pack;
198         }
199         while (y >= 0) {
200             dest[x * dstride + h - y - 1]
201                 = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
202             --y;
203         }
204     }
205 }
206
207 #endif // QT_ROTATION_PACKING
208
209 #if QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
210 template <class DST, class SRC>
211 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled(const SRC *src, int w, int h,
212                                         int sstride,
213                                         DST *dest, int dstride)
214 {
215     sstride /= sizeof(SRC);
216     dstride /= sizeof(DST);
217
218     const int pack = sizeof(quint32) / sizeof(DST);
219     const int unaligned =
220         qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(DST)), uint(h));
221     const int restX = w % tileSize;
222     const int restY = (h - unaligned) % tileSize;
223     const int unoptimizedY = restY % pack;
224     const int numTilesX = w / tileSize + (restX > 0);
225     const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
226
227     for (int tx = 0; tx < numTilesX; ++tx) {
228         const int startx = w - tx * tileSize - 1;
229         const int stopx = qMax(startx - tileSize, 0);
230
231         if (unaligned) {
232             for (int x = startx; x >= stopx; --x) {
233                 DST *d = dest + (w - x - 1) * dstride;
234                 for (int y = 0; y < unaligned; ++y) {
235                     *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
236                 }
237             }
238         }
239
240         for (int ty = 0; ty < numTilesY; ++ty) {
241             const int starty = ty * tileSize + unaligned;
242             const int stopy = qMin(starty + tileSize, h - unoptimizedY);
243
244             for (int x = startx; x >= stopx; --x) {
245                 quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride + starty);
246                 for (int y = starty; y < stopy; y += pack) {
247                     quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
248                     for (int i = 1; i < pack; ++i) {
249                         const int shift = (sizeof(int) * 8 / pack * i);
250                         const DST color = qt_colorConvert<DST,SRC>(src[(y + i) * sstride + x], 0);
251                         c |= color << shift;
252                     }
253                     *d++ = c;
254                 }
255             }
256         }
257
258         if (unoptimizedY) {
259             const int starty = h - unoptimizedY;
260             for (int x = startx; x >= stopx; --x) {
261                 DST *d = dest + (w - x - 1) * dstride + starty;
262                 for (int y = starty; y < h; ++y) {
263                     *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
264                 }
265             }
266         }
267     }
268 }
269
270 template <class DST, class SRC>
271 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled_unpacked(const SRC *src, int w, int h,
272                                                  int sstride,
273                                                  DST *dest, int dstride)
274 {
275     const int numTilesX = (w + tileSize - 1) / tileSize;
276     const int numTilesY = (h + tileSize - 1) / tileSize;
277
278     for (int tx = 0; tx < numTilesX; ++tx) {
279         const int startx = w - tx * tileSize - 1;
280         const int stopx = qMax(startx - tileSize, 0);
281
282         for (int ty = 0; ty < numTilesY; ++ty) {
283             const int starty = ty * tileSize;
284             const int stopy = qMin(starty + tileSize, h);
285
286             for (int x = startx; x >= stopx; --x) {
287                 DST *d = (DST*)((char*)dest + (w - x - 1) * dstride) + starty;
288                 const char *s = (const char*)(src + x) + starty * sstride;
289                 for (int y = starty; y < stopy; ++y) {
290                     *d++ = qt_colorConvert<DST,SRC>(*(const SRC*)(s), 0);
291                     s += sstride;
292                 }
293             }
294         }
295     }
296 }
297
298 template <class DST, class SRC>
299 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled(const SRC *src, int w, int h,
300                                          int sstride,
301                                          DST *dest, int dstride)
302 {
303     sstride /= sizeof(SRC);
304     dstride /= sizeof(DST);
305
306     const int pack = sizeof(quint32) / sizeof(DST);
307     const int unaligned =
308         qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(DST)), uint(h));
309     const int restX = w % tileSize;
310     const int restY = (h - unaligned) % tileSize;
311     const int unoptimizedY = restY % pack;
312     const int numTilesX = w / tileSize + (restX > 0);
313     const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
314
315     for (int tx = 0; tx < numTilesX; ++tx) {
316         const int startx = tx * tileSize;
317         const int stopx = qMin(startx + tileSize, w);
318
319         if (unaligned) {
320             for (int x = startx; x < stopx; ++x) {
321                 DST *d = dest + x * dstride;
322                 for (int y = h - 1; y >= h - unaligned; --y) {
323                     *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
324                 }
325             }
326         }
327
328         for (int ty = 0; ty < numTilesY; ++ty) {
329             const int starty = h - 1 - unaligned - ty * tileSize;
330             const int stopy = qMax(starty - tileSize, unoptimizedY);
331
332             for (int x = startx; x < stopx; ++x) {
333                 quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
334                                                         + h - 1 - starty);
335                 for (int y = starty; y > stopy; y -= pack) {
336                     quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
337                     for (int i = 1; i < pack; ++i) {
338                         const int shift = (sizeof(int) * 8 / pack * i);
339                         const DST color = qt_colorConvert<DST,SRC>(src[(y - i) * sstride + x], 0);
340                         c |= color << shift;
341                     }
342                     *d++ = c;
343                 }
344             }
345         }
346         if (unoptimizedY) {
347             const int starty = unoptimizedY - 1;
348             for (int x = startx; x < stopx; ++x) {
349                 DST *d = dest + x * dstride + h - 1 - starty;
350                 for (int y = starty; y >= 0; --y) {
351                     *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0);
352                 }
353             }
354         }
355     }
356 }
357
358 template <class DST, class SRC>
359 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled_unpacked(const SRC *src, int w, int h,
360                                                   int sstride,
361                                                   DST *dest, int dstride)
362 {
363     const int numTilesX = (w + tileSize - 1) / tileSize;
364     const int numTilesY = (h + tileSize - 1) / tileSize;
365
366     for (int tx = 0; tx < numTilesX; ++tx) {
367         const int startx = tx * tileSize;
368         const int stopx = qMin(startx + tileSize, w);
369
370         for (int ty = 0; ty < numTilesY; ++ty) {
371             const int starty = h - 1 - ty * tileSize;
372             const int stopy = qMax(starty - tileSize, 0);
373
374             for (int x = startx; x < stopx; ++x) {
375                 DST *d = (DST*)((char*)dest + x * dstride) + h - 1 - starty;
376                 const char *s = (const char*)(src + x) + starty * sstride;
377                 for (int y = starty; y >= stopy; --y) {
378                     *d++ = qt_colorConvert<DST,SRC>(*(const SRC*)s, 0);
379                     s -= sstride;
380                 }
381             }
382         }
383     }
384 }
385
386 #endif // QT_ROTATION_ALGORITHM
387
388 template <class DST, class SRC>
389 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_template(const SRC *src,
390                                            int srcWidth, int srcHeight, int srcStride,
391                                            DST *dest, int dstStride)
392 {
393 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
394     qt_memrotate90_cachedRead<DST,SRC>(src, srcWidth, srcHeight, srcStride,
395                                        dest, dstStride);
396 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
397     qt_memrotate90_cachedWrite<DST,SRC>(src, srcWidth, srcHeight, srcStride,
398                                         dest, dstStride);
399 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
400     qt_memrotate90_packing<DST,SRC>(src, srcWidth, srcHeight, srcStride,
401                                     dest, dstStride);
402 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
403     qt_memrotate90_tiled<DST,SRC>(src, srcWidth, srcHeight, srcStride,
404                                   dest, dstStride);
405 #endif
406 }
407
408 template <class DST, class SRC>
409 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate180_template(const SRC *src,
410                                             int w, int h, int sstride,
411                                             DST *dest, int dstride)
412 {
413     const char *s = (const char*)(src) + (h - 1) * sstride;
414     for (int y = h - 1; y >= 0; --y) {
415         DST *d = reinterpret_cast<DST*>((char *)(dest) + (h - y - 1) * dstride);
416         src = reinterpret_cast<const SRC*>(s);
417         for (int x = w - 1; x >= 0; --x) {
418             d[w - x - 1] = qt_colorConvert<DST,SRC>(src[x], 0);
419         }
420         s -= sstride;
421     }
422 }
423
424 template <class DST, class SRC>
425 Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_template(const SRC *src,
426                                             int srcWidth, int srcHeight, int srcStride,
427                                             DST *dest, int dstStride)
428 {
429 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
430     qt_memrotate270_cachedRead<DST,SRC>(src, srcWidth, srcHeight, srcStride,
431                                         dest, dstStride);
432 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
433     qt_memrotate270_cachedWrite<DST,SRC>(src, srcWidth, srcHeight, srcStride,
434                                          dest, dstStride);
435 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
436     qt_memrotate270_packing<DST,SRC>(src, srcWidth, srcHeight, srcStride,
437                                      dest, dstStride);
438 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
439     qt_memrotate270_tiled_unpacked<DST,SRC>(src, srcWidth, srcHeight,
440                                             srcStride,
441                                             dest, dstStride);
442 #endif
443 }
444
445 template <>
446 Q_STATIC_TEMPLATE_SPECIALIZATION
447 inline void qt_memrotate90_template<quint24, quint24>(const quint24 *src,
448                                                              int srcWidth, int srcHeight, int srcStride,
449                                                              quint24 *dest, int dstStride)
450 {
451 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
452     qt_memrotate90_cachedRead<quint24,quint24>(src, srcWidth, srcHeight,
453                                                srcStride, dest, dstStride);
454 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
455     qt_memrotate90_cachedWrite<quint24,quint24>(src, srcWidth, srcHeight,
456                                                 srcStride, dest, dstStride);
457 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
458     // packed algorithm not implemented
459     qt_memrotate90_cachedRead<quint24,quint24>(src, srcWidth, srcHeight,
460                                                srcStride, dest, dstStride);
461 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
462     // packed algorithm not implemented
463     qt_memrotate90_tiled_unpacked<quint24,quint24>(src, srcWidth, srcHeight,
464                                                    srcStride, dest, dstStride);
465 #endif
466 }
467
468 template <>
469 Q_STATIC_TEMPLATE_SPECIALIZATION
470 inline void qt_memrotate90_template<quint24, quint32>(const quint32 *src,
471                                                              int srcWidth, int srcHeight, int srcStride,
472                                                              quint24 *dest, int dstStride)
473 {
474 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
475     qt_memrotate90_cachedRead<quint24,quint32>(src, srcWidth, srcHeight,
476                                                srcStride, dest, dstStride);
477 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
478     qt_memrotate90_cachedWrite<quint24,quint32>(src, srcWidth, srcHeight,
479                                                 srcStride, dest, dstStride);
480 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
481     // packed algorithm not implemented
482     qt_memrotate90_cachedRead<quint24,quint32>(src, srcWidth, srcHeight,
483                                                srcStride, dest, dstStride);
484 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
485     // packed algorithm not implemented
486     qt_memrotate90_tiled_unpacked<quint24,quint32>(src, srcWidth, srcHeight,
487                                                    srcStride, dest, dstStride);
488 #endif
489 }
490
491 template <>
492 Q_STATIC_TEMPLATE_SPECIALIZATION
493 inline void qt_memrotate90_template<quint18, quint32>(const quint32 *src,
494                                                              int srcWidth, int srcHeight, int srcStride,
495                                                              quint18 *dest, int dstStride)
496 {
497 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
498     qt_memrotate90_cachedRead<quint18,quint32>(src, srcWidth, srcHeight,
499                                                srcStride, dest, dstStride);
500 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
501     qt_memrotate90_cachedWrite<quint18,quint32>(src, srcWidth, srcHeight,
502                                                 srcStride, dest, dstStride);
503 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
504     // packed algorithm not implemented
505     qt_memrotate90_cachedRead<quint18,quint32>(src, srcWidth, srcHeight,
506                                                srcStride, dest, dstStride);
507 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
508     // packed algorithm not implemented
509     qt_memrotate90_tiled_unpacked<quint18,quint32>(src, srcWidth, srcHeight,
510                                                    srcStride, dest, dstStride);
511 #endif
512 }
513
514 #define QT_IMPL_MEMROTATE(srctype, desttype)                        \
515 Q_GUI_EXPORT void qt_memrotate90(const srctype *src, int w, int h, int sstride,  \
516                     desttype *dest, int dstride)                    \
517 {                                                                   \
518     qt_memrotate90_template(src, w, h, sstride, dest, dstride);     \
519 }                                                                   \
520 Q_GUI_EXPORT void qt_memrotate180(const srctype *src, int w, int h, int sstride, \
521                      desttype *dest, int dstride)                   \
522 {                                                                   \
523     qt_memrotate180_template(src, w, h, sstride, dest, dstride);    \
524 }                                                                   \
525 Q_GUI_EXPORT void qt_memrotate270(const srctype *src, int w, int h, int sstride, \
526                      desttype *dest, int dstride)                   \
527 {                                                                   \
528     qt_memrotate270_template(src, w, h, sstride, dest, dstride);    \
529 }
530
531 #define QT_IMPL_SIMPLE_MEMROTATE(srctype, desttype)                 \
532 Q_GUI_EXPORT void qt_memrotate90(const srctype *src, int w, int h, int sstride,  \
533                     desttype *dest, int dstride)                    \
534 {                                                                   \
535     qt_memrotate90_tiled_unpacked<desttype,srctype>(src, w, h, sstride, dest, dstride); \
536 }                                                                   \
537 Q_GUI_EXPORT void qt_memrotate180(const srctype *src, int w, int h, int sstride, \
538                      desttype *dest, int dstride)                   \
539 {                                                                   \
540     qt_memrotate180_template(src, w, h, sstride, dest, dstride);    \
541 }                                                                   \
542 Q_GUI_EXPORT void qt_memrotate270(const srctype *src, int w, int h, int sstride, \
543                      desttype *dest, int dstride)                   \
544 {                                                                   \
545     qt_memrotate270_tiled_unpacked<desttype,srctype>(src, w, h, sstride, dest, dstride); \
546 }
547
548
549
550
551 QT_IMPL_MEMROTATE(quint32, quint32)
552 QT_IMPL_MEMROTATE(quint32, quint16)
553 QT_IMPL_MEMROTATE(quint16, quint32)
554 QT_IMPL_MEMROTATE(quint16, quint16)
555 QT_IMPL_MEMROTATE(quint24, quint24)
556 QT_IMPL_MEMROTATE(quint32, quint24)
557 QT_IMPL_MEMROTATE(quint32, quint18)
558 QT_IMPL_MEMROTATE(quint32, quint8)
559 QT_IMPL_MEMROTATE(quint16, quint8)
560 QT_IMPL_MEMROTATE(qrgb444, quint8)
561 QT_IMPL_MEMROTATE(quint8, quint8)
562
563 #if defined(QT_QWS_ROTATE_BGR)
564 QT_IMPL_SIMPLE_MEMROTATE(quint16, qbgr565)
565 QT_IMPL_SIMPLE_MEMROTATE(quint32, qbgr565)
566 QT_IMPL_SIMPLE_MEMROTATE(qrgb555, qbgr555)
567 QT_IMPL_SIMPLE_MEMROTATE(quint32, qbgr555)
568 #endif
569
570 #ifdef QT_QWS_DEPTH_GENERIC
571 QT_IMPL_MEMROTATE(quint32, qrgb_generic16)
572 QT_IMPL_MEMROTATE(quint16, qrgb_generic16)
573 #endif
574
575 struct qrgb_gl_rgba
576 {
577 public:
578     inline qrgb_gl_rgba(quint32 v) {
579         if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
580             data = ((v << 16) & 0xff0000) | ((v >> 16) & 0xff) | (v & 0xff00ff00);
581         else
582             data = (v << 8) | ((v >> 24) & 0xff);
583     }
584
585     inline operator quint32() const { return data; }
586
587 private:
588     quint32 data;
589 } Q_PACKED;
590
591 void Q_GUI_EXPORT qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride,
592                                     quint32 *dest, int dstStride)
593 {
594     qt_memrotate90_template(src, srcWidth, srcHeight, srcStride, reinterpret_cast<qrgb_gl_rgba *>(dest), dstStride);
595 }
596
597 void qt_memrotate90_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
598 {
599     qt_memrotate90((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
600 }
601
602 void qt_memrotate180_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
603 {
604     qt_memrotate180((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
605 }
606
607 void qt_memrotate270_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
608 {
609     qt_memrotate270((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
610 }
611
612 void qt_memrotate90_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
613 {
614     qt_memrotate90((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
615 }
616
617 void qt_memrotate180_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
618 {
619     qt_memrotate180((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
620 }
621
622 void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
623 {
624     qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
625 }
626
627 MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] =
628 // 90, 180, 270
629 {
630     { 0, 0, 0 },      // Format_Invalid,
631     { 0, 0, 0 },      // Format_Mono,
632     { 0, 0, 0 },      // Format_MonoLSB,
633     { 0, 0, 0 },      // Format_Indexed8,
634     { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_RGB32,
635     { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_ARGB32,
636     { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_ARGB32_Premultiplied,
637     { qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 },      // Format_RGB16,
638     { 0, 0, 0 },      // Format_ARGB8565_Premultiplied,
639     { 0, 0, 0 },      // Format_RGB666,
640     { 0, 0, 0 },      // Format_ARGB6666_Premultiplied,
641     { 0, 0, 0 },      // Format_RGB555,
642     { 0, 0, 0 },      // Format_ARGB8555_Premultiplied,
643     { 0, 0, 0 },      // Format_RGB888,
644     { 0, 0, 0 },      // Format_RGB444,
645     { 0, 0, 0 }       // Format_ARGB4444_Premultiplied,
646 };
647
648 QT_END_NAMESPACE