1 /*
2 SPDX-FileCopyrightText: 2015-2017 Pavel Mraz
3
4 SPDX-FileCopyrightText: 2017 Jasem Mutlaq
5
6 SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "scanrender.h"
10
11 //#include <omp.h>
12 //#define PARALLEL_OMP
13
14 #define FRAC(f, from, to) ((((f) - (from)) / (double)((to) - (from))))
15 #define LERP(f, mi, ma) ((mi) + (f) * ((ma) - (mi)))
16 #define CLAMP(v, mi, ma) (((v) < (mi)) ? (mi) : ((v) > (ma)) ? (ma) : (v))
17 #define SIGN(x) ((x) >= 0 ? 1.0 : -1.0)
18
19 #pragma GCC diagnostic push
20 #pragma GCC diagnostic ignored "-Wcast-align"
21
22 //////////////////////////////
ScanRender(void)23 ScanRender::ScanRender(void)
24 //////////////////////////////
25 {
26 }
27
28 /////////////////////////////////////////////////
setBilinearInterpolationEnabled(bool enable)29 void ScanRender::setBilinearInterpolationEnabled(bool enable)
30 /////////////////////////////////////////////////
31 {
32 bBilinear = enable;
33 }
34
35 //////////////////////////////////
isBilinearInterpolationEnabled()36 bool ScanRender::isBilinearInterpolationEnabled()
37 //////////////////////////////////
38 {
39 return(bBilinear);
40 }
41
42 ///////////////////////////////////////////////
resetScanPoly(int sx,int sy)43 void ScanRender::resetScanPoly(int sx, int sy)
44 ///////////////////////////////////////////////
45 {
46 plMinY = 999999;
47 plMaxY = -999999;
48
49 if (sy >= MAX_BK_SCANLINES)
50 {
51 qDebug("ScanRender::resetScanPoly fail!");
52 return;
53 }
54
55 m_sx = sx;
56 m_sy = sy;
57 }
58
59 //////////////////////////////////////////////////////////
scanLine(int x1,int y1,int x2,int y2)60 void ScanRender::scanLine(int x1, int y1, int x2, int y2)
61 //////////////////////////////////////////////////////////
62 {
63 int side;
64
65 if (y1 > y2)
66 {
67 qSwap(x1, x2);
68 qSwap(y1, y2);
69 side = 0;
70 }
71 else
72 {
73 side = 1;
74 }
75
76 if (y2 < 0)
77 {
78 return; // offscreen
79 }
80
81 if (y1 >= m_sy)
82 {
83 return; // offscreen
84 }
85
86 float dy = (float)(y2 - y1);
87
88 if (dy == 0) // hor. line
89 {
90 return;
91 }
92
93 float dx = (float)(x2 - x1) / dy;
94 float x = x1;
95 int y;
96
97 if (y2 >= m_sy)
98 {
99 y2 = m_sy - 1;
100 }
101
102 if (y1 < 0)
103 { // partially off screen
104 float m = (float) -y1;
105
106 x += dx * m;
107 y1 = 0;
108 }
109
110 int minY = qMin(y1, y2);
111 int maxY = qMax(y1, y2);
112
113 if (minY < plMinY)
114 plMinY = minY;
115 if (maxY > plMaxY)
116 plMaxY = maxY;
117
118 #define SCAN_FIX_PT 1
119
120 #if SCAN_FIX_PT
121
122 #define FP 16
123
124 int fx = (int)(x * (float)(1 << FP));
125 int fdx = (int)(dx * (float)(1 << FP));
126
127 for (y = y1; y <= y2; y++)
128 {
129 scLR[y].scan[side] = fx >> FP;
130 fx += fdx;
131 }
132
133 #else
134
135 for (y = y1; y <= y2; y++)
136 {
137 if (side == 1)
138 { // side left
139 scLR[y].scan[0] = float2int(x);
140 }
141 else
142 { // side right
143 scLR[y].scan[1] = float2int(x);
144 }
145 x += dx;
146 }
147
148 #endif
149 }
150
151
152 //////////////////////////////////////////////////////////////////////////////////////////////////
scanLine(int x1,int y1,int x2,int y2,float u1,float v1,float u2,float v2)153 void ScanRender::scanLine(int x1, int y1, int x2, int y2, float u1, float v1, float u2, float v2)
154 //////////////////////////////////////////////////////////////////////////////////////////////////
155 {
156 int side;
157
158 if (y1 > y2)
159 {
160 qSwap(x1, x2);
161 qSwap(y1, y2);
162 qSwap(u1, u2);
163 qSwap(v1, v2);
164 side = 0;
165 }
166 else
167 {
168 side = 1;
169 }
170
171 if (y2 < 0)
172 return; // offscreen
173 if (y1 >= m_sy)
174 return; // offscreen
175
176 float dy = (float)(y2 - y1);
177
178 if (dy == 0) // hor. line
179 return;
180
181 float dx = (float)(x2 - x1) / dy;
182 float x = x1;
183 int y;
184
185 if (y2 >= m_sy)
186 y2 = m_sy - 1;
187
188 float duv[2];
189 float uv[2] = {u1, v1};
190
191 duv[0] = (u2 - u1) / dy;
192 duv[1] = (v2 - v1) / dy;
193
194 if (y1 < 0)
195 { // partially off screen
196 float m = (float) -y1;
197
198 uv[0] += duv[0] * m;
199 uv[1] += duv[1] * m;
200
201 x += dx * m;
202 y1 = 0;
203 }
204
205 int minY = qMin(y1, y2);
206 int maxY = qMax(y1, y2);
207
208 if (minY < plMinY)
209 plMinY = minY;
210 if (maxY > plMaxY)
211 plMaxY = maxY;
212
213 for (y = y1; y <= y2; y++)
214 {
215 scLR[y].scan[side] = (int)x;
216 scLR[y].uv[side][0] = uv[0];
217 scLR[y].uv[side][1] = uv[1];
218
219 x += dx;
220
221 uv[0] += duv[0];
222 uv[1] += duv[1];
223 }
224 }
225
226
227 ////////////////////////////////////////////////////////
renderPolygon(QColor col,QImage * dst)228 void ScanRender::renderPolygon(QColor col, QImage *dst)
229 ////////////////////////////////////////////////////////
230 {
231 quint32 c = col.rgb();
232 quint32 *bits = (quint32 *)dst->bits();
233 int dw = dst->width();
234 bkScan_t *scan = scLR;
235
236 for (int y = plMinY; y <= plMaxY; y++)
237 {
238 int px1 = scan[y].scan[0];
239 int px2 = scan[y].scan[1];
240
241 if (px1 > px2)
242 {
243 qSwap(px1, px2);
244 }
245
246 if (px1 < 0)
247 {
248 px1 = 0;
249 if (px2 < 0)
250 {
251 continue;
252 }
253 }
254
255 if (px2 >= m_sx)
256 {
257 if (px1 >= m_sx)
258 {
259 continue;
260 }
261 px2 = m_sx - 1;
262 }
263
264 quint32 *pDst = bits + (y * dw) + px1;
265 for (int x = px1; x < px2; x++)
266 {
267 *pDst = c;
268 pDst++;
269 }
270 }
271 }
272
273
274 /////////////////////////////////////////////////////////////
renderPolygonAlpha(QColor col,QImage * dst)275 void ScanRender::renderPolygonAlpha(QColor col, QImage *dst)
276 /////////////////////////////////////////////////////////////
277 {
278 quint32 c = col.rgba();
279 quint32 *bits = (quint32 *)dst->bits();
280 int dw = dst->width();
281 bkScan_t *scan = scLR;
282 float a = qAlpha(c) / 256.0f;
283 int rc = qRed(c);
284 int gc = qGreen(c);
285 int bc = qBlue(c);
286
287 for (int y = plMinY; y <= plMaxY; y++)
288 {
289 int px1 = scan[y].scan[0];
290 int px2 = scan[y].scan[1];
291
292 if (px1 > px2)
293 {
294 qSwap(px1, px2);
295 }
296
297 if (px1 < 0)
298 {
299 px1 = 0;
300 }
301
302 if (px2 >= m_sx)
303 {
304 px2 = m_sx - 1;
305 }
306
307 quint32 *pDst = bits + (y * dw) + px1;
308 for (int x = px1; x < px2; x++)
309 {
310 QRgb rgbd = *pDst;
311
312 *pDst = qRgb(LERP(a, qRed(rgbd), rc),
313 LERP(a, qGreen(rgbd), gc),
314 LERP(a, qBlue(rgbd), bc)
315 );
316 pDst++;
317 }
318 }
319 }
320
setOpacity(float opacity)321 void ScanRender::setOpacity(float opacity)
322 {
323 m_opacity = opacity;
324 }
325
326 /////////////////////////////////////////////////////////
renderPolygon(QImage * dst,QImage * src)327 void ScanRender::renderPolygon(QImage *dst, QImage *src)
328 /////////////////////////////////////////////////////////
329 {
330 if (bBilinear)
331 renderPolygonBI(dst, src);
332 else
333 renderPolygonNI(dst, src);
334 }
335
renderPolygon(int interpolation,QPointF * pts,QImage * pDest,QImage * pSrc,QPointF * uv)336 void ScanRender::renderPolygon(int interpolation, QPointF *pts, QImage *pDest, QImage *pSrc, QPointF *uv)
337 {
338 QPointF Auv = uv[0];
339 QPointF Buv = uv[1];
340 QPointF Cuv = uv[2];
341 QPointF Duv = uv[3];
342
343 if (interpolation < 2)
344 {
345 resetScanPoly(pDest->width(), pDest->height());
346 scanLine(pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y(), 1, 1, 1, 0);
347 scanLine(pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), 1, 0, 0, 0);
348 scanLine(pts[2].x(), pts[2].y(), pts[3].x(), pts[3].y(), 0, 0, 0, 1);
349 scanLine(pts[3].x(), pts[3].y(), pts[0].x(), pts[0].y(), 0, 1, 1, 1);
350 renderPolygon(pDest, pSrc);
351 return;
352 }
353
354 QPointF A = pts[0];
355 QPointF B = pts[1];
356 QPointF C = pts[2];
357 QPointF D = pts[3];
358
359 //p->setPen(Qt::green);
360
361 for (int i = 0; i < interpolation; i++)
362 {
363 QPointF P1 = A + i * (D - A) / interpolation;
364 QPointF P1uv = Auv + i * (Duv - Auv) / interpolation;
365
366 QPointF P2 = B + i * (C - B) / interpolation;
367 QPointF P2uv = Buv + i * (Cuv - Buv) / interpolation;
368
369 QPointF Q1 = A + (i + 1) * (D - A) / interpolation;
370 QPointF Q1uv = Auv + (i + 1) * (Duv - Auv) / interpolation;
371
372 QPointF Q2 = B + (i + 1) * (C - B) / interpolation;
373 QPointF Q2uv = Buv + (i + 1) * (Cuv - Buv) / interpolation;
374
375 for (int j = 0; j < interpolation; j++)
376 {
377 QPointF A1 = P1 + j * (P2 - P1) / interpolation;
378 QPointF A1uv = P1uv + j * (P2uv - P1uv) / interpolation;
379
380 QPointF B1 = P1 + (j + 1) * (P2 - P1) / interpolation;
381 QPointF B1uv = P1uv + (j + 1) * (P2uv - P1uv) / interpolation;
382
383 QPointF C1 = Q1 + (j + 1) * (Q2 - Q1) / interpolation;
384 QPointF C1uv = Q1uv + (j + 1) * (Q2uv - Q1uv) / interpolation;
385
386 QPointF D1 = Q1 + j * (Q2 - Q1) / interpolation;
387 QPointF D1uv = Q1uv + j * (Q2uv - Q1uv) / interpolation;
388
389 resetScanPoly(pDest->width(), pDest->height());
390 scanLine(A1.x(), A1.y(), B1.x(), B1.y(), A1uv.x(), A1uv.y(), B1uv.x(), B1uv.y());
391 scanLine(B1.x(), B1.y(), C1.x(), C1.y(), B1uv.x(), B1uv.y(), C1uv.x(), C1uv.y());
392 scanLine(C1.x(), C1.y(), D1.x(), D1.y(), C1uv.x(), C1uv.y(), D1uv.x(), D1uv.y());
393 scanLine(D1.x(), D1.y(), A1.x(), A1.y(), D1uv.x(), D1uv.y(), A1uv.x(), A1uv.y());
394 renderPolygon(pDest, pSrc);
395
396 //p->drawLine(A1, B1);
397 //p->drawLine(B1, C1);
398 //p->drawLine(C1, D1);
399 //p->drawLine(D1, A1);
400 }
401 }
402 }
403
404 ///////////////////////////////////////////////////////////
renderPolygonNI(QImage * dst,QImage * src)405 void ScanRender::renderPolygonNI(QImage *dst, QImage *src)
406 ///////////////////////////////////////////////////////////
407 {
408 int w = dst->width();
409 int sw = src->width();
410 int sh = src->height();
411 float tsx = src->width() - 1;
412 float tsy = src->height() - 1;
413 const quint32 *bitsSrc = (quint32 *)src->constBits();
414 quint32 *bitsDst = (quint32 *)dst->bits();
415 bkScan_t *scan = scLR;
416 bool bw = src->format() == QImage::Format_Indexed8 || src->format() == QImage::Format_Grayscale8;
417
418 //#pragma omp parallel for
419 for (int y = plMinY; y <= plMaxY; y++)
420 {
421 if (scan[y].scan[0] > scan[y].scan[1])
422 {
423 qSwap(scan[y].scan[0], scan[y].scan[1]);
424 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
425 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
426 }
427
428 int px1 = scan[y].scan[0];
429 int px2 = scan[y].scan[1];
430
431 float dx = px2 - px1;
432 if (dx == 0)
433 continue;
434
435 float duv[2];
436 float uv[2];
437
438 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
439 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
440
441 uv[0] = scan[y].uv[0][0];
442 uv[1] = scan[y].uv[0][1];
443
444 if (px1 < 0)
445 {
446 float m = (float)-px1;
447
448 px1 = 0;
449 uv[0] += duv[0] * m;
450 uv[1] += duv[1] * m;
451 }
452
453 if (px2 >= w)
454 px2 = w - 1;
455
456 uv[0] *= tsx;
457 uv[1] *= tsy;
458
459 duv[0] *= tsx;
460 duv[1] *= tsy;
461
462 quint32 *pDst = bitsDst + (y * w) + px1;
463
464 int fuv[2];
465 int fduv[2];
466
467 fuv[0] = uv[0] * 65536;
468 fuv[1] = uv[1] * 65536;
469
470 fduv[0] = duv[0] * 65536;
471 fduv[1] = duv[1] * 65536;
472
473 fuv[0] = CLAMP(fuv[0], 0, (sw - 1) * 65536.);
474 fuv[1] = CLAMP(fuv[1], 0, (sh - 1) * 65536.);
475
476 if (bw)
477 {
478 for (int x = px1; x < px2; x++)
479 {
480 const uchar *pSrc = (uchar *)bitsSrc + (fuv[0] >> 16) + ((fuv[1] >> 16) * sw);
481 *pDst = qRgb(*pSrc, *pSrc, *pSrc);
482 pDst++;
483
484 fuv[0] += fduv[0];
485 fuv[1] += fduv[1];
486 }
487 }
488 else
489 {
490 for (int x = px1; x < px2; x++)
491 {
492 int offset = (fuv[0] >> 16) + ((fuv[1] >> 16) * sw);
493
494 const quint32 *pSrc = bitsSrc + offset;
495 *pDst = (*pSrc) | (0xFF << 24);
496
497 pDst++;
498
499 fuv[0] += fduv[0];
500 fuv[1] += fduv[1];
501 }
502 }
503 }
504 }
505
506
507 ///////////////////////////////////////////////////////////
renderPolygonBI(QImage * dst,QImage * src)508 void ScanRender::renderPolygonBI(QImage *dst, QImage *src)
509 ///////////////////////////////////////////////////////////
510 {
511 int w = dst->width();
512 int sw = src->width();
513 int sh = src->height();
514 float tsx = src->width() - 1;
515 float tsy = src->height() - 1;
516 const quint32 *bitsSrc = (quint32 *)src->constBits();
517 const uchar *bitsSrc8 = (uchar *)src->constBits();
518 quint32 *bitsDst = (quint32 *)dst->bits();
519 bkScan_t *scan = scLR;
520 bool bw = src->format() == QImage::Format_Indexed8 || src->format() == QImage::Format_Grayscale8;
521
522 #ifdef PARALLEL_OMP
523 #pragma omp parallel for
524 #endif
525 for (int y = plMinY; y <= plMaxY; y++)
526 {
527 if (scan[y].scan[0] > scan[y].scan[1])
528 {
529 qSwap(scan[y].scan[0], scan[y].scan[1]);
530 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
531 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
532 }
533
534 int px1 = scan[y].scan[0];
535 int px2 = scan[y].scan[1];
536
537 float dx = px2 - px1;
538 if (dx == 0)
539 continue;
540
541 float duv[2];
542 float uv[2];
543
544 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
545 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
546
547 uv[0] = scan[y].uv[0][0];
548 uv[1] = scan[y].uv[0][1];
549
550 if (px1 < 0)
551 {
552 float m = (float)-px1;
553
554 px1 = 0;
555 uv[0] += duv[0] * m;
556 uv[1] += duv[1] * m;
557 }
558
559 if (px2 >= w)
560 px2 = w - 1;
561
562 uv[0] *= tsx;
563 uv[1] *= tsy;
564
565 duv[0] *= tsx;
566 duv[1] *= tsy;
567
568 int size = sw * sh;
569
570 quint32 *pDst = bitsDst + (y * w) + px1;
571 if (bw)
572 {
573 for (int x = px1; x < px2; x++)
574 {
575 float x_diff = uv[0] - static_cast<int>(uv[0]);
576 float y_diff = uv[1] - static_cast<int>(uv[1]);
577 float x_1diff = 1 - x_diff;
578 float y_1diff = 1 - y_diff;
579
580 int index = ((int)uv[0] + ((int)uv[1] * sw));
581
582 uchar a = bitsSrc8[index];
583 uchar b = bitsSrc8[(index + 1) % size];
584 uchar c = bitsSrc8[(index + sw) % size];
585 uchar d = bitsSrc8[(index + sw + 1) % size];
586
587 int val = (a&0xff)*(x_1diff)*(y_1diff) + (b&0xff)*(x_diff)*(y_1diff) +
588 (c&0xff)*(y_diff)*(x_1diff) + (d&0xff)*(x_diff*y_diff);
589
590 *pDst = 0xff000000 |
591 ((((int)val)<<16)&0xff0000) |
592 ((((int)val)<<8)&0xff00) |
593 ((int)val) ;
594 pDst++;
595
596 uv[0] += duv[0];
597 uv[1] += duv[1];
598 }
599 }
600 else
601 {
602 for (int x = px1; x < px2; x++)
603 {
604 float x_diff = uv[0] - static_cast<int>(uv[0]);
605 float y_diff = uv[1] - static_cast<int>(uv[1]);
606 float x_1diff = 1 - x_diff;
607 float y_1diff = 1 - y_diff;
608
609 int index = ((int)uv[0] + ((int)uv[1] * sw));
610
611 quint32 a = bitsSrc[index];
612 quint32 b = bitsSrc[(index + 1) % size];
613 quint32 c = bitsSrc[(index + sw) % size];
614 quint32 d = bitsSrc[(index + sw + 1) % size];
615
616 int qxy1 = (x_1diff * y_1diff) * 65536;
617 int qxy2 =(x_diff * y_1diff) * 65536;
618 int qxy = (x_diff * y_diff) * 65536;
619 int qyx1 = (y_diff * x_1diff) * 65536;
620
621 // blue element
622 int blue = ((a&0xff)*(qxy1) + (b&0xff)*(qxy2) + (c&0xff)*(qyx1) + (d&0xff)*(qxy)) >> 16;
623
624 // green element
625 int green = (((a>>8)&0xff)*(qxy1) + ((b>>8)&0xff)*(qxy2) + ((c>>8)&0xff)*(qyx1) + ((d>>8)&0xff)*(qxy)) >> 16;
626
627 // red element
628 int red = (((a>>16)&0xff)*(qxy1) + ((b>>16)&0xff)*(qxy2) +((c>>16)&0xff)*(qyx1) + ((d>>16)&0xff)*(qxy)) >> 16;
629
630 *pDst = 0xff000000 | (((red)<<16)&0xff0000) | (((green)<<8)&0xff00) | (blue);
631
632 pDst++;
633
634 uv[0] += duv[0];
635 uv[1] += duv[1];
636 }
637 }
638 }
639 }
640
renderPolygonAlpha(QImage * dst,QImage * src)641 void ScanRender::renderPolygonAlpha(QImage *dst, QImage *src)
642 {
643 if (bBilinear)
644 renderPolygonAlphaBI(dst, src);
645 else
646 renderPolygonAlphaNI(dst, src);
647 }
648
649
renderPolygonAlphaBI(QImage * dst,QImage * src)650 void ScanRender::renderPolygonAlphaBI(QImage *dst, QImage *src)
651 {
652 int w = dst->width();
653 int sw = src->width();
654 int sh = src->height();
655 float tsx = src->width() - 1;
656 float tsy = src->height() - 1;
657 const quint32 *bitsSrc = (quint32 *)src->constBits();
658 quint32 *bitsDst = (quint32 *)dst->bits();
659 bkScan_t *scan = scLR;
660 bool bw = src->format() == QImage::Format_Indexed8;
661 float opacity = (m_opacity / 65536.) * 0.00390625f;
662
663 #ifdef PARALLEL_OMP
664 #pragma omp parallel for shared(bitsDst, bitsSrc, scan, tsx, tsy, w, sw)
665 #endif
666 for (int y = plMinY; y <= plMaxY; y++)
667 {
668 if (scan[y].scan[0] > scan[y].scan[1])
669 {
670 qSwap(scan[y].scan[0], scan[y].scan[1]);
671 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
672 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
673 }
674
675 int px1 = scan[y].scan[0];
676 int px2 = scan[y].scan[1];
677
678 float dx = px2 - px1;
679 if (dx == 0)
680 continue;
681
682 float duv[2];
683 float uv[2];
684
685 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
686 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
687
688 uv[0] = scan[y].uv[0][0];
689 uv[1] = scan[y].uv[0][1];
690
691 if (px1 < 0)
692 {
693 float m = (float)-px1;
694
695 px1 = 0;
696 uv[0] += duv[0] * m;
697 uv[1] += duv[1] * m;
698 }
699
700 if (px2 >= w)
701 px2 = w - 1;
702
703 uv[0] *= tsx;
704 uv[1] *= tsy;
705
706 duv[0] *= tsx;
707 duv[1] *= tsy;
708
709 int size = sw * sh;
710
711 quint32 *pDst = bitsDst + (y * w) + px1;
712 if (bw)
713 {
714 /*
715 for (int x = px1; x < px2; x++)
716 {
717 float x_diff = uv[0] - static_cast<int>(uv[0]);
718 float y_diff = uv[1] - static_cast<int>(uv[1]);
719 float x_1diff = 1 - x_diff;
720 float y_1diff = 1 - y_diff;
721
722 int index = ((int)uv[0] + ((int)uv[1] * sw));
723
724 uchar a = bitsSrc8[index];
725 uchar b = bitsSrc8[(index + 1) % size];
726 uchar c = bitsSrc8[(index + sw) % size];
727 uchar d = bitsSrc8[(index + sw + 1) % size];
728
729 int val = (a&0xff)*(x_1diff)*(y_1diff) + (b&0xff)*(x_diff)*(y_1diff) +
730 (c&0xff)*(y_diff)*(x_1diff) + (d&0xff)*(x_diff*y_diff);
731
732
733 *pDst = 0xff000000 |
734 ((((int)val)<<16)&0xff0000) |
735 ((((int)val)<<8)&0xff00) |
736 ((int)val) ;
737 pDst++;
738
739 uv[0] += duv[0];
740 uv[1] += duv[1];
741 }
742 */
743 }
744 else
745 {
746 for (int x = px1; x < px2; x++)
747 {
748 float x_diff = uv[0] - static_cast<int>(uv[0]);
749 float y_diff = uv[1] - static_cast<int>(uv[1]);
750 float x_1diff = 1 - x_diff;
751 float y_1diff = 1 - y_diff;
752
753 int index = ((int)uv[0] + ((int)uv[1] * sw));
754
755 quint32 a = bitsSrc[index];
756 quint32 b = bitsSrc[(index + 1) % size];
757 quint32 c = bitsSrc[(index + sw) % size];
758 quint32 d = bitsSrc[(index + sw + 1) % size];
759
760 int x1y1 = (x_1diff * y_1diff) * 65536;
761 int xy = (x_diff * y_diff) * 65536;
762 int x1y = (y_diff * x_1diff) * 65536;
763 int xy1 = (x_diff *y_1diff) * 65536;
764
765 float alpha = ((((a>>24)&0xff)*(x1y1) + ((b>>24)&0xff)*(xy1) +
766 ((c>>24)&0xff)*(x1y) + ((d>>24)&0xff)*(xy)) * opacity);
767
768 if (alpha > 0.00390625f) // > 1 / 256.
769 {
770 // blue element
771 int blue = ((a&0xff)*(x1y1) + (b&0xff)* (xy1) +
772 (c&0xff)*(x1y) + (d&0xff)*(xy)) >> 16;
773
774 // green element
775 int green = (((a>>8)&0xff)*(x1y1) + ((b>>8)&0xff)*(xy1) +
776 ((c>>8)&0xff)*(x1y) + ((d>>8)&0xff)*(xy)) >> 16;
777
778 // red element
779 int red = (((a>>16)&0xff)*(x1y1) + ((b>>16)&0xff)*(xy1) +
780 ((c>>16)&0xff)*(x1y) + ((d>>16)&0xff)*(xy)) >> 16;
781
782 int rd = qRed(*pDst);
783 int gd = qGreen(*pDst);
784 int bd = qBlue(*pDst);
785
786 *pDst = qRgb(LERP(alpha, rd, red), LERP(alpha, gd, green), LERP(alpha, bd, blue));
787 }
788
789 pDst++;
790
791 uv[0] += duv[0];
792 uv[1] += duv[1];
793 }
794 }
795 }
796 }
797
798
799 ////////////////////////////////////////////////////////////////
renderPolygonAlphaNI(QImage * dst,QImage * src)800 void ScanRender::renderPolygonAlphaNI(QImage *dst, QImage *src)
801 ////////////////////////////////////////////////////////////////
802 {
803 int w = dst->width();
804 int sw = src->width();
805 float tsx = src->width() - 1;
806 float tsy = src->height() - 1;
807 const quint32 *bitsSrc = (quint32 *)src->constBits();
808 quint32 *bitsDst = (quint32 *)dst->bits();
809 bkScan_t *scan = scLR;
810 float opacity = 0.00390625f * m_opacity;
811
812 #ifdef PARALLEL_OMP
813 #pragma omp parallel for shared(bitsDst, bitsSrc, scan, tsx, tsy, w, sw)
814 #endif
815 for (int y = plMinY; y <= plMaxY; y++)
816 {
817 if (scan[y].scan[0] > scan[y].scan[1])
818 {
819 qSwap(scan[y].scan[0], scan[y].scan[1]);
820 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
821 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
822 }
823
824 int px1 = scan[y].scan[0];
825 int px2 = scan[y].scan[1];
826
827 float dx = px2 - px1;
828 if (dx == 0)
829 continue;
830
831 float duv[2];
832 float uv[2];
833
834 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
835 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
836
837 uv[0] = scan[y].uv[0][0];
838 uv[1] = scan[y].uv[0][1];
839
840 if (px1 < 0)
841 {
842 float m = (float)-px1;
843
844 px1 = 0;
845 uv[0] += duv[0] * m;
846 uv[1] += duv[1] * m;
847 }
848
849 if (px2 >= w)
850 px2 = w - 1;
851
852 quint32 *pDst = bitsDst + (y * w) + px1;
853
854 uv[0] *= tsx;
855 uv[1] *= tsy;
856
857 duv[0] *= tsx;
858 duv[1] *= tsy;
859
860 for (int x = px1; x < px2; x++)
861 {
862 const quint32 *pSrc = bitsSrc + ((int)(uv[0])) + ((int)(uv[1]) * sw);
863 QRgb rgbs = *pSrc;
864 QRgb rgbd = *pDst;
865 float a = qAlpha(*pSrc) * opacity;
866
867 if (a > 0.00390625f)
868 {
869 *pDst = qRgb(LERP(a, qRed(rgbd), qRed(rgbs)),
870 LERP(a, qGreen(rgbd), qGreen(rgbs)),
871 LERP(a, qBlue(rgbd), qBlue(rgbs))
872 );
873 }
874 pDst++;
875
876 uv[0] += duv[0];
877 uv[1] += duv[1];
878 }
879 }
880 }
881
882 #pragma GCC diagnostic pop
883