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