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