Update spec to build Qt 5.0
[profile/ivi/qtbase.git] / src / gui / painting / qmemrotate.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 T>
57 Q_STATIC_TEMPLATE_FUNCTION
58 inline void qt_memrotate90_cachedRead(const T *src, int w, int h, int sstride, T *dest,
59                                       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             T *destline = reinterpret_cast<T *>(d + (w - x - 1) * dstride);
66             destline[y] = src[x];
67         }
68         s += sstride;
69         src = reinterpret_cast<const T*>(s);
70     }
71 }
72
73 template <class T>
74 Q_STATIC_TEMPLATE_FUNCTION
75 inline void qt_memrotate270_cachedRead(const T *src, int w, int h, int sstride, T *dest,
76                                        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 T*>(s);
83         for (int x = 0; x < w; ++x) {
84             T *destline = reinterpret_cast<T *>(d + x * dstride);
85             destline[h - y - 1] = src[x];
86         }
87         s -= sstride;
88     }
89 }
90
91 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
92
93 template <class T>
94 Q_STATIC_TEMPLATE_FUNCTION
95 inline void qt_memrotate90_cachedWrite(const T *src, int w, int h, int sstride, T *dest,
96                                        int dstride)
97 {
98     for (int x = w - 1; x >= 0; --x) {
99         T *d = dest + (w - x - 1) * dstride;
100         for (int y = 0; y < h; ++y) {
101             *d++ = src[y * sstride + x];
102         }
103     }
104
105 }
106
107 template <class T>
108 Q_STATIC_TEMPLATE_FUNCTION
109 inline void qt_memrotate270_cachedWrite(const T *src, int w, int h, int sstride, T *dest,
110                                         int dstride)
111 {
112     for (int x = 0; x < w; ++x) {
113         T *d = dest + x * dstride;
114         for (int y = h - 1; y >= 0; --y) {
115             *d++ = src[y * sstride + x];
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 T>
127 Q_STATIC_TEMPLATE_FUNCTION
128 inline void qt_memrotate90_packing(const T *src, int w, int h, int sstride, T *dest, int dstride)
129 {
130     sstride /= sizeof(T);
131     dstride /= sizeof(T);
132
133     const int pack = sizeof(quint32) / sizeof(T);
134     const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(T);
135
136     for (int x = w - 1; x >= 0; --x) {
137         int y = 0;
138
139         for (int i = 0; i < unaligned; ++i) {
140             dest[(w - x - 1) * dstride + y] = src[y * sstride + x];
141             ++y;
142         }
143
144         quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride
145                                                 + unaligned);
146         const int rest = (h - unaligned) % pack;
147         while (y < h - rest) {
148             quint32 c = src[y * sstride + x];
149             for (int i = 1; i < pack; ++i) {
150                 c |= src[(y + i) * sstride + x] << (sizeof(int) * 8 / pack * i);
151             }
152             *d++ = c;
153             y += pack;
154         }
155
156         while (y < h) {
157             dest[(w - x - 1) * dstride + y] = src[y * sstride + x];
158             ++y;
159         }
160     }
161 }
162
163 template <class T>
164 Q_STATIC_TEMPLATE_FUNCTION
165 inline void qt_memrotate270_packing(const T *src, int w, int h, int sstride, T *dest, int dstride)
166 {
167     sstride /= sizeof(T);
168     dstride /= sizeof(T);
169
170     const int pack = sizeof(quint32) / sizeof(T);
171     const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(T);
172
173     for (int x = 0; x < w; ++x) {
174         int y = h - 1;
175
176         for (int i = 0; i < unaligned; ++i) {
177             dest[x * dstride + h - y - 1] = src[y * sstride + x];
178             --y;
179         }
180
181         quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
182                                                 + unaligned);
183         const int rest = (h - unaligned) % pack;
184         while (y > rest) {
185             quint32 c = src[y * sstride + x];
186             for (int i = 1; i < pack; ++i) {
187                 c |= src[(y - i) * sstride + x] << (sizeof(int) * 8 / pack * i);
188             }
189             *d++ = c;
190             y -= pack;
191         }
192         while (y >= 0) {
193             dest[x * dstride + h - y - 1] = src[y * sstride + x];
194             --y;
195         }
196     }
197 }
198
199 #endif // QT_ROTATION_PACKING
200
201 #if QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
202 template <class T>
203 Q_STATIC_TEMPLATE_FUNCTION
204 inline void qt_memrotate90_tiled(const T *src, int w, int h, int sstride, T *dest, int dstride)
205 {
206     sstride /= sizeof(T);
207     dstride /= sizeof(T);
208
209     const int pack = sizeof(quint32) / sizeof(T);
210     const int unaligned =
211         qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h));
212     const int restX = w % tileSize;
213     const int restY = (h - unaligned) % tileSize;
214     const int unoptimizedY = restY % pack;
215     const int numTilesX = w / tileSize + (restX > 0);
216     const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
217
218     for (int tx = 0; tx < numTilesX; ++tx) {
219         const int startx = w - tx * tileSize - 1;
220         const int stopx = qMax(startx - tileSize, 0);
221
222         if (unaligned) {
223             for (int x = startx; x >= stopx; --x) {
224                 T *d = dest + (w - x - 1) * dstride;
225                 for (int y = 0; y < unaligned; ++y) {
226                     *d++ = src[y * sstride + x];
227                 }
228             }
229         }
230
231         for (int ty = 0; ty < numTilesY; ++ty) {
232             const int starty = ty * tileSize + unaligned;
233             const int stopy = qMin(starty + tileSize, h - unoptimizedY);
234
235             for (int x = startx; x >= stopx; --x) {
236                 quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride + starty);
237                 for (int y = starty; y < stopy; y += pack) {
238                     quint32 c = src[y * sstride + x];
239                     for (int i = 1; i < pack; ++i) {
240                         const int shift = (sizeof(int) * 8 / pack * i);
241                         const T color = src[(y + i) * sstride + x];
242                         c |= color << shift;
243                     }
244                     *d++ = c;
245                 }
246             }
247         }
248
249         if (unoptimizedY) {
250             const int starty = h - unoptimizedY;
251             for (int x = startx; x >= stopx; --x) {
252                 T *d = dest + (w - x - 1) * dstride + starty;
253                 for (int y = starty; y < h; ++y) {
254                     *d++ = src[y * sstride + x];
255                 }
256             }
257         }
258     }
259 }
260
261 template <class T>
262 Q_STATIC_TEMPLATE_FUNCTION
263 inline void qt_memrotate90_tiled_unpacked(const T *src, int w, int h, int sstride, T *dest,
264                                           int dstride)
265 {
266     const int numTilesX = (w + tileSize - 1) / tileSize;
267     const int numTilesY = (h + tileSize - 1) / tileSize;
268
269     for (int tx = 0; tx < numTilesX; ++tx) {
270         const int startx = w - tx * tileSize - 1;
271         const int stopx = qMax(startx - tileSize, 0);
272
273         for (int ty = 0; ty < numTilesY; ++ty) {
274             const int starty = ty * tileSize;
275             const int stopy = qMin(starty + tileSize, h);
276
277             for (int x = startx; x >= stopx; --x) {
278                 T *d = (T *)((char*)dest + (w - x - 1) * dstride) + starty;
279                 const char *s = (const char*)(src + x) + starty * sstride;
280                 for (int y = starty; y < stopy; ++y) {
281                     *d++ = *(const T *)(s);
282                     s += sstride;
283                 }
284             }
285         }
286     }
287 }
288
289 template <class T>
290 Q_STATIC_TEMPLATE_FUNCTION
291 inline void qt_memrotate270_tiled(const T *src, int w, int h, int sstride, T *dest, int dstride)
292 {
293     sstride /= sizeof(T);
294     dstride /= sizeof(T);
295
296     const int pack = sizeof(quint32) / sizeof(T);
297     const int unaligned =
298         qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h));
299     const int restX = w % tileSize;
300     const int restY = (h - unaligned) % tileSize;
301     const int unoptimizedY = restY % pack;
302     const int numTilesX = w / tileSize + (restX > 0);
303     const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
304
305     for (int tx = 0; tx < numTilesX; ++tx) {
306         const int startx = tx * tileSize;
307         const int stopx = qMin(startx + tileSize, w);
308
309         if (unaligned) {
310             for (int x = startx; x < stopx; ++x) {
311                 T *d = dest + x * dstride;
312                 for (int y = h - 1; y >= h - unaligned; --y) {
313                     *d++ = src[y * sstride + x];
314                 }
315             }
316         }
317
318         for (int ty = 0; ty < numTilesY; ++ty) {
319             const int starty = h - 1 - unaligned - ty * tileSize;
320             const int stopy = qMax(starty - tileSize, unoptimizedY);
321
322             for (int x = startx; x < stopx; ++x) {
323                 quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
324                                                         + h - 1 - starty);
325                 for (int y = starty; y > stopy; y -= pack) {
326                     quint32 c = src[y * sstride + x];
327                     for (int i = 1; i < pack; ++i) {
328                         const int shift = (sizeof(int) * 8 / pack * i);
329                         const T color = src[(y - i) * sstride + x];
330                         c |= color << shift;
331                     }
332                     *d++ = c;
333                 }
334             }
335         }
336         if (unoptimizedY) {
337             const int starty = unoptimizedY - 1;
338             for (int x = startx; x < stopx; ++x) {
339                 T *d = dest + x * dstride + h - 1 - starty;
340                 for (int y = starty; y >= 0; --y) {
341                     *d++ = src[y * sstride + x];
342                 }
343             }
344         }
345     }
346 }
347
348 template <class T>
349 Q_STATIC_TEMPLATE_FUNCTION
350 inline void qt_memrotate270_tiled_unpacked(const T *src, int w, int h, int sstride, T *dest,
351                                            int dstride)
352 {
353     const int numTilesX = (w + tileSize - 1) / tileSize;
354     const int numTilesY = (h + tileSize - 1) / tileSize;
355
356     for (int tx = 0; tx < numTilesX; ++tx) {
357         const int startx = tx * tileSize;
358         const int stopx = qMin(startx + tileSize, w);
359
360         for (int ty = 0; ty < numTilesY; ++ty) {
361             const int starty = h - 1 - ty * tileSize;
362             const int stopy = qMax(starty - tileSize, 0);
363
364             for (int x = startx; x < stopx; ++x) {
365                 T *d = (T*)((char*)dest + x * dstride) + h - 1 - starty;
366                 const char *s = (const char*)(src + x) + starty * sstride;
367                 for (int y = starty; y >= stopy; --y) {
368                     *d++ = *(const T*)s;
369                     s -= sstride;
370                 }
371             }
372         }
373     }
374 }
375
376 #endif // QT_ROTATION_ALGORITHM
377
378 template <class T>
379 Q_STATIC_TEMPLATE_FUNCTION
380 inline void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, int srcStride,
381                                     T *dest, int dstStride)
382 {
383 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
384     qt_memrotate90_cachedRead<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
385 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
386     qt_memrotate90_cachedWrite<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
387 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
388     qt_memrotate90_packing<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
389 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
390     qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
391 #endif
392 }
393
394 template <class T>
395 Q_STATIC_TEMPLATE_FUNCTION
396 inline void qt_memrotate180_template(const T *src, int w, int h, int sstride, T *dest, int dstride)
397 {
398     const char *s = (const char*)(src) + (h - 1) * sstride;
399     for (int y = h - 1; y >= 0; --y) {
400         T *d = reinterpret_cast<T*>((char *)(dest) + (h - y - 1) * dstride);
401         src = reinterpret_cast<const T*>(s);
402         for (int x = w - 1; x >= 0; --x) {
403             d[w - x - 1] = src[x];
404         }
405         s -= sstride;
406     }
407 }
408
409 template <class T>
410 Q_STATIC_TEMPLATE_FUNCTION
411 inline void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight, int srcStride,
412                                      T *dest, int dstStride)
413 {
414 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
415     qt_memrotate270_cachedRead<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
416 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
417     qt_memrotate270_cachedWrite<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
418 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
419     qt_memrotate270_packing<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
420 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
421     qt_memrotate270_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
422 #endif
423 }
424
425 template <>
426 inline void qt_memrotate90_template<quint24>(const quint24 *src, int srcWidth, int srcHeight,
427                                              int srcStride, quint24 *dest, int dstStride)
428 {
429 #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
430     qt_memrotate90_cachedRead<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
431 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
432     qt_memrotate90_cachedWrite<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
433 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
434     // packed algorithm not implemented
435     qt_memrotate90_cachedRead<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
436 #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
437     // packed algorithm not implemented
438     qt_memrotate90_tiled_unpacked<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
439 #endif
440 }
441
442 #define QT_IMPL_MEMROTATE(type)                                     \
443 Q_GUI_EXPORT void qt_memrotate90(const type *src, int w, int h, int sstride, \
444                                  type *dest, int dstride)           \
445 {                                                                   \
446     qt_memrotate90_template(src, w, h, sstride, dest, dstride);     \
447 }                                                                   \
448 Q_GUI_EXPORT void qt_memrotate180(const type *src, int w, int h, int sstride, \
449                                   type *dest, int dstride)          \
450 {                                                                   \
451     qt_memrotate180_template(src, w, h, sstride, dest, dstride);    \
452 }                                                                   \
453 Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
454                                   type *dest, int dstride)          \
455 {                                                                   \
456     qt_memrotate270_template(src, w, h, sstride, dest, dstride);    \
457 }
458
459 #define QT_IMPL_SIMPLE_MEMROTATE(type)                              \
460 Q_GUI_EXPORT void qt_memrotate90(const type *src, int w, int h, int sstride,  \
461                                  type *dest, int dstride)           \
462 {                                                                   \
463     qt_memrotate90_tiled_unpacked<type>(src, w, h, sstride, dest, dstride); \
464 }                                                                   \
465 Q_GUI_EXPORT void qt_memrotate180(const type *src, int w, int h, int sstride, \
466                                   type *dest, int dstride)          \
467 {                                                                   \
468     qt_memrotate180_template(src, w, h, sstride, dest, dstride);    \
469 }                                                                   \
470 Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
471                                   type *dest, int dstride)          \
472 {                                                                   \
473     qt_memrotate270_tiled_unpacked<type>(src, w, h, sstride, dest, dstride); \
474 }
475
476
477
478
479 QT_IMPL_MEMROTATE(quint32)
480 QT_IMPL_MEMROTATE(quint16)
481 QT_IMPL_MEMROTATE(quint24)
482 QT_IMPL_MEMROTATE(quint8)
483
484 void qt_memrotate90_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
485 {
486     qt_memrotate90((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
487 }
488
489 void qt_memrotate180_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
490 {
491     qt_memrotate180((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
492 }
493
494 void qt_memrotate270_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
495 {
496     qt_memrotate270((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
497 }
498
499 void qt_memrotate90_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
500 {
501     qt_memrotate90((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
502 }
503
504 void qt_memrotate180_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
505 {
506     qt_memrotate180((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
507 }
508
509 void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
510 {
511     qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
512 }
513
514 MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] =
515 // 90, 180, 270
516 {
517     { 0, 0, 0 },      // Format_Invalid,
518     { 0, 0, 0 },      // Format_Mono,
519     { 0, 0, 0 },      // Format_MonoLSB,
520     { 0, 0, 0 },      // Format_Indexed8,
521     { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_RGB32,
522     { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_ARGB32,
523     { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_ARGB32_Premultiplied,
524     { qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 },      // Format_RGB16,
525     { 0, 0, 0 },      // Format_ARGB8565_Premultiplied,
526     { 0, 0, 0 },      // Format_RGB666,
527     { 0, 0, 0 },      // Format_ARGB6666_Premultiplied,
528     { 0, 0, 0 },      // Format_RGB555,
529     { 0, 0, 0 },      // Format_ARGB8555_Premultiplied,
530     { 0, 0, 0 },      // Format_RGB888,
531     { 0, 0, 0 },      // Format_RGB444,
532     { 0, 0, 0 }       // Format_ARGB4444_Premultiplied,
533 };
534
535 QT_END_NAMESPACE