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 | { |
68 | qreal sx = srcRect.width() / (qreal) targetRect.width(); |
69 | qreal sy = srcRect.height() / (qreal) targetRect.height(); |
70 | |
71 | const int ix = 0x00010000 * sx; |
72 | 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 | QRect tr = targetRect.normalized().toRect(); |
81 | tr = tr.intersected(clip); |
82 | if (tr.isEmpty()) |
83 | return; |
84 | const int tx1 = tr.left(); |
85 | const int ty1 = tr.top(); |
86 | int h = tr.height(); |
87 | int w = tr.width(); |
88 | |
89 | quint32 basex; |
90 | quint32 srcy; |
91 | |
92 | if (sx < 0) { |
93 | int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * sx * 65536) + 1; |
94 | basex = quint32(srcRect.right() * 65536) + dstx; |
95 | } else { |
96 | int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * sx * 65536) - 1; |
97 | basex = quint32(srcRect.left() * 65536) + dstx; |
98 | } |
99 | if (sy < 0) { |
100 | int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * sy * 65536) + 1; |
101 | srcy = quint32(srcRect.bottom() * 65536) + dsty; |
102 | } else { |
103 | int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * sy * 65536) - 1; |
104 | srcy = quint32(srcRect.top() * 65536) + dsty; |
105 | } |
106 | |
107 | 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 | const int ystart = srcy >> 16; |
112 | if (ystart >= srch && iy < 0) { |
113 | srcy += iy; |
114 | --h; |
115 | } |
116 | const int xstart = basex >> 16; |
117 | if (xstart >= (int)(sbpl/sizeof(SRC)) && ix < 0) { |
118 | basex += ix; |
119 | --w; |
120 | } |
121 | int yend = (srcy + iy * (h - 1)) >> 16; |
122 | if (yend < 0 || yend >= srch) |
123 | --h; |
124 | int xend = (basex + ix * (w - 1)) >> 16; |
125 | if (xend < 0 || xend >= (int)(sbpl/sizeof(SRC))) |
126 | --w; |
127 | |
128 | while (h--) { |
129 | const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl); |
130 | quint32 srcx = basex; |
131 | int x = 0; |
132 | for (; x<w-7; x+=8) { |
133 | blender.write(&dst[x], src[srcx >> 16]); srcx += ix; |
134 | blender.write(&dst[x+1], src[srcx >> 16]); srcx += ix; |
135 | blender.write(&dst[x+2], src[srcx >> 16]); srcx += ix; |
136 | blender.write(&dst[x+3], src[srcx >> 16]); srcx += ix; |
137 | blender.write(&dst[x+4], src[srcx >> 16]); srcx += ix; |
138 | blender.write(&dst[x+5], src[srcx >> 16]); srcx += ix; |
139 | blender.write(&dst[x+6], src[srcx >> 16]); srcx += ix; |
140 | blender.write(&dst[x+7], src[srcx >> 16]); srcx += ix; |
141 | } |
142 | for (; x<w; ++x) { |
143 | blender.write(&dst[x], src[srcx >> 16]); |
144 | srcx += ix; |
145 | } |
146 | blender.flush(&dst[x]); |
147 | dst = (quint16 *)(((uchar *) dst) + dbpl); |
148 | srcy += iy; |
149 | } |
150 | } |
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 | { |
159 | qreal sx = srcRect.width() / (qreal) targetRect.width(); |
160 | qreal sy = srcRect.height() / (qreal) targetRect.height(); |
161 | |
162 | const int ix = 0x00010000 * sx; |
163 | 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 | QRect tr = targetRect.normalized().toRect(); |
172 | tr = tr.intersected(clip); |
173 | if (tr.isEmpty()) |
174 | return; |
175 | const int tx1 = tr.left(); |
176 | const int ty1 = tr.top(); |
177 | int h = tr.height(); |
178 | int w = tr.width(); |
179 | |
180 | quint32 basex; |
181 | quint32 srcy; |
182 | |
183 | if (sx < 0) { |
184 | int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * sx * 65536) + 1; |
185 | basex = quint32(srcRect.right() * 65536) + dstx; |
186 | } else { |
187 | int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * sx * 65536) - 1; |
188 | basex = quint32(srcRect.left() * 65536) + dstx; |
189 | } |
190 | if (sy < 0) { |
191 | int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * sy * 65536) + 1; |
192 | srcy = quint32(srcRect.bottom() * 65536) + dsty; |
193 | } else { |
194 | int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * sy * 65536) - 1; |
195 | srcy = quint32(srcRect.top() * 65536) + dsty; |
196 | } |
197 | |
198 | 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 | const int ystart = srcy >> 16; |
203 | if (ystart >= srch && iy < 0) { |
204 | srcy += iy; |
205 | --h; |
206 | } |
207 | const int xstart = basex >> 16; |
208 | if (xstart >= (int)(sbpl/sizeof(quint32)) && ix < 0) { |
209 | basex += ix; |
210 | --w; |
211 | } |
212 | int yend = (srcy + iy * (h - 1)) >> 16; |
213 | if (yend < 0 || yend >= srch) |
214 | --h; |
215 | int xend = (basex + ix * (w - 1)) >> 16; |
216 | if (xend < 0 || xend >= (int)(sbpl/sizeof(quint32))) |
217 | --w; |
218 | |
219 | while (h--) { |
220 | const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl); |
221 | quint32 srcx = basex; |
222 | int x = 0; |
223 | for (; x<w; ++x) { |
224 | blender.write(&dst[x], src[srcx >> 16]); |
225 | srcx += ix; |
226 | } |
227 | blender.flush(&dst[x]); |
228 | dst = (quint32 *)(((uchar *) dst) + dbpl); |
229 | srcy += iy; |
230 | } |
231 | } |
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 | { |
249 | int fromY = qMax(qRound(topY), clip.top()); |
250 | int toY = qMin(qRound(bottomY), clip.top() + clip.height()); |
251 | if (fromY >= toY) |
252 | return; |
253 | |
254 | qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y); |
255 | qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y); |
256 | int dx_l = int(leftSlope * 0x10000); |
257 | int dx_r = int(rightSlope * 0x10000); |
258 | int x_l = int((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000); |
259 | int x_r = int((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000); |
260 | |
261 | int fromX, toX, x1, x2, u, v, i, ii; |
262 | DestT *line; |
263 | for (int y = fromY; y < toY; ++y) { |
264 | line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl); |
265 | |
266 | fromX = qMax(x_l >> 16, clip.left()); |
267 | toX = qMin(x_r >> 16, clip.left() + clip.width()); |
268 | if (fromX < toX) { |
269 | // Because of rounding, we can get source coordinates outside the source image. |
270 | // Clamp these coordinates to the source rect to avoid segmentation fault and |
271 | // garbage on the screen. |
272 | |
273 | // Find the first pixel on the current scan line where the source coordinates are within the source rect. |
274 | x1 = fromX; |
275 | u = x1 * dudx + y * dudy + u0; |
276 | v = x1 * dvdx + y * dvdy + v0; |
277 | for (; x1 < toX; ++x1) { |
278 | int uu = u >> 16; |
279 | int vv = v >> 16; |
280 | if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() |
281 | && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { |
282 | break; |
283 | } |
284 | u += dudx; |
285 | v += dvdx; |
286 | } |
287 | |
288 | // Find the last pixel on the current scan line where the source coordinates are within the source rect. |
289 | x2 = toX; |
290 | u = (x2 - 1) * dudx + y * dudy + u0; |
291 | v = (x2 - 1) * dvdx + y * dvdy + v0; |
292 | for (; x2 > x1; --x2) { |
293 | int uu = u >> 16; |
294 | int vv = v >> 16; |
295 | if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() |
296 | && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { |
297 | break; |
298 | } |
299 | u -= dudx; |
300 | v -= dvdx; |
301 | } |
302 | |
303 | // Set up values at the beginning of the scan line. |
304 | u = fromX * dudx + y * dudy + u0; |
305 | v = fromX * dvdx + y * dvdy + v0; |
306 | line += fromX; |
307 | |
308 | // Beginning of the scan line, with per-pixel checks. |
309 | i = x1 - fromX; |
310 | while (i) { |
311 | int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); |
312 | int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); |
313 | blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]); |
314 | u += dudx; |
315 | v += dvdx; |
316 | ++line; |
317 | --i; |
318 | } |
319 | |
320 | // Middle of the scan line, without checks. |
321 | // Manual loop unrolling. |
322 | i = x2 - x1; |
323 | ii = i >> 3; |
324 | while (ii) { |
325 | blender.write(&line[0], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
326 | blender.write(&line[1], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
327 | blender.write(&line[2], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
328 | blender.write(&line[3], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
329 | blender.write(&line[4], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
330 | blender.write(&line[5], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
331 | blender.write(&line[6], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
332 | blender.write(&line[7], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; |
333 | |
334 | line += 8; |
335 | |
336 | --ii; |
337 | } |
338 | switch (i & 7) { |
339 | 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(); |
340 | 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(); |
341 | 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(); |
342 | 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(); |
343 | 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(); |
344 | 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(); |
345 | case 1: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; |
346 | } |
347 | |
348 | // End of the scan line, with per-pixel checks. |
349 | i = toX - x2; |
350 | while (i) { |
351 | int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); |
352 | int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); |
353 | blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]); |
354 | u += dudx; |
355 | v += dvdx; |
356 | ++line; |
357 | --i; |
358 | } |
359 | |
360 | blender.flush(line); |
361 | } |
362 | x_l += dx_l; |
363 | x_r += dx_r; |
364 | } |
365 | } |
366 | |
367 | template <class SrcT, class DestT, class Blender> |
368 | void qt_transform_image(DestT *destPixels, int dbpl, |
369 | const SrcT *srcPixels, int sbpl, |
370 | const QRectF &targetRect, |
371 | const QRectF &sourceRect, |
372 | const QRect &clip, |
373 | const QTransform &targetRectTransform, |
374 | Blender blender) |
375 | { |
376 | enum Corner |
377 | { |
378 | TopLeft, |
379 | TopRight, |
380 | BottomRight, |
381 | BottomLeft |
382 | }; |
383 | |
384 | // map source rectangle to destination. |
385 | QTransformImageVertex v[4]; |
386 | v[TopLeft].u = v[BottomLeft].u = sourceRect.left(); |
387 | v[TopLeft].v = v[TopRight].v = sourceRect.top(); |
388 | v[TopRight].u = v[BottomRight].u = sourceRect.right(); |
389 | v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom(); |
390 | targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y); |
391 | targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y); |
392 | targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y); |
393 | targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y); |
394 | |
395 | // find topmost vertex. |
396 | int topmost = 0; |
397 | for (int i = 1; i < 4; ++i) { |
398 | if (v[i].y < v[topmost].y) |
399 | topmost = i; |
400 | } |
401 | // rearrange array such that topmost vertex is at index 0. |
402 | switch (topmost) { |
403 | case 1: |
404 | { |
405 | QTransformImageVertex t = v[0]; |
406 | for (int i = 0; i < 3; ++i) |
407 | v[i] = v[i+1]; |
408 | v[3] = t; |
409 | } |
410 | break; |
411 | case 2: |
412 | qSwap(v[0], v[2]); |
413 | qSwap(v[1], v[3]); |
414 | break; |
415 | case 3: |
416 | { |
417 | QTransformImageVertex t = v[3]; |
418 | for (int i = 3; i > 0; --i) |
419 | v[i] = v[i-1]; |
420 | v[0] = t; |
421 | } |
422 | break; |
423 | } |
424 | |
425 | // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3. |
426 | qreal dx1 = v[1].x - v[0].x; |
427 | qreal dy1 = v[1].y - v[0].y; |
428 | qreal dx2 = v[3].x - v[0].x; |
429 | qreal dy2 = v[3].y - v[0].y; |
430 | if (dx1 * dy2 - dx2 * dy1 > 0) |
431 | qSwap(v[1], v[3]); |
432 | |
433 | 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}; |
434 | 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}; |
435 | |
436 | qreal det = u.x * w.y - u.y * w.x; |
437 | if (det == 0) |
438 | return; |
439 | |
440 | qreal invDet = 1.0 / det; |
441 | qreal m11, m12, m21, m22, mdx, mdy; |
442 | |
443 | m11 = (u.u * w.y - u.y * w.u) * invDet; |
444 | m12 = (u.x * w.u - u.u * w.x) * invDet; |
445 | m21 = (u.v * w.y - u.y * w.v) * invDet; |
446 | m22 = (u.x * w.v - u.v * w.x) * invDet; |
447 | mdx = v[0].u - m11 * v[0].x - m12 * v[0].y; |
448 | mdy = v[0].v - m21 * v[0].x - m22 * v[0].y; |
449 | |
450 | int dudx = int(m11 * 0x10000); |
451 | int dvdx = int(m21 * 0x10000); |
452 | int dudy = int(m12 * 0x10000); |
453 | int dvdy = int(m22 * 0x10000); |
454 | int u0 = qCeil((qreal(0.5) * m11 + qreal(0.5) * m12 + mdx) * 0x10000) - 1; |
455 | int v0 = qCeil((qreal(0.5) * m21 + qreal(0.5) * m22 + mdy) * 0x10000) - 1; |
456 | |
457 | int x1 = qFloor(sourceRect.left()); |
458 | int y1 = qFloor(sourceRect.top()); |
459 | int x2 = qCeil(sourceRect.right()); |
460 | int y2 = qCeil(sourceRect.bottom()); |
461 | QRect sourceRectI(x1, y1, x2 - x1, y2 - y1); |
462 | |
463 | // rasterize trapezoids. |
464 | if (v[1].y < v[3].y) { |
465 | 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); |
466 | 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); |
467 | 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); |
468 | } else { |
469 | 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); |
470 | 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); |
471 | 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); |
472 | } |
473 | } |
474 | |
475 | QT_END_NAMESPACE |
476 | |
477 | #endif // QBLENDFUNCTIONS_P_H |
478 | |