1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #ifndef QDRAWHELPER_P_H
43 #define QDRAWHELPER_P_H
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.
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
64 #include "private/qrasterdefs_p.h"
65 #include <private/qsimd_p.h>
66 #include <private/qmath_p.h>
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__
80 # define Q_STATIC_TEMPLATE_FUNCTION static
81 # define Q_STATIC_INLINE_FUNCTION static inline
82 # define Q_DECL_RESTRICT
85 static const uint AMASK = 0xff000000;
86 static const uint RMASK = 0x00ff0000;
87 static const uint GMASK = 0x0000ff00;
88 static const uint BMASK = 0x000000ff;
90 /*******************************************************************************
93 * duplicate definition of FT_Span
95 typedef QT_FT_Span QSpan;
100 struct QLinearGradientData;
101 struct QRadialGradientData;
102 struct QConicalGradientData;
107 class QRasterPaintEngineState;
109 typedef QT_FT_SpanFunc ProcessSpans;
110 typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer,
111 int x, int y, quint32 color,
113 int mapWidth, int mapHeight, int mapStride);
115 typedef void (*AlphamapBlitFunc)(QRasterBuffer *rasterBuffer,
116 int x, int y, quint32 color,
118 int mapWidth, int mapHeight, int mapStride,
119 const QClipData *clip);
121 typedef void (*AlphaRGBBlitFunc)(QRasterBuffer *rasterBuffer,
122 int x, int y, quint32 color,
124 int mapWidth, int mapHeight, int mapStride,
125 const QClipData *clip);
127 typedef void (*RectFillFunc)(QRasterBuffer *rasterBuffer,
128 int x, int y, int width, int height,
131 typedef void (*SrcOverBlendFunc)(uchar *destPixels, int dbpl,
132 const uchar *src, int spbl,
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,
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,
151 typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
154 ProcessSpans blendColor;
155 ProcessSpans blendGradient;
156 BitmapBlitFunc bitmapBlit;
157 AlphamapBlitFunc alphamapBlit;
158 AlphaRGBBlitFunc alphaRGBBlit;
159 RectFillFunc fillRect;
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];
167 extern DrawHelper qDrawHelper[QImage::NImageFormats];
169 void qBlendTexture(int count, const QSpan *spans, void *userData);
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);
174 struct LinearGradientValues
182 struct RadialGradientValues
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);
200 QPainter::CompositionMode mode;
201 DestFetchProc dest_fetch;
202 DestStoreProc dest_store;
203 SourceFetchProc src_fetch;
204 CompositionFunctionSolid funcSolid;
205 CompositionFunction func;
207 LinearGradientValues linear;
208 RadialGradientValues radial;
212 void qInitDrawhelperAsm();
214 class QRasterPaintEngine;
221 struct QLinearGradientData
233 struct QRadialGradientData
247 struct QConicalGradientData
258 QGradient::Spread spread;
261 QLinearGradientData linear;
262 QRadialGradientData radial;
263 QConicalGradientData conical;
266 #define GRADIENT_STOPTABLE_SIZE 1024
267 #define GRADIENT_STOPTABLE_SIZE_SHIFT 10
269 uint* colorTable; //[GRADIENT_STOPTABLE_SIZE];
276 const uchar *imageData;
277 const uchar *scanLine(int y) const { return imageData + y*bytesPerLine; }
287 QImage::Format format;
288 const QVector<QRgb> *colorTable;
300 QSpanData() : tempImage(0) {}
301 ~QSpanData() { delete tempImage; }
303 QRasterBuffer *rasterBuffer;
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;
326 QGradientData gradient;
327 QTextureData texture;
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();
337 struct QDrawHelperGammaTables
339 explicit QDrawHelperGammaTables(qreal smoothing);
341 void refresh(qreal smoothing);
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];
349 static inline uint qt_gradient_clamp(const QGradientData *data, int ipos)
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;
358 ipos = ipos < 0 ? limit + ipos : ipos;
359 ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - 1 - ipos : ipos;
363 else if (ipos >= GRADIENT_STOPTABLE_SIZE)
364 ipos = GRADIENT_STOPTABLE_SIZE-1;
369 Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
374 static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos)
376 int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5));
377 return data->colorTable[qt_gradient_clamp(data, ipos)];
380 static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c)
382 return (b * b) - (4 * a * c);
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)
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);
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;
403 uint *end = buffer + length;
405 rx -= data->gradient.radial.focal.x;
406 ry -= data->gradient.radial.focal.y;
408 qreal inv_a = 1 / qreal(2 * op->radial.a);
410 const qreal delta_rx = data->m11;
411 const qreal delta_ry = data->m12;
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;
418 const qreal bb = b * b;
419 const qreal delta_bb = delta_b * delta_b;
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;
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;
435 RadialFetchFunc::fetch(buffer, end, op, data, det, delta_det, delta_delta_det, b, delta_b);
437 qreal rw = data->m23 * (y + qreal(0.5))
438 + data->m33 + data->m13 * (x + qreal(0.5));
440 while (buffer < end) {
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));
452 qreal detSqrt = qSqrt(det);
454 qreal s0 = (-b - detSqrt) * op->radial.inv2a;
455 qreal s1 = (-b + detSqrt) * op->radial.inv2a;
457 qreal s = qMax(s0, s1);
459 if (data->gradient.radial.focal.radius + op->radial.dr * s >= 0)
460 result = qt_gradient_pixel(&data->gradient, s);
477 template <class Simd>
478 class QRadialFetchSimd
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)
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;
488 for (int i = 0; i < 4; ++i) {
490 delta_det4_vec.f[i] = 4 * delta_det;
494 delta_det += delta_delta_det;
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);
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);
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);
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)));
512 const typename Simd::Int32x4 v_reflect_limit = Simd::v_dup(2 * GRADIENT_STOPTABLE_SIZE - 1);
514 const int extended_mask = op->radial.extended ? 0x0 : ~0x0;
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]]; \
540 #define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \
541 FETCH_RADIAL_LOOP_PROLOGUE \
542 FETCH_RADIAL_LOOP_CLAMP \
543 FETCH_RADIAL_LOOP_EPILOGUE
545 switch (data->gradient.spread) {
546 case QGradient::RepeatSpread:
547 FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REPEAT)
549 case QGradient::ReflectSpread:
550 FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REFLECT)
552 case QGradient::PadSpread:
553 FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_PAD)
561 #if defined(Q_CC_RVCT)
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;
570 x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
571 x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
576 #if defined(Q_CC_RVCT)
580 #if QT_POINTER_SIZE == 8 // 64-bit versions
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;
586 t &= 0x00ff00ff00ff00ff;
587 return (uint(t)) | (uint(t >> 24));
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));
597 Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
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);
605 #else // 32-bit versions
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;
612 x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
618 #if defined(Q_CC_RVCT)
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;
627 x = ((x >> 8) & 0xff00ff) * a;
628 x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
633 #if defined(Q_CC_RVCT)
637 Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
639 uint t = (x & 0xff00ff) * a;
640 t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
643 x = ((x >> 8) & 0xff) * a;
644 x = (x + ((x >> 8) & 0xff) + 0x80);
652 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) {
654 uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
655 t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f;
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;
665 #define INV_PREMUL(p) \
666 (qAlpha(p) == 0 ? 0 : \
668 | (((255*qRed(p))/ qAlpha(p)) << 16) \
669 | (((255*qGreen(p)) / qAlpha(p)) << 8) \
670 | ((255*qBlue(p)) / qAlpha(p))))
674 operator uint() const;
678 inline quint24::quint24(uint value)
680 data[0] = uchar(value >> 16);
681 data[1] = uchar(value >> 8);
682 data[2] = uchar(value);
685 inline quint24::operator uint() const
687 return data[2] | (data[1] << 8) | (data[0] << 16);
691 void qt_memfill(T *dest, T value, int count);
693 template<> inline void qt_memfill(quint32 *dest, quint32 color, int count)
695 extern void (*qt_memfill32)(quint32 *dest, quint32 value, int count);
696 qt_memfill32(dest, color, count);
699 template<> inline void qt_memfill(quint16 *dest, quint16 color, int count)
701 extern void (*qt_memfill16)(quint16 *dest, quint16 value, int count);
702 qt_memfill16(dest, color, count);
705 template<> inline void qt_memfill(quint8 *dest, quint8 color, int count)
707 memset(dest, color, count);
711 inline void qt_memfill(T *dest, T value, int count)
716 int n = (count + 7) / 8;
717 switch (count & 0x07)
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;
732 inline void qt_rectfill(T *dest, T value,
733 int x, int y, int width, int height, int stride)
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);
739 for (int j = 0; j < height; ++j) {
740 dest = reinterpret_cast<T*>(d);
741 qt_memfill(dest, value, width);
747 #define QT_MEMFILL_UINT(dest, length, color) \
748 qt_memfill<quint32>(dest, color, length);
750 #define QT_MEMFILL_USHORT(dest, length, color) \
751 qt_memfill<quint16>(dest, color, length);
753 #define QT_MEMCPY_REV_UINT(dest, src, length) \
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) \
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; \
773 #define QT_MEMCPY_USHORT(dest, src, length) \
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) \
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++; \
793 #if defined(Q_CC_RVCT)
797 Q_STATIC_INLINE_FUNCTION int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
798 #if defined(Q_CC_RVCT)
802 inline ushort qConvertRgb32To16(uint c)
804 return (((c) >> 3) & 0x001f)
805 | (((c) >> 5) & 0x07e0)
806 | (((c) >> 8) & 0xf800);
809 inline QRgb qConvertRgb16To32(uint c)
812 | ((((c) << 3) & 0xf8) | (((c) >> 2) & 0x7))
813 | ((((c) << 5) & 0xfc00) | (((c) >> 1) & 0x300))
814 | ((((c) << 8) & 0xf80000) | (((c) << 3) & 0x70000));
817 inline int qRed565(quint16 rgb) {
818 const int r = (rgb & 0xf800);
819 return (r >> 8) | (r >> 13);
822 inline int qGreen565(quint16 rgb) {
823 const int g = (rgb & 0x07e0);
824 return (g >> 3) | (g >> 9);
827 inline int qBlue565(quint16 rgb) {
828 const int b = (rgb & 0x001f);
829 return (b << 3) | (b >> 2);
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}
867 #define ARGB_COMBINE_ALPHA(argb, alpha) \
868 ((((argb >> 24) * alpha) >> 8) << 24) | (argb & 0x00ffffff)
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)))
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)))
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)
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);
886 inline int comp_func_Plus_one_pixel(uint d, const uint s)
888 const int result = (AMIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
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);
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);
967 typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count,
968 const QPixelLayout *layout, const QRgb *clut);
984 // All numbers in bits.
995 ConvertFunc convertToARGB32PM;
996 ConvertFunc convertFromARGB32PM;
999 template <QPixelLayout::BPP bpp>
1000 uint QT_FASTCALL fetchPixel(const uchar *src, int index);
1003 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
1005 return (src[index >> 3] >> (index & 7)) & 1;
1009 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
1011 return (src[index >> 3] >> (~index & 7)) & 1;
1015 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
1021 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
1023 return reinterpret_cast<const quint16 *>(src)[index];
1027 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
1029 return reinterpret_cast<const quint24 *>(src)[index];
1033 inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
1035 return reinterpret_cast<const uint *>(src)[index];
1038 template <QPixelLayout::BPP bpp>
1039 inline const uint *QT_FASTCALL fetchPixels(uint *buffer, const uchar *src, int index, int count)
1041 for (int i = 0; i < count; ++i)
1042 buffer[i] = fetchPixel<bpp>(src, index + i);
1047 inline const uint *QT_FASTCALL fetchPixels<QPixelLayout::BPP32>(uint *, const uchar *src, int index, int)
1049 return reinterpret_cast<const uint *>(src) + index;
1052 typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
1055 template <QPixelLayout::BPP width>
1056 void QT_FASTCALL storePixel(uchar *dest, int index, uint pixel);
1059 inline void QT_FASTCALL storePixel<QPixelLayout::BPP1LSB>(uchar *dest, int index, uint pixel)
1062 dest[index >> 3] |= 1 << (index & 7);
1064 dest[index >> 3] &= ~(1 << (index & 7));
1068 inline void QT_FASTCALL storePixel<QPixelLayout::BPP1MSB>(uchar *dest, int index, uint pixel)
1071 dest[index >> 3] |= 1 << (~index & 7);
1073 dest[index >> 3] &= ~(1 << (~index & 7));
1077 inline void QT_FASTCALL storePixel<QPixelLayout::BPP8>(uchar *dest, int index, uint pixel)
1079 dest[index] = uchar(pixel);
1083 inline void QT_FASTCALL storePixel<QPixelLayout::BPP16>(uchar *dest, int index, uint pixel)
1085 reinterpret_cast<quint16 *>(dest)[index] = quint16(pixel);
1089 inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, uint pixel)
1091 reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel);
1095 inline void QT_FASTCALL storePixel<QPixelLayout::BPP32>(uchar *dest, int index, uint pixel)
1097 reinterpret_cast<uint *>(dest)[index] = pixel;
1100 template <QPixelLayout::BPP width>
1101 inline void QT_FASTCALL storePixels(uchar *dest, const uint *src, int index, int count)
1103 for (int i = 0; i < count; ++i)
1104 storePixel<width>(dest, index + i, src[i]);
1108 inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint *src, int index, int count)
1110 memcpy(reinterpret_cast<uint *>(dest) + index, src, count * sizeof(uint));
1113 typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int index, int count);
1115 extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
1116 extern FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
1117 extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
1123 #endif // QDRAWHELPER_P_H