Rename QPaintDevice::init() to initPainter()
[profile/ivi/qtbase.git] / src / gui / painting / qdrawhelper_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QDRAWHELPER_P_H
43 #define QDRAWHELPER_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "QtCore/qglobal.h"
57 #include "QtGui/qcolor.h"
58 #include "QtGui/qpainter.h"
59 #include "QtGui/qimage.h"
60 #ifndef QT_FT_BEGIN_HEADER
61 #define QT_FT_BEGIN_HEADER
62 #define QT_FT_END_HEADER
63 #endif
64 #include "private/qrasterdefs_p.h"
65 #include <private/qsimd_p.h>
66 #include <private/qmath_p.h>
67
68 QT_BEGIN_NAMESPACE
69
70 #if defined(Q_CC_RVCT)
71 // RVCT doesn't like static template functions
72 #  define Q_STATIC_TEMPLATE_FUNCTION
73 #  define Q_STATIC_INLINE_FUNCTION static __forceinline
74 #  define Q_DECL_RESTRICT
75 #elif defined(Q_CC_GNU)
76 #  define Q_STATIC_TEMPLATE_FUNCTION static __attribute__((always_inline))
77 #  define Q_STATIC_INLINE_FUNCTION static inline __attribute__((always_inline))
78 #  define Q_DECL_RESTRICT __restrict__
79 #else
80 #  define Q_STATIC_TEMPLATE_FUNCTION static
81 #  define Q_STATIC_INLINE_FUNCTION static inline
82 #  define Q_DECL_RESTRICT
83 #endif
84
85 static const uint AMASK = 0xff000000;
86 static const uint RMASK = 0x00ff0000;
87 static const uint GMASK = 0x0000ff00;
88 static const uint BMASK = 0x000000ff;
89
90 /*******************************************************************************
91  * QSpan
92  *
93  * duplicate definition of FT_Span
94  */
95 typedef QT_FT_Span QSpan;
96
97 struct QSolidData;
98 struct QTextureData;
99 struct QGradientData;
100 struct QLinearGradientData;
101 struct QRadialGradientData;
102 struct QConicalGradientData;
103 struct QSpanData;
104 class QGradient;
105 class QRasterBuffer;
106 class QClipData;
107 class QRasterPaintEngineState;
108
109 typedef QT_FT_SpanFunc ProcessSpans;
110 typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer,
111                                int x, int y, quint32 color,
112                                const uchar *bitmap,
113                                int mapWidth, int mapHeight, int mapStride);
114
115 typedef void (*AlphamapBlitFunc)(QRasterBuffer *rasterBuffer,
116                                  int x, int y, quint32 color,
117                                  const uchar *bitmap,
118                                  int mapWidth, int mapHeight, int mapStride,
119                                  const QClipData *clip);
120
121 typedef void (*AlphaRGBBlitFunc)(QRasterBuffer *rasterBuffer,
122                                  int x, int y, quint32 color,
123                                  const uint *rgbmask,
124                                  int mapWidth, int mapHeight, int mapStride,
125                                  const QClipData *clip);
126
127 typedef void (*RectFillFunc)(QRasterBuffer *rasterBuffer,
128                              int x, int y, int width, int height,
129                              quint32 color);
130
131 typedef void (*SrcOverBlendFunc)(uchar *destPixels, int dbpl,
132                                  const uchar *src, int spbl,
133                                  int w, int h,
134                                  int const_alpha);
135
136 typedef void (*SrcOverScaleFunc)(uchar *destPixels, int dbpl,
137                                  const uchar *src, int spbl,
138                                  const QRectF &targetRect,
139                                  const QRectF &sourceRect,
140                                  const QRect &clipRect,
141                                  int const_alpha);
142
143 typedef void (*SrcOverTransformFunc)(uchar *destPixels, int dbpl,
144                                      const uchar *src, int spbl,
145                                      const QRectF &targetRect,
146                                      const QRectF &sourceRect,
147                                      const QRect &clipRect,
148                                      const QTransform &targetRectTransform,
149                                      int const_alpha);
150
151 typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
152
153 struct DrawHelper {
154     ProcessSpans blendColor;
155     ProcessSpans blendGradient;
156     BitmapBlitFunc bitmapBlit;
157     AlphamapBlitFunc alphamapBlit;
158     AlphaRGBBlitFunc alphaRGBBlit;
159     RectFillFunc fillRect;
160 };
161
162 extern SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats];
163 extern SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats];
164 extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats];
165 extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3];
166
167 extern DrawHelper qDrawHelper[QImage::NImageFormats];
168
169 void qBlendTexture(int count, const QSpan *spans, void *userData);
170
171 typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha);
172 typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha);
173
174 struct LinearGradientValues
175 {
176     qreal dx;
177     qreal dy;
178     qreal l;
179     qreal off;
180 };
181
182 struct RadialGradientValues
183 {
184     qreal dx;
185     qreal dy;
186     qreal dr;
187     qreal sqrfr;
188     qreal a;
189     qreal inv2a;
190     bool extended;
191 };
192
193 struct Operator;
194 typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
195 typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length);
196 typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
197
198 struct Operator
199 {
200     QPainter::CompositionMode mode;
201     DestFetchProc dest_fetch;
202     DestStoreProc dest_store;
203     SourceFetchProc src_fetch;
204     CompositionFunctionSolid funcSolid;
205     CompositionFunction func;
206     union {
207         LinearGradientValues linear;
208         RadialGradientValues radial;
209     };
210 };
211
212 void qInitDrawhelperAsm();
213
214 class QRasterPaintEngine;
215
216 struct QSolidData
217 {
218     uint color;
219 };
220
221 struct QLinearGradientData
222 {
223     struct {
224         qreal x;
225         qreal y;
226     } origin;
227     struct {
228         qreal x;
229         qreal y;
230     } end;
231 };
232
233 struct QRadialGradientData
234 {
235     struct {
236         qreal x;
237         qreal y;
238         qreal radius;
239     } center;
240     struct {
241         qreal x;
242         qreal y;
243         qreal radius;
244     } focal;
245 };
246
247 struct QConicalGradientData
248 {
249     struct {
250         qreal x;
251         qreal y;
252     } center;
253     qreal angle;
254 };
255
256 struct QGradientData
257 {
258     QGradient::Spread spread;
259
260     union {
261         QLinearGradientData linear;
262         QRadialGradientData radial;
263         QConicalGradientData conical;
264     };
265
266 #define GRADIENT_STOPTABLE_SIZE 1024
267 #define GRADIENT_STOPTABLE_SIZE_SHIFT 10
268
269     uint* colorTable; //[GRADIENT_STOPTABLE_SIZE];
270
271     uint alphaColor : 1;
272 };
273
274 struct QTextureData
275 {
276     const uchar *imageData;
277     const uchar *scanLine(int y) const { return imageData + y*bytesPerLine; }
278
279     int width;
280     int height;
281     // clip rect
282     int x1;
283     int y1;
284     int x2;
285     int y2;
286     int bytesPerLine;
287     QImage::Format format;
288     const QVector<QRgb> *colorTable;
289     bool hasAlpha;
290     enum Type {
291         Plain,
292         Tiled
293     };
294     Type type;
295     int const_alpha;
296 };
297
298 struct QSpanData
299 {
300     QSpanData() : tempImage(0) {}
301     ~QSpanData() { delete tempImage; }
302
303     QRasterBuffer *rasterBuffer;
304     ProcessSpans blend;
305     ProcessSpans unclipped_blend;
306     BitmapBlitFunc bitmapBlit;
307     AlphamapBlitFunc alphamapBlit;
308     AlphaRGBBlitFunc alphaRGBBlit;
309     RectFillFunc fillRect;
310     qreal m11, m12, m13, m21, m22, m23, m33, dx, dy;   // inverse xform matrix
311     const QClipData *clip;
312     enum Type {
313         None,
314         Solid,
315         LinearGradient,
316         RadialGradient,
317         ConicalGradient,
318         Texture
319     } type : 8;
320     int txop : 8;
321     int fast_matrix : 1;
322     bool bilinear;
323     QImage *tempImage;
324     union {
325         QSolidData solid;
326         QGradientData gradient;
327         QTextureData texture;
328     };
329
330     void init(QRasterBuffer *rb, const QRasterPaintEngine *pe);
331     void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode);
332     void setupMatrix(const QTransform &matrix, int bilinear);
333     void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect());
334     void adjustSpanMethods();
335 };
336
337 struct QDrawHelperGammaTables
338 {
339     explicit QDrawHelperGammaTables(qreal smoothing);
340
341     void refresh(qreal smoothing);
342
343     uchar qt_pow_rgb_gamma[256];
344     uchar qt_pow_rgb_invgamma[256];
345     uint qt_pow_gamma[256];
346     uchar qt_pow_invgamma[2048];
347 };
348
349 static inline uint qt_gradient_clamp(const QGradientData *data, int ipos)
350 {
351     if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
352         if (data->spread == QGradient::RepeatSpread) {
353             ipos = ipos % GRADIENT_STOPTABLE_SIZE;
354             ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
355         } else if (data->spread == QGradient::ReflectSpread) {
356             const int limit = GRADIENT_STOPTABLE_SIZE * 2;
357             ipos = ipos % limit;
358             ipos = ipos < 0 ? limit + ipos : ipos;
359             ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - 1 - ipos : ipos;
360         } else {
361             if (ipos < 0)
362                 ipos = 0;
363             else if (ipos >= GRADIENT_STOPTABLE_SIZE)
364                 ipos = GRADIENT_STOPTABLE_SIZE-1;
365         }
366     }
367
368     Q_ASSERT(ipos >= 0);
369     Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
370
371     return ipos;
372 }
373
374 static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos)
375 {
376     int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5));
377     return data->colorTable[qt_gradient_clamp(data, ipos)];
378 }
379
380 static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c)
381 {
382     return (b * b) - (4 * a * c);
383 }
384
385 template <class RadialFetchFunc>
386 const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const Operator *op, const QSpanData *data,
387                                                            int y, int x, int length)
388 {
389     // avoid division by zero
390     if (qFuzzyIsNull(op->radial.a)) {
391         extern void (*qt_memfill32)(quint32 *dest, quint32 value, int count);
392         qt_memfill32(buffer, 0, length);
393         return buffer;
394     }
395
396     const uint *b = buffer;
397     qreal rx = data->m21 * (y + qreal(0.5))
398                + data->dx + data->m11 * (x + qreal(0.5));
399     qreal ry = data->m22 * (y + qreal(0.5))
400                + data->dy + data->m12 * (x + qreal(0.5));
401     bool affine = !data->m13 && !data->m23;
402
403     uint *end = buffer + length;
404     if (affine) {
405         rx -= data->gradient.radial.focal.x;
406         ry -= data->gradient.radial.focal.y;
407
408         qreal inv_a = 1 / qreal(2 * op->radial.a);
409
410         const qreal delta_rx = data->m11;
411         const qreal delta_ry = data->m12;
412
413         qreal b = 2*(op->radial.dr*data->gradient.radial.focal.radius + rx * op->radial.dx + ry * op->radial.dy);
414         qreal delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy);
415         const qreal b_delta_b = 2 * b * delta_b;
416         const qreal delta_b_delta_b = 2 * delta_b * delta_b;
417
418         const qreal bb = b * b;
419         const qreal delta_bb = delta_b * delta_b;
420
421         b *= inv_a;
422         delta_b *= inv_a;
423
424         const qreal rxrxryry = rx * rx + ry * ry;
425         const qreal delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
426         const qreal rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
427         const qreal delta_rx_plus_ry = 2 * delta_rxrxryry;
428
429         inv_a *= inv_a;
430
431         qreal det = (bb - 4 * op->radial.a * (op->radial.sqrfr - rxrxryry)) * inv_a;
432         qreal delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
433         const qreal delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a;
434
435         RadialFetchFunc::fetch(buffer, end, op, data, det, delta_det, delta_delta_det, b, delta_b);
436     } else {
437         qreal rw = data->m23 * (y + qreal(0.5))
438                    + data->m33 + data->m13 * (x + qreal(0.5));
439
440         while (buffer < end) {
441             if (rw == 0) {
442                 *buffer = 0;
443             } else {
444                 qreal invRw = 1 / rw;
445                 qreal gx = rx * invRw - data->gradient.radial.focal.x;
446                 qreal gy = ry * invRw - data->gradient.radial.focal.y;
447                 qreal b  = 2*(op->radial.dr*data->gradient.radial.focal.radius + gx*op->radial.dx + gy*op->radial.dy);
448                 qreal det = qRadialDeterminant(op->radial.a, b, op->radial.sqrfr - (gx*gx + gy*gy));
449
450                 quint32 result = 0;
451                 if (det >= 0) {
452                     qreal detSqrt = qSqrt(det);
453
454                     qreal s0 = (-b - detSqrt) * op->radial.inv2a;
455                     qreal s1 = (-b + detSqrt) * op->radial.inv2a;
456
457                     qreal s = qMax(s0, s1);
458
459                     if (data->gradient.radial.focal.radius + op->radial.dr * s >= 0)
460                         result = qt_gradient_pixel(&data->gradient, s);
461                 }
462
463                 *buffer = result;
464             }
465
466             rx += data->m11;
467             ry += data->m12;
468             rw += data->m13;
469
470             ++buffer;
471         }
472     }
473
474     return b;
475 }
476
477 template <class Simd>
478 class QRadialFetchSimd
479 {
480 public:
481     static void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det,
482                       qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
483     {
484         typename Simd::Vect_buffer_f det_vec;
485         typename Simd::Vect_buffer_f delta_det4_vec;
486         typename Simd::Vect_buffer_f b_vec;
487
488         for (int i = 0; i < 4; ++i) {
489             det_vec.f[i] = det;
490             delta_det4_vec.f[i] = 4 * delta_det;
491             b_vec.f[i] = b;
492
493             det += delta_det;
494             delta_det += delta_delta_det;
495             b += delta_b;
496         }
497
498         const typename Simd::Float32x4 v_delta_delta_det16 = Simd::v_dup(16 * delta_delta_det);
499         const typename Simd::Float32x4 v_delta_delta_det6 = Simd::v_dup(6 * delta_delta_det);
500         const typename Simd::Float32x4 v_delta_b4 = Simd::v_dup(4 * delta_b);
501
502         const typename Simd::Float32x4 v_r0 = Simd::v_dup(data->gradient.radial.focal.radius);
503         const typename Simd::Float32x4 v_dr = Simd::v_dup(op->radial.dr);
504
505         const typename Simd::Float32x4 v_min = Simd::v_dup(0.0f);
506         const typename Simd::Float32x4 v_max = Simd::v_dup(float(GRADIENT_STOPTABLE_SIZE-1));
507         const typename Simd::Float32x4 v_half = Simd::v_dup(0.5f);
508
509         const typename Simd::Int32x4 v_repeat_mask = Simd::v_dup(~(uint(0xffffff) << GRADIENT_STOPTABLE_SIZE_SHIFT));
510         const typename Simd::Int32x4 v_reflect_mask = Simd::v_dup(~(uint(0xffffff) << (GRADIENT_STOPTABLE_SIZE_SHIFT+1)));
511
512         const typename Simd::Int32x4 v_reflect_limit = Simd::v_dup(2 * GRADIENT_STOPTABLE_SIZE - 1);
513
514         const int extended_mask = op->radial.extended ? 0x0 : ~0x0;
515
516 #define FETCH_RADIAL_LOOP_PROLOGUE \
517         while (buffer < end) { \
518             typename Simd::Vect_buffer_i v_buffer_mask; \
519             v_buffer_mask.v = Simd::v_greaterOrEqual(det_vec.v, v_min); \
520             const typename Simd::Float32x4 v_index_local = Simd::v_sub(Simd::v_sqrt(Simd::v_max(v_min, det_vec.v)), b_vec.v); \
521             const typename Simd::Float32x4 v_index = Simd::v_add(Simd::v_mul(v_index_local, v_max), v_half); \
522             v_buffer_mask.v = Simd::v_and(v_buffer_mask.v, Simd::v_greaterOrEqual(Simd::v_add(v_r0, Simd::v_mul(v_dr, v_index_local)), v_min)); \
523             typename Simd::Vect_buffer_i index_vec;
524 #define FETCH_RADIAL_LOOP_CLAMP_REPEAT \
525             index_vec.v = Simd::v_and(v_repeat_mask, Simd::v_toInt(v_index));
526 #define FETCH_RADIAL_LOOP_CLAMP_REFLECT \
527             const typename Simd::Int32x4 v_index_i = Simd::v_and(v_reflect_mask, Simd::v_toInt(v_index)); \
528             const typename Simd::Int32x4 v_index_i_inv = Simd::v_sub(v_reflect_limit, v_index_i); \
529             index_vec.v = Simd::v_min_16(v_index_i, v_index_i_inv);
530 #define FETCH_RADIAL_LOOP_CLAMP_PAD \
531             index_vec.v = Simd::v_toInt(Simd::v_min(v_max, Simd::v_max(v_min, v_index)));
532 #define FETCH_RADIAL_LOOP_EPILOGUE \
533             det_vec.v = Simd::v_add(Simd::v_add(det_vec.v, delta_det4_vec.v), v_delta_delta_det6); \
534             delta_det4_vec.v = Simd::v_add(delta_det4_vec.v, v_delta_delta_det16); \
535             b_vec.v = Simd::v_add(b_vec.v, v_delta_b4); \
536             for (int i = 0; i < 4; ++i) \
537                 *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]]; \
538         }
539
540 #define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \
541         FETCH_RADIAL_LOOP_PROLOGUE \
542         FETCH_RADIAL_LOOP_CLAMP \
543         FETCH_RADIAL_LOOP_EPILOGUE
544
545         switch (data->gradient.spread) {
546         case QGradient::RepeatSpread:
547             FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REPEAT)
548             break;
549         case QGradient::ReflectSpread:
550             FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REFLECT)
551             break;
552         case QGradient::PadSpread:
553             FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_PAD)
554             break;
555         default:
556             Q_ASSERT(false);
557         }
558     }
559 };
560
561 #if defined(Q_CC_RVCT)
562 #  pragma push
563 #  pragma arm
564 #endif
565 Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
566     uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
567     t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
568     t &= 0xff00ff;
569
570     x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
571     x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
572     x &= 0xff00ff00;
573     x |= t;
574     return x;
575 }
576 #if defined(Q_CC_RVCT)
577 #  pragma pop
578 #endif
579
580 #if QT_POINTER_SIZE == 8 // 64-bit versions
581
582 Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
583     quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
584     t += (((quint64(y)) | ((quint64(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
585     t >>= 8;
586     t &= 0x00ff00ff00ff00ff;
587     return (uint(t)) | (uint(t >> 24));
588 }
589
590 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
591     quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
592     t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
593     t &= 0x00ff00ff00ff00ff;
594     return (uint(t)) | (uint(t >> 24));
595 }
596
597 Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
598     uint a = x >> 24;
599     quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
600     t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
601     t &= 0x000000ff00ff00ff;
602     return (uint(t)) | (uint(t >> 24)) | (a << 24);
603 }
604
605 #else // 32-bit versions
606
607 Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
608     uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
609     t >>= 8;
610     t &= 0xff00ff;
611
612     x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
613     x &= 0xff00ff00;
614     x |= t;
615     return x;
616 }
617
618 #if defined(Q_CC_RVCT)
619 #  pragma push
620 #  pragma arm
621 #endif
622 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
623     uint t = (x & 0xff00ff) * a;
624     t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
625     t &= 0xff00ff;
626
627     x = ((x >> 8) & 0xff00ff) * a;
628     x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
629     x &= 0xff00ff00;
630     x |= t;
631     return x;
632 }
633 #if defined(Q_CC_RVCT)
634 #  pragma pop
635 #endif
636
637 Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
638     uint a = x >> 24;
639     uint t = (x & 0xff00ff) * a;
640     t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
641     t &= 0xff00ff;
642
643     x = ((x >> 8) & 0xff) * a;
644     x = (x + ((x >> 8) & 0xff) + 0x80);
645     x &= 0xff00;
646     x |= t | (a << 24);
647     return x;
648 }
649 #endif
650
651
652 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) {
653     a += 1;
654     uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
655     t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f;
656     return t;
657 }
658
659 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) {
660     uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0;
661     t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f;
662     return t;
663 }
664
665 #define INV_PREMUL(p)                                   \
666     (qAlpha(p) == 0 ? 0 :                               \
667     ((qAlpha(p) << 24)                                  \
668      | (((255*qRed(p))/ qAlpha(p)) << 16)               \
669      | (((255*qGreen(p)) / qAlpha(p))  << 8)            \
670      | ((255*qBlue(p)) / qAlpha(p))))
671
672 struct quint24 {
673     quint24(uint value);
674     operator uint() const;
675     uchar data[3];
676 } Q_PACKED;
677
678 inline quint24::quint24(uint value)
679 {
680     data[0] = uchar(value >> 16);
681     data[1] = uchar(value >> 8);
682     data[2] = uchar(value);
683 }
684
685 inline quint24::operator uint() const
686 {
687     return data[2] | (data[1] << 8) | (data[0] << 16);
688 }
689
690 template <class T>
691 void qt_memfill(T *dest, T value, int count);
692
693 template<> inline void qt_memfill(quint32 *dest, quint32 color, int count)
694 {
695     extern void (*qt_memfill32)(quint32 *dest, quint32 value, int count);
696     qt_memfill32(dest, color, count);
697 }
698
699 template<> inline void qt_memfill(quint16 *dest, quint16 color, int count)
700 {
701     extern void (*qt_memfill16)(quint16 *dest, quint16 value, int count);
702     qt_memfill16(dest, color, count);
703 }
704
705 template<> inline void qt_memfill(quint8 *dest, quint8 color, int count)
706 {
707     memset(dest, color, count);
708 }
709
710 template <class T>
711 inline void qt_memfill(T *dest, T value, int count)
712 {
713     if (!count)
714         return;
715
716     int n = (count + 7) / 8;
717     switch (count & 0x07)
718     {
719     case 0: do { *dest++ = value;
720     case 7:      *dest++ = value;
721     case 6:      *dest++ = value;
722     case 5:      *dest++ = value;
723     case 4:      *dest++ = value;
724     case 3:      *dest++ = value;
725     case 2:      *dest++ = value;
726     case 1:      *dest++ = value;
727     } while (--n > 0);
728     }
729 }
730
731 template <class T>
732 inline void qt_rectfill(T *dest, T value,
733                         int x, int y, int width, int height, int stride)
734 {
735     char *d = reinterpret_cast<char*>(dest + x) + y * stride;
736     if (uint(stride) == (width * sizeof(T))) {
737         qt_memfill(reinterpret_cast<T*>(d), value, width * height);
738     } else {
739         for (int j = 0; j < height; ++j) {
740             dest = reinterpret_cast<T*>(d);
741             qt_memfill(dest, value, width);
742             d += stride;
743         }
744     }
745 }
746
747 #define QT_MEMFILL_UINT(dest, length, color)            \
748     qt_memfill<quint32>(dest, color, length);
749
750 #define QT_MEMFILL_USHORT(dest, length, color) \
751     qt_memfill<quint16>(dest, color, length);
752
753 #define QT_MEMCPY_REV_UINT(dest, src, length) \
754 do {                                          \
755     /* Duff's device */                       \
756     uint *_d = (uint*)(dest) + length;         \
757     const uint *_s = (uint*)(src) + length;    \
758     register int n = ((length) + 7) / 8;      \
759     switch ((length) & 0x07)                  \
760     {                                         \
761     case 0: do { *--_d = *--_s;                 \
762     case 7:      *--_d = *--_s;                 \
763     case 6:      *--_d = *--_s;                 \
764     case 5:      *--_d = *--_s;                 \
765     case 4:      *--_d = *--_s;                 \
766     case 3:      *--_d = *--_s;                 \
767     case 2:      *--_d = *--_s;                 \
768     case 1:      *--_d = *--_s;                 \
769     } while (--n > 0);                        \
770     }                                         \
771 } while (0)
772
773 #define QT_MEMCPY_USHORT(dest, src, length) \
774 do {                                          \
775     /* Duff's device */                       \
776     ushort *_d = (ushort*)(dest);         \
777     const ushort *_s = (ushort*)(src);    \
778     register int n = ((length) + 7) / 8;      \
779     switch ((length) & 0x07)                  \
780     {                                         \
781     case 0: do { *_d++ = *_s++;                 \
782     case 7:      *_d++ = *_s++;                 \
783     case 6:      *_d++ = *_s++;                 \
784     case 5:      *_d++ = *_s++;                 \
785     case 4:      *_d++ = *_s++;                 \
786     case 3:      *_d++ = *_s++;                 \
787     case 2:      *_d++ = *_s++;                 \
788     case 1:      *_d++ = *_s++;                 \
789     } while (--n > 0);                        \
790     }                                         \
791 } while (0)
792
793 #if defined(Q_CC_RVCT)
794 #  pragma push
795 #  pragma arm
796 #endif
797 Q_STATIC_INLINE_FUNCTION int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
798 #if defined(Q_CC_RVCT)
799 #  pragma pop
800 #endif
801
802 inline ushort qConvertRgb32To16(uint c)
803 {
804    return (((c) >> 3) & 0x001f)
805        | (((c) >> 5) & 0x07e0)
806        | (((c) >> 8) & 0xf800);
807 }
808
809 inline QRgb qConvertRgb16To32(uint c)
810 {
811     return 0xff000000
812         | ((((c) << 3) & 0xf8) | (((c) >> 2) & 0x7))
813         | ((((c) << 5) & 0xfc00) | (((c) >> 1) & 0x300))
814         | ((((c) << 8) & 0xf80000) | (((c) << 3) & 0x70000));
815 }
816
817 inline int qRed565(quint16 rgb) {
818     const int r = (rgb & 0xf800);
819     return (r >> 8) | (r >> 13);
820 }
821
822 inline int qGreen565(quint16 rgb) {
823     const int g = (rgb & 0x07e0);
824     return (g >> 3) | (g >> 9);
825 }
826
827 inline int qBlue565(quint16 rgb) {
828     const int b = (rgb & 0x001f);
829     return (b << 3) | (b >> 2);
830 }
831
832 const uint qt_bayer_matrix[16][16] = {
833     { 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc,
834       0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff},
835     { 0x80, 0x40, 0xb0, 0x70, 0x8c, 0x4c, 0xbc, 0x7c,
836       0x83, 0x43, 0xb3, 0x73, 0x8f, 0x4f, 0xbf, 0x7f},
837     { 0x20, 0xe0, 0x10, 0xd0, 0x2c, 0xec, 0x1c, 0xdc,
838       0x23, 0xe3, 0x13, 0xd3, 0x2f, 0xef, 0x1f, 0xdf},
839     { 0xa0, 0x60, 0x90, 0x50, 0xac, 0x6c, 0x9c, 0x5c,
840       0xa3, 0x63, 0x93, 0x53, 0xaf, 0x6f, 0x9f, 0x5f},
841     { 0x8, 0xc8, 0x38, 0xf8, 0x4, 0xc4, 0x34, 0xf4,
842       0xb, 0xcb, 0x3b, 0xfb, 0x7, 0xc7, 0x37, 0xf7},
843     { 0x88, 0x48, 0xb8, 0x78, 0x84, 0x44, 0xb4, 0x74,
844       0x8b, 0x4b, 0xbb, 0x7b, 0x87, 0x47, 0xb7, 0x77},
845     { 0x28, 0xe8, 0x18, 0xd8, 0x24, 0xe4, 0x14, 0xd4,
846       0x2b, 0xeb, 0x1b, 0xdb, 0x27, 0xe7, 0x17, 0xd7},
847     { 0xa8, 0x68, 0x98, 0x58, 0xa4, 0x64, 0x94, 0x54,
848       0xab, 0x6b, 0x9b, 0x5b, 0xa7, 0x67, 0x97, 0x57},
849     { 0x2, 0xc2, 0x32, 0xf2, 0xe, 0xce, 0x3e, 0xfe,
850       0x1, 0xc1, 0x31, 0xf1, 0xd, 0xcd, 0x3d, 0xfd},
851     { 0x82, 0x42, 0xb2, 0x72, 0x8e, 0x4e, 0xbe, 0x7e,
852       0x81, 0x41, 0xb1, 0x71, 0x8d, 0x4d, 0xbd, 0x7d},
853     { 0x22, 0xe2, 0x12, 0xd2, 0x2e, 0xee, 0x1e, 0xde,
854       0x21, 0xe1, 0x11, 0xd1, 0x2d, 0xed, 0x1d, 0xdd},
855     { 0xa2, 0x62, 0x92, 0x52, 0xae, 0x6e, 0x9e, 0x5e,
856       0xa1, 0x61, 0x91, 0x51, 0xad, 0x6d, 0x9d, 0x5d},
857     { 0xa, 0xca, 0x3a, 0xfa, 0x6, 0xc6, 0x36, 0xf6,
858       0x9, 0xc9, 0x39, 0xf9, 0x5, 0xc5, 0x35, 0xf5},
859     { 0x8a, 0x4a, 0xba, 0x7a, 0x86, 0x46, 0xb6, 0x76,
860       0x89, 0x49, 0xb9, 0x79, 0x85, 0x45, 0xb5, 0x75},
861     { 0x2a, 0xea, 0x1a, 0xda, 0x26, 0xe6, 0x16, 0xd6,
862       0x29, 0xe9, 0x19, 0xd9, 0x25, 0xe5, 0x15, 0xd5},
863     { 0xaa, 0x6a, 0x9a, 0x5a, 0xa6, 0x66, 0x96, 0x56,
864       0xa9, 0x69, 0x99, 0x59, 0xa5, 0x65, 0x95, 0x55}
865 };
866
867 #define ARGB_COMBINE_ALPHA(argb, alpha) \
868     ((((argb >> 24) * alpha) >> 8) << 24) | (argb & 0x00ffffff)
869
870
871 #if QT_POINTER_SIZE == 8 // 64-bit versions
872 #define AMIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
873 #define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
874 #else // 32 bits
875 // The mask for alpha can overflow over 32 bits
876 #define AMIX(mask) quint32(qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
877 #define MIX(mask) (qMin(((quint32(s)&mask) + (quint32(d)&mask)), quint32(mask)))
878 #endif
879
880 inline int comp_func_Plus_one_pixel_const_alpha(uint d, const uint s, const uint const_alpha, const uint one_minus_const_alpha)
881 {
882     const int result = (AMIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
883     return INTERPOLATE_PIXEL_255(result, const_alpha, d, one_minus_const_alpha);
884 }
885
886 inline int comp_func_Plus_one_pixel(uint d, const uint s)
887 {
888     const int result = (AMIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
889     return result;
890 }
891
892 #undef MIX
893 #undef AMIX
894
895 // prototypes of all the composition functions
896 void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha);
897 void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha);
898 void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha);
899 void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha);
900 void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint);
901 void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha);
902 void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha);
903 void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha);
904 void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha);
905 void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha);
906 void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha);
907 void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha);
908 void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha);
909 void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha);
910 void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha);
911 void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha);
912 void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha);
913 void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha);
914 void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha);
915 void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha);
916 void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha);
917 void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha);
918 void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha);
919 void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha);
920 void QT_FASTCALL rasterop_SourceOrDestination(uint *dest, const uint *src, int length, uint const_alpha);
921 void QT_FASTCALL rasterop_SourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha);
922 void QT_FASTCALL rasterop_SourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha);
923 void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
924 void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
925 void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha);
926 void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src, int length, uint const_alpha);
927 void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha);
928 void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
929
930 // prototypes of all the solid composition functions
931 void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha);
932 void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha);
933 void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint color, uint const_alpha);
934 void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha);
935 void QT_FASTCALL comp_func_solid_Destination(uint *dest, int length, uint color, uint const_alpha);
936 void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha);
937 void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha);
938 void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha);
939 void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha);
940 void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha);
941 void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha);
942 void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha);
943 void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha);
944 void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha);
945 void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha);
946 void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha);
947 void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha);
948 void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha);
949 void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha);
950 void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha);
951 void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha);
952 void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha);
953 void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha);
954 void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha);
955 void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, int length, uint color, uint const_alpha);
956 void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, int length, uint color, uint const_alpha);
957 void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, int length, uint color, uint const_alpha);
958 void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha);
959 void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, int length, uint color, uint const_alpha);
960 void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, int length, uint color, uint const_alpha);
961 void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, uint color, uint const_alpha);
962 void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, int length, uint color, uint const_alpha);
963 void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha);
964
965
966 struct QPixelLayout;
967 typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count,
968                                                const QPixelLayout *layout, const QRgb *clut);
969
970 struct QPixelLayout
971 {
972     // Bits per pixel
973     enum BPP {
974         BPPNone,
975         BPP1MSB,
976         BPP1LSB,
977         BPP8,
978         BPP16,
979         BPP24,
980         BPP32,
981         BPPCount
982     };
983
984     // All numbers in bits.
985     uchar redWidth;
986     uchar redShift;
987     uchar greenWidth;
988     uchar greenShift;
989     uchar blueWidth;
990     uchar blueShift;
991     uchar alphaWidth;
992     uchar alphaShift;
993     bool premultiplied;
994     BPP bpp;
995     ConvertFunc convertToARGB32PM;
996     ConvertFunc convertFromARGB32PM;
997 };
998
999 template <QPixelLayout::BPP bpp>
1000 uint QT_FASTCALL fetchPixel(const uchar *src, int index);
1001
1002 template <>
1003 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
1004 {
1005     return (src[index >> 3] >> (index & 7)) & 1;
1006 }
1007
1008 template <>
1009 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
1010 {
1011     return (src[index >> 3] >> (~index & 7)) & 1;
1012 }
1013
1014 template <>
1015 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
1016 {
1017     return src[index];
1018 }
1019
1020 template <>
1021 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
1022 {
1023     return reinterpret_cast<const quint16 *>(src)[index];
1024 }
1025
1026 template <>
1027 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
1028 {
1029     return reinterpret_cast<const quint24 *>(src)[index];
1030 }
1031
1032 template <>
1033 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
1034 {
1035     return reinterpret_cast<const uint *>(src)[index];
1036 }
1037
1038 template <QPixelLayout::BPP bpp>
1039 inline const uint *QT_FASTCALL fetchPixels(uint *buffer, const uchar *src, int index, int count)
1040 {
1041     for (int i = 0; i < count; ++i)
1042         buffer[i] = fetchPixel<bpp>(src, index + i);
1043     return buffer;
1044 }
1045
1046 template <>
1047 inline const uint *QT_FASTCALL fetchPixels<QPixelLayout::BPP32>(uint *, const uchar *src, int index, int)
1048 {
1049     return reinterpret_cast<const uint *>(src) + index;
1050 }
1051
1052 typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
1053
1054
1055 template <QPixelLayout::BPP width>
1056 void QT_FASTCALL storePixel(uchar *dest, int index, uint pixel);
1057
1058 template <>
1059 inline void QT_FASTCALL storePixel<QPixelLayout::BPP1LSB>(uchar *dest, int index, uint pixel)
1060 {
1061     if (pixel)
1062         dest[index >> 3] |= 1 << (index & 7);
1063     else
1064         dest[index >> 3] &= ~(1 << (index & 7));
1065 }
1066
1067 template <>
1068 inline void QT_FASTCALL storePixel<QPixelLayout::BPP1MSB>(uchar *dest, int index, uint pixel)
1069 {
1070     if (pixel)
1071         dest[index >> 3] |= 1 << (~index & 7);
1072     else
1073         dest[index >> 3] &= ~(1 << (~index & 7));
1074 }
1075
1076 template <>
1077 inline void QT_FASTCALL storePixel<QPixelLayout::BPP8>(uchar *dest, int index, uint pixel)
1078 {
1079     dest[index] = uchar(pixel);
1080 }
1081
1082 template <>
1083 inline void QT_FASTCALL storePixel<QPixelLayout::BPP16>(uchar *dest, int index, uint pixel)
1084 {
1085     reinterpret_cast<quint16 *>(dest)[index] = quint16(pixel);
1086 }
1087
1088 template <>
1089 inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, uint pixel)
1090 {
1091     reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel);
1092 }
1093
1094 template <>
1095 inline void QT_FASTCALL storePixel<QPixelLayout::BPP32>(uchar *dest, int index, uint pixel)
1096 {
1097     reinterpret_cast<uint *>(dest)[index] = pixel;
1098 }
1099
1100 template <QPixelLayout::BPP width>
1101 inline void QT_FASTCALL storePixels(uchar *dest, const uint *src, int index, int count)
1102 {
1103     for (int i = 0; i < count; ++i)
1104         storePixel<width>(dest, index + i, src[i]);
1105 }
1106
1107 template <>
1108 inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint *src, int index, int count)
1109 {
1110     memcpy(reinterpret_cast<uint *>(dest) + index, src, count * sizeof(uint));
1111 }
1112
1113 typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int index, int count);
1114
1115 extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
1116 extern FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
1117 extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
1118
1119
1120
1121 QT_END_NAMESPACE
1122
1123 #endif // QDRAWHELPER_P_H