/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 |