Coverage Report

Created: 2025-07-23 08:13

/src/qtbase/src/gui/painting/qblendfunctions_p.h
Line
Count
Source (jump to first uncovered line)
1
/****************************************************************************
2
**
3
** Copyright (C) 2016 The Qt Company Ltd.
4
** Contact: https://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14
** and conditions see https://www.qt.io/terms-conditions. For further
15
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL3 included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 3 requirements
23
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24
**
25
** GNU General Public License Usage
26
** Alternatively, this file may be used under the terms of the GNU
27
** General Public License version 2.0 or (at your option) the GNU General
28
** Public license version 3 or any later version approved by the KDE Free
29
** Qt Foundation. The licenses are as published by the Free Software
30
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31
** included in the packaging of this file. Please review the following
32
** information to ensure the GNU General Public License requirements will
33
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34
** https://www.gnu.org/licenses/gpl-3.0.html.
35
**
36
** $QT_END_LICENSE$
37
**
38
****************************************************************************/
39
40
#ifndef QBLENDFUNCTIONS_P_H
41
#define QBLENDFUNCTIONS_P_H
42
43
#include <QtGui/private/qtguiglobal_p.h>
44
#include <qmath.h>
45
#include "qdrawhelper_p.h"
46
47
QT_BEGIN_NAMESPACE
48
49
//
50
//  W A R N I N G
51
//  -------------
52
//
53
// This file is not part of the Qt API.  It exists purely as an
54
// implementation detail.  This header file may change from version to
55
// version without notice, or even be removed.
56
//
57
// We mean it.
58
//
59
60
template <typename SRC, typename T>
61
void qt_scale_image_16bit(uchar *destPixels, int dbpl,
62
                          const uchar *srcPixels, int sbpl, int srch,
63
                          const QRectF &targetRect,
64
                          const QRectF &srcRect,
65
                          const QRect &clip,
66
                          T blender)
67
0
{
68
0
    qreal sx = srcRect.width() / (qreal) targetRect.width();
69
0
    qreal sy = srcRect.height() / (qreal) targetRect.height();
70
71
0
    const int ix = 0x00010000 * sx;
72
0
    const int iy = 0x00010000 * sy;
73
74
//     qDebug() << "scale:" << Qt::endl
75
//              << " - target" << targetRect << Qt::endl
76
//              << " - source" << srcRect << Qt::endl
77
//              << " - clip" << clip << Qt::endl
78
//              << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
79
80
0
    QRect tr = targetRect.normalized().toRect();
81
0
    tr = tr.intersected(clip);
82
0
    if (tr.isEmpty())
83
0
        return;
84
0
    const int tx1 = tr.left();
85
0
    const int ty1 = tr.top();
86
0
    int h = tr.height();
87
0
    int w = tr.width();
88
89
0
    quint32 basex;
90
0
    quint32 srcy;
91
92
0
    if (sx < 0) {
93
0
        int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * sx * 65536) + 1;
94
0
        basex = quint32(srcRect.right() * 65536) + dstx;
95
0
    } else {
96
0
        int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * sx * 65536) - 1;
97
0
        basex = quint32(srcRect.left() * 65536) + dstx;
98
0
    }
99
0
    if (sy < 0) {
100
0
        int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * sy * 65536) + 1;
101
0
        srcy = quint32(srcRect.bottom() * 65536) + dsty;
102
0
    } else {
103
0
        int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * sy * 65536) - 1;
104
0
        srcy = quint32(srcRect.top() * 65536) + dsty;
105
0
    }
106
107
0
    quint16 *dst = ((quint16 *) (destPixels + ty1 * dbpl)) + tx1;
108
109
    // this bounds check here is required as floating point rounding above might in some cases lead to
110
    // w/h values that are one pixel too large, falling outside of the valid image area.
111
0
    const int ystart = srcy >> 16;
112
0
    if (ystart >= srch && iy < 0) {
113
0
        srcy += iy;
114
0
        --h;
115
0
    }
116
0
    const int xstart = basex >> 16;
117
0
    if (xstart >=  (int)(sbpl/sizeof(SRC)) && ix < 0) {
118
0
        basex += ix;
119
0
        --w;
120
0
    }
121
0
    int yend = (srcy + iy * (h - 1)) >> 16;
122
0
    if (yend < 0 || yend >= srch)
123
0
        --h;
124
0
    int xend = (basex + ix * (w - 1)) >> 16;
125
0
    if (xend < 0 || xend >= (int)(sbpl/sizeof(SRC)))
126
0
        --w;
127
128
0
    while (h--) {
129
0
        const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl);
130
0
        quint32 srcx = basex;
131
0
        int x = 0;
132
0
        for (; x<w-7; x+=8) {
133
0
            blender.write(&dst[x], src[srcx >> 16]); srcx += ix;
134
0
            blender.write(&dst[x+1], src[srcx >> 16]); srcx += ix;
135
0
            blender.write(&dst[x+2], src[srcx >> 16]); srcx += ix;
136
0
            blender.write(&dst[x+3], src[srcx >> 16]); srcx += ix;
137
0
            blender.write(&dst[x+4], src[srcx >> 16]); srcx += ix;
138
0
            blender.write(&dst[x+5], src[srcx >> 16]); srcx += ix;
139
0
            blender.write(&dst[x+6], src[srcx >> 16]); srcx += ix;
140
0
            blender.write(&dst[x+7], src[srcx >> 16]); srcx += ix;
141
0
        }
142
0
        for (; x<w; ++x) {
143
0
            blender.write(&dst[x], src[srcx >> 16]);
144
0
            srcx += ix;
145
0
        }
146
0
        blender.flush(&dst[x]);
147
0
        dst = (quint16 *)(((uchar *) dst) + dbpl);
148
0
        srcy += iy;
149
0
    }
150
0
}
Unexecuted instantiation: void qt_scale_image_16bit<unsigned short, Blend_RGB16_on_RGB16_NoAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_RGB16_on_RGB16_NoAlpha)
Unexecuted instantiation: void qt_scale_image_16bit<unsigned short, Blend_RGB16_on_RGB16_ConstAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_RGB16_on_RGB16_ConstAlpha)
Unexecuted instantiation: void qt_scale_image_16bit<unsigned int, Blend_ARGB32_on_RGB16_SourceAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_ARGB32_on_RGB16_SourceAlpha)
Unexecuted instantiation: void qt_scale_image_16bit<unsigned int, Blend_ARGB32_on_RGB16_SourceAndConstAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_ARGB32_on_RGB16_SourceAndConstAlpha)
151
152
template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
153
                                                const uchar *srcPixels, int sbpl, int srch,
154
                                                const QRectF &targetRect,
155
                                                const QRectF &srcRect,
156
                                                const QRect &clip,
157
                                                T blender)
158
0
{
159
0
    qreal sx = srcRect.width() / (qreal) targetRect.width();
160
0
    qreal sy = srcRect.height() / (qreal) targetRect.height();
161
162
0
    const int ix = 0x00010000 * sx;
163
0
    const int iy = 0x00010000 * sy;
164
165
//     qDebug() << "scale:" << Qt::endl
166
//              << " - target" << targetRect << Qt::endl
167
//              << " - source" << srcRect << Qt::endl
168
//              << " - clip" << clip << Qt::endl
169
//              << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
170
171
0
    QRect tr = targetRect.normalized().toRect();
172
0
    tr = tr.intersected(clip);
173
0
    if (tr.isEmpty())
174
0
        return;
175
0
    const int tx1 = tr.left();
176
0
    const int ty1 = tr.top();
177
0
    int h = tr.height();
178
0
    int w = tr.width();
179
180
0
    quint32 basex;
181
0
    quint32 srcy;
182
183
0
    if (sx < 0) {
184
0
        int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * sx * 65536) + 1;
185
0
        basex = quint32(srcRect.right() * 65536) + dstx;
186
0
    } else {
187
0
        int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * sx * 65536) - 1;
188
0
        basex = quint32(srcRect.left() * 65536) + dstx;
189
0
    }
190
0
    if (sy < 0) {
191
0
        int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * sy * 65536) + 1;
192
0
        srcy = quint32(srcRect.bottom() * 65536) + dsty;
193
0
    } else {
194
0
        int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * sy * 65536) - 1;
195
0
        srcy = quint32(srcRect.top() * 65536) + dsty;
196
0
    }
197
198
0
    quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1;
199
200
    // this bounds check here is required as floating point rounding above might in some cases lead to
201
    // w/h values that are one pixel too large, falling outside of the valid image area.
202
0
    const int ystart = srcy >> 16;
203
0
    if (ystart >= srch && iy < 0) {
204
0
        srcy += iy;
205
0
        --h;
206
0
    }
207
0
    const int xstart = basex >> 16;
208
0
    if (xstart >=  (int)(sbpl/sizeof(quint32)) && ix < 0) {
209
0
        basex += ix;
210
0
        --w;
211
0
    }
212
0
    int yend = (srcy + iy * (h - 1)) >> 16;
213
0
    if (yend < 0 || yend >= srch)
214
0
        --h;
215
0
    int xend = (basex + ix * (w - 1)) >> 16;
216
0
    if (xend < 0 || xend >= (int)(sbpl/sizeof(quint32)))
217
0
        --w;
218
219
0
    while (h--) {
220
0
        const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
221
0
        quint32 srcx = basex;
222
0
        int x = 0;
223
0
        for (; x<w; ++x) {
224
0
            blender.write(&dst[x], src[srcx >> 16]);
225
0
            srcx += ix;
226
0
        }
227
0
        blender.flush(&dst[x]);
228
0
        dst = (quint32 *)(((uchar *) dst) + dbpl);
229
0
        srcy += iy;
230
0
    }
231
0
}
Unexecuted instantiation: void qt_scale_image_32bit<Blend_RGB32_on_RGB32_NoAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_RGB32_on_RGB32_NoAlpha)
Unexecuted instantiation: void qt_scale_image_32bit<Blend_RGB32_on_RGB32_ConstAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_RGB32_on_RGB32_ConstAlpha)
Unexecuted instantiation: void qt_scale_image_32bit<Blend_ARGB32_on_ARGB32_SourceAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_ARGB32_on_ARGB32_SourceAlpha)
Unexecuted instantiation: void qt_scale_image_32bit<Blend_ARGB32_on_ARGB32_SourceAndConstAlpha>(unsigned char*, int, unsigned char const*, int, int, QRectF const&, QRectF const&, QRect const&, Blend_ARGB32_on_ARGB32_SourceAndConstAlpha)
232
233
struct QTransformImageVertex
234
{
235
    qreal x, y, u, v; // destination coordinates (x, y) and source coordinates (u, v)
236
};
237
238
template <class SrcT, class DestT, class Blender>
239
void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
240
                                  const SrcT *srcPixels, int sbpl,
241
                                  const QTransformImageVertex &topLeft, const QTransformImageVertex &bottomLeft,
242
                                  const QTransformImageVertex &topRight, const QTransformImageVertex &bottomRight,
243
                                  const QRect &sourceRect,
244
                                  const QRect &clip,
245
                                  qreal topY, qreal bottomY,
246
                                  int dudx, int dvdx, int dudy, int dvdy, int u0, int v0,
247
                                  Blender blender)
248
0
{
249
0
    qint64 fromY = qMax(qRound(topY), clip.top());
250
0
    qint64 toY = qMin(qRound(bottomY), clip.top() + clip.height());
251
0
    if (fromY >= toY)
252
0
        return;
253
254
0
    qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y);
255
0
    qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
256
0
    qint64 dx_l = qint64(leftSlope * 0x10000);
257
0
    qint64 dx_r = qint64(rightSlope * 0x10000);
258
0
    qint64 x_l = qint64((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000);
259
0
    qint64 x_r = qint64((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000);
260
261
0
    qint64 sourceRectTop = qint64(sourceRect.top());
262
0
    qint64 sourceRectLeft = qint64(sourceRect.left());
263
0
    qint64 sourceRectWidth = qint64(sourceRect.width());
264
0
    qint64 sourceRectHeight = qint64(sourceRect.height());
265
0
    qint64 clipLeft = qint64(clip.left());
266
0
    qint64 clipWidth = qint64(clip.width());
267
268
0
    qint64 fromX, toX, x1, x2, u, v, i, ii;
269
0
    DestT *line;
270
0
    for (qint64 y = fromY; y < toY; ++y) {
271
0
        line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl);
272
273
0
        fromX = qMax(x_l >> 16, clipLeft);
274
0
        toX = qMin(x_r >> 16, clipLeft + clipWidth);
275
0
        if (fromX < toX) {
276
            // Because of rounding, we can get source coordinates outside the source image.
277
            // Clamp these coordinates to the source rect to avoid segmentation fault and
278
            // garbage on the screen.
279
280
            // Find the first pixel on the current scan line where the source coordinates are within the source rect.
281
0
            x1 = fromX;
282
0
            u = x1 * dudx + y * dudy + u0;
283
0
            v = x1 * dvdx + y * dvdy + v0;
284
0
            for (; x1 < toX; ++x1) {
285
0
                qint64 uu = u >> 16;
286
0
                qint64 vv = v >> 16;
287
0
                if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth
288
0
                    && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) {
289
0
                    break;
290
0
                }
291
0
                u += dudx;
292
0
                v += dvdx;
293
0
            }
294
295
            // Find the last pixel on the current scan line where the source coordinates are within the source rect.
296
0
            x2 = toX;
297
0
            u = (x2 - 1) * dudx + y * dudy + u0;
298
0
            v = (x2 - 1) * dvdx + y * dvdy + v0;
299
0
            for (; x2 > x1; --x2) {
300
0
                qint64 uu = u >> 16;
301
0
                qint64 vv = v >> 16;
302
0
                if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth
303
0
                    && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) {
304
0
                    break;
305
0
                }
306
0
                u -= dudx;
307
0
                v -= dvdx;
308
0
            }
309
310
            // Set up values at the beginning of the scan line.
311
0
            u = fromX * dudx + y * dudy + u0;
312
0
            v = fromX * dvdx + y * dvdy + v0;
313
0
            line += fromX;
314
315
            // Beginning of the scan line, with per-pixel checks.
316
0
            i = x1 - fromX;
317
0
            while (i) {
318
0
                qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1);
319
0
                qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1);
320
0
                blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
321
0
                u += dudx;
322
0
                v += dvdx;
323
0
                ++line;
324
0
                --i;
325
0
            }
326
327
            // Middle of the scan line, without checks.
328
            // Manual loop unrolling.
329
0
            i = x2 - x1;
330
0
            ii = i >> 3;
331
0
            while (ii) {
332
0
                blender.write(&line[0], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
333
0
                blender.write(&line[1], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
334
0
                blender.write(&line[2], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
335
0
                blender.write(&line[3], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
336
0
                blender.write(&line[4], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
337
0
                blender.write(&line[5], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
338
0
                blender.write(&line[6], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
339
0
                blender.write(&line[7], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
340
341
0
                line += 8;
342
343
0
                --ii;
344
0
            }
345
0
            switch (i & 7) {
346
0
                case 7: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH();
347
0
                case 6: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH();
348
0
                case 5: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH();
349
0
                case 4: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH();
350
0
                case 3: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH();
351
0
                case 2: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH();
352
0
                case 1: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
353
0
            }
354
355
            // End of the scan line, with per-pixel checks.
356
0
            i = toX - x2;
357
0
            while (i) {
358
0
                qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1);
359
0
                qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1);
360
0
                blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
361
0
                u += dudx;
362
0
                v += dvdx;
363
0
                ++line;
364
0
                --i;
365
0
            }
366
367
0
            blender.flush(line);
368
0
        }
369
0
        x_l += dx_l;
370
0
        x_r += dx_r;
371
0
    }
372
0
}
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned short, unsigned short, Blend_RGB16_on_RGB16_NoAlpha>(unsigned short*, int, unsigned short const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_RGB16_on_RGB16_NoAlpha)
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned short, unsigned short, Blend_RGB16_on_RGB16_ConstAlpha>(unsigned short*, int, unsigned short const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_RGB16_on_RGB16_ConstAlpha)
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned int, unsigned short, Blend_ARGB32_on_RGB16_SourceAlpha>(unsigned short*, int, unsigned int const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_ARGB32_on_RGB16_SourceAlpha)
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned int, unsigned short, Blend_ARGB32_on_RGB16_SourceAndConstAlpha>(unsigned short*, int, unsigned int const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_ARGB32_on_RGB16_SourceAndConstAlpha)
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned int, unsigned int, Blend_RGB32_on_RGB32_NoAlpha>(unsigned int*, int, unsigned int const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_RGB32_on_RGB32_NoAlpha)
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned int, unsigned int, Blend_RGB32_on_RGB32_ConstAlpha>(unsigned int*, int, unsigned int const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_RGB32_on_RGB32_ConstAlpha)
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned int, unsigned int, Blend_ARGB32_on_ARGB32_SourceAlpha>(unsigned int*, int, unsigned int const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_ARGB32_on_ARGB32_SourceAlpha)
Unexecuted instantiation: void qt_transform_image_rasterize<unsigned int, unsigned int, Blend_ARGB32_on_ARGB32_SourceAndConstAlpha>(unsigned int*, int, unsigned int const*, int, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QTransformImageVertex const&, QRect const&, QRect const&, double, double, int, int, int, int, int, int, Blend_ARGB32_on_ARGB32_SourceAndConstAlpha)
373
374
template <class SrcT, class DestT, class Blender>
375
void qt_transform_image(DestT *destPixels, int dbpl,
376
                        const SrcT *srcPixels, int sbpl,
377
                        const QRectF &targetRect,
378
                        const QRectF &sourceRect,
379
                        const QRect &clip,
380
                        const QTransform &targetRectTransform,
381
                        Blender blender)
382
0
{
383
0
    enum Corner
384
0
    {
385
0
        TopLeft,
386
0
        TopRight,
387
0
        BottomRight,
388
0
        BottomLeft
389
0
    };
390
391
    // map source rectangle to destination.
392
0
    QTransformImageVertex v[4];
393
0
    v[TopLeft].u = v[BottomLeft].u = sourceRect.left();
394
0
    v[TopLeft].v = v[TopRight].v = sourceRect.top();
395
0
    v[TopRight].u = v[BottomRight].u = sourceRect.right();
396
0
    v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom();
397
0
    targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y);
398
0
    targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y);
399
0
    targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y);
400
0
    targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y);
401
402
    // find topmost vertex.
403
0
    int topmost = 0;
404
0
    for (int i = 1; i < 4; ++i) {
405
0
        if (v[i].y < v[topmost].y)
406
0
            topmost = i;
407
0
    }
408
    // rearrange array such that topmost vertex is at index 0.
409
0
    switch (topmost) {
410
0
    case 1:
411
0
        {
412
0
            QTransformImageVertex t = v[0];
413
0
            for (int i = 0; i < 3; ++i)
414
0
                v[i] = v[i+1];
415
0
            v[3] = t;
416
0
        }
417
0
        break;
418
0
    case 2:
419
0
        qSwap(v[0], v[2]);
420
0
        qSwap(v[1], v[3]);
421
0
        break;
422
0
    case 3:
423
0
        {
424
0
            QTransformImageVertex t = v[3];
425
0
            for (int i = 3; i > 0; --i)
426
0
                v[i] = v[i-1];
427
0
            v[0] = t;
428
0
        }
429
0
        break;
430
0
    }
431
432
    // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3.
433
0
    qreal dx1 = v[1].x - v[0].x;
434
0
    qreal dy1 = v[1].y - v[0].y;
435
0
    qreal dx2 = v[3].x - v[0].x;
436
0
    qreal dy2 = v[3].y - v[0].y;
437
0
    if (dx1 * dy2 - dx2 * dy1 > 0)
438
0
        qSwap(v[1], v[3]);
439
440
0
    QTransformImageVertex u = {v[1].x - v[0].x, v[1].y - v[0].y, v[1].u - v[0].u, v[1].v - v[0].v};
441
0
    QTransformImageVertex w = {v[2].x - v[0].x, v[2].y - v[0].y, v[2].u - v[0].u, v[2].v - v[0].v};
442
443
0
    qreal det = u.x * w.y - u.y * w.x;
444
0
    if (det == 0)
445
0
        return;
446
447
0
    qreal invDet = 1.0 / det;
448
0
    qreal m11, m12, m21, m22, mdx, mdy;
449
450
0
    m11 = (u.u * w.y - u.y * w.u) * invDet;
451
0
    m12 = (u.x * w.u - u.u * w.x) * invDet;
452
0
    m21 = (u.v * w.y - u.y * w.v) * invDet;
453
0
    m22 = (u.x * w.v - u.v * w.x) * invDet;
454
0
    mdx = v[0].u - m11 * v[0].x - m12 * v[0].y;
455
0
    mdy = v[0].v - m21 * v[0].x - m22 * v[0].y;
456
457
0
    int dudx = int(m11 * 0x10000);
458
0
    int dvdx = int(m21 * 0x10000);
459
0
    int dudy = int(m12 * 0x10000);
460
0
    int dvdy = int(m22 * 0x10000);
461
0
    int u0 = qCeil((qreal(0.5) * m11 + qreal(0.5) * m12 + mdx) * 0x10000) - 1;
462
0
    int v0 = qCeil((qreal(0.5) * m21 + qreal(0.5) * m22 + mdy) * 0x10000) - 1;
463
464
0
    int x1 = qFloor(sourceRect.left());
465
0
    int y1 = qFloor(sourceRect.top());
466
0
    int x2 = qCeil(sourceRect.right());
467
0
    int y2 = qCeil(sourceRect.bottom());
468
0
    QRect sourceRectI(x1, y1, x2 - x1, y2 - y1);
469
470
    // rasterize trapezoids.
471
0
    if (v[1].y < v[3].y) {
472
0
        qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
473
0
        qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[0], v[3], sourceRectI, clip, v[1].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
474
0
        qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[3].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
475
0
    } else {
476
0
        qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
477
0
        qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[3], v[2], sourceRectI, clip, v[3].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
478
0
        qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[1].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
479
0
    }
480
0
}
Unexecuted instantiation: void qt_transform_image<unsigned short, unsigned short, Blend_RGB16_on_RGB16_NoAlpha>(unsigned short*, int, unsigned short const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_RGB16_on_RGB16_NoAlpha)
Unexecuted instantiation: void qt_transform_image<unsigned short, unsigned short, Blend_RGB16_on_RGB16_ConstAlpha>(unsigned short*, int, unsigned short const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_RGB16_on_RGB16_ConstAlpha)
Unexecuted instantiation: void qt_transform_image<unsigned int, unsigned short, Blend_ARGB32_on_RGB16_SourceAlpha>(unsigned short*, int, unsigned int const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_ARGB32_on_RGB16_SourceAlpha)
Unexecuted instantiation: void qt_transform_image<unsigned int, unsigned short, Blend_ARGB32_on_RGB16_SourceAndConstAlpha>(unsigned short*, int, unsigned int const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_ARGB32_on_RGB16_SourceAndConstAlpha)
Unexecuted instantiation: void qt_transform_image<unsigned int, unsigned int, Blend_RGB32_on_RGB32_NoAlpha>(unsigned int*, int, unsigned int const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_RGB32_on_RGB32_NoAlpha)
Unexecuted instantiation: void qt_transform_image<unsigned int, unsigned int, Blend_RGB32_on_RGB32_ConstAlpha>(unsigned int*, int, unsigned int const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_RGB32_on_RGB32_ConstAlpha)
Unexecuted instantiation: void qt_transform_image<unsigned int, unsigned int, Blend_ARGB32_on_ARGB32_SourceAlpha>(unsigned int*, int, unsigned int const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_ARGB32_on_ARGB32_SourceAlpha)
Unexecuted instantiation: void qt_transform_image<unsigned int, unsigned int, Blend_ARGB32_on_ARGB32_SourceAndConstAlpha>(unsigned int*, int, unsigned int const*, int, QRectF const&, QRectF const&, QRect const&, QTransform const&, Blend_ARGB32_on_ARGB32_SourceAndConstAlpha)
481
482
QT_END_NAMESPACE
483
484
#endif // QBLENDFUNCTIONS_P_H