Make QRegion not need to be friends with QVector
[profile/ivi/qtbase.git] / src / gui / painting / qimagescale.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <private/qimagescale_p.h>
42 #include <private/qdrawhelper_p.h>
43
44 #include "qimage.h"
45 #include "qcolor.h"
46
47 QT_BEGIN_NAMESPACE
48
49 namespace QImageScale {
50     struct QImageScaleInfo;
51 }
52
53 typedef void (*qt_qimageScaleFunc)(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
54                                    int dxx, int dyy, int dx, int dy, int dw,
55                                    int dh, int dow, int sow);
56
57 static void qt_qimageScaleAARGB(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
58                          int dxx, int dyy, int dx, int dy, int dw,
59                          int dh, int dow, int sow);
60
61 static void qt_qimageScaleAARGBA(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
62                           int dxx, int dyy, int dx, int dy, int dw,
63                           int dh, int dow, int sow);
64
65 qt_qimageScaleFunc qt_qimageScaleArgb = qt_qimageScaleAARGBA;
66 qt_qimageScaleFunc qt_qimageScaleRgb  = qt_qimageScaleAARGB;
67
68
69 /*
70  * Copyright (C) 2004, 2005 Daniel M. Duley
71  *
72  * Redistribution and use in source and binary forms, with or without
73  * modification, are permitted provided that the following conditions
74  * are met:
75  *
76  * 1. Redistributions of source code must retain the above copyright
77  *    notice, this list of conditions and the following disclaimer.
78  * 2. Redistributions in binary form must reproduce the above copyright
79  *    notice, this list of conditions and the following disclaimer in the
80  *    documentation and/or other materials provided with the distribution.
81  *
82  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
83  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
84  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
85  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
86  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
87  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
88  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
89  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
90  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
91  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
92  *
93  */
94
95 /* OTHER CREDITS:
96  *
97  * This is the normal smoothscale method, based on Imlib2's smoothscale.
98  *
99  * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
100  * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
101  * C algorithm and it ran at about the same speed as my MMX optimized one...
102  * Finally I ported Imlib's MMX version and it ran in less than half the
103  * time as my MMX algorithm, (taking only a quarter of the time Qt does).
104  * After further optimization it seems to run at around 1/6th.
105  *
106  * Changes include formatting, namespaces and other C++'ings, removal of old
107  * #ifdef'ed code, and removal of unneeded border calculation code.
108  *
109  * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
110  * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
111  * (C) Daniel M. Duley.
112  */
113
114
115 namespace QImageScale {
116     struct QImageScaleInfo {
117         int *xpoints;
118         unsigned int **ypoints;
119         int *xapoints, *yapoints;
120         int xup_yup;
121     };
122
123     unsigned int** qimageCalcYPoints(unsigned int *src, int sw, int sh,
124                                      int dh);
125     int* qimageCalcXPoints(int sw, int dw);
126     int* qimageCalcApoints(int s, int d, int up);
127     QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
128     QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh,
129                                          int dw, int dh, char aa);
130 }
131
132 using namespace QImageScale;
133
134 //
135 // Code ported from Imlib...
136 //
137
138 // FIXME: replace with qRed, etc... These work on pointers to pixels, not
139 // pixel values
140 #define A_VAL(p) (qAlpha(*p))
141 #define R_VAL(p) (qRed(*p))
142 #define G_VAL(p) (qGreen(*p))
143 #define B_VAL(p) (qBlue(*p))
144
145 #define INV_XAP                   (256 - xapoints[x])
146 #define XAP                       (xapoints[x])
147 #define INV_YAP                   (256 - yapoints[dyy + y])
148 #define YAP                       (yapoints[dyy + y])
149
150 unsigned int** QImageScale::qimageCalcYPoints(unsigned int *src,
151                                               int sw, int sh, int dh)
152 {
153     unsigned int **p;
154     int i, j = 0;
155     int val, inc, rv = 0;
156
157     if(dh < 0){
158         dh = -dh;
159         rv = 1;
160     }
161     p = new unsigned int* [dh+1];
162
163     int up = qAbs(dh) >= sh;
164     val = up ? 0x8000 * sh / dh - 0x8000 : 0;
165     inc = (sh << 16) / dh;
166     for(i = 0; i < dh; i++){
167         p[j++] = src + qMax(0, val >> 16) * sw;
168         val += inc;
169     }
170     if(rv){
171         for(i = dh / 2; --i >= 0; ){
172             unsigned int *tmp = p[i];
173             p[i] = p[dh - i - 1];
174             p[dh - i - 1] = tmp;
175         }
176     }
177     return(p);
178 }
179
180 int* QImageScale::qimageCalcXPoints(int sw, int dw)
181 {
182     int *p, i, j = 0;
183     int val, inc, rv = 0;
184
185     if(dw < 0){
186         dw = -dw;
187         rv = 1;
188     }
189     p = new int[dw+1];
190
191     int up = qAbs(dw) >= sw;
192     val = up ? 0x8000 * sw / dw - 0x8000 : 0;
193     inc = (sw << 16) / dw;
194     for(i = 0; i < dw; i++){
195         p[j++] = qMax(0, val >> 16);
196         val += inc;
197     }
198
199     if(rv){
200         for(i = dw / 2; --i >= 0; ){
201             int tmp = p[i];
202             p[i] = p[dw - i - 1];
203             p[dw - i - 1] = tmp;
204         }
205     }
206    return(p);
207 }
208
209 int* QImageScale::qimageCalcApoints(int s, int d, int up)
210 {
211     int *p, i, j = 0, rv = 0;
212
213     if(d < 0){
214         rv = 1;
215         d = -d;
216     }
217     p = new int[d];
218
219     /* scaling up */
220     if(up){
221         int val, inc;
222
223         val = 0x8000 * s / d - 0x8000;
224         inc = (s << 16) / d;
225         for(i = 0; i < d; i++){
226             int pos = val >> 16;
227             if (pos < 0)
228                 p[j++] = 0;
229             else if (pos >= (s - 1))
230                 p[j++] = 0;
231             else
232                 p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
233             val += inc;
234         }
235     }
236     /* scaling down */
237     else{
238         int val, inc, ap, Cp;
239         val = 0;
240         inc = (s << 16) / d;
241         Cp = ((d << 14) / s) + 1;
242         for(i = 0; i < d; i++){
243             ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
244             p[j] = ap | (Cp << 16);
245             j++;
246             val += inc;
247         }
248     }
249     if(rv){
250         int tmp;
251         for(i = d / 2; --i >= 0; ){
252             tmp = p[i];
253             p[i] = p[d - i - 1];
254             p[d - i - 1] = tmp;
255         }
256     }
257     return(p);
258 }
259
260 QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
261 {
262     if(isi){
263         delete[] isi->xpoints;
264         delete[] isi->ypoints;
265         delete[] isi->xapoints;
266         delete[] isi->yapoints;
267         delete isi;
268     }
269     return 0;
270 }
271
272 QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
273                                                   int sw, int sh,
274                                                   int dw, int dh, char aa)
275 {
276     QImageScaleInfo *isi;
277     int scw, sch;
278
279     scw = dw * qlonglong(img.width()) / sw;
280     sch = dh * qlonglong(img.height()) / sh;
281
282     isi = new QImageScaleInfo;
283     if(!isi)
284         return 0;
285     memset(isi, 0, sizeof(QImageScaleInfo));
286
287     isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
288
289     isi->xpoints = qimageCalcXPoints(img.width(), scw);
290     if(!isi->xpoints)
291         return(qimageFreeScaleInfo(isi));
292     isi->ypoints = qimageCalcYPoints((unsigned int *)img.scanLine(0),
293                                      img.bytesPerLine() / 4, img.height(), sch);
294     if (!isi->ypoints)
295         return(qimageFreeScaleInfo(isi));
296     if(aa) {
297         isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
298         if(!isi->xapoints)
299             return(qimageFreeScaleInfo(isi));
300         isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
301         if(!isi->yapoints)
302             return(qimageFreeScaleInfo(isi));
303     }
304     return(isi);
305 }
306
307 /* FIXME: NEED to optimize ScaleAARGBA - currently its "ok" but needs work*/
308
309 /* scale by area sampling */
310 static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
311                                  int dxx, int dyy, int dx, int dy, int dw,
312                                  int dh, int dow, int sow)
313 {
314     unsigned int *sptr, *dptr;
315     int x, y, end;
316     unsigned int **ypoints = isi->ypoints;
317     int *xpoints = isi->xpoints;
318     int *xapoints = isi->xapoints;
319     int *yapoints = isi->yapoints;
320
321     end = dxx + dw;
322     /* scaling up both ways */
323     if(isi->xup_yup == 3){
324         /* go through every scanline in the output buffer */
325         for(y = 0; y < dh; y++){
326             /* calculate the source line we'll scan from */
327             dptr = dest + dx + ((y + dy) * dow);
328             sptr = ypoints[dyy + y];
329             if(YAP > 0){
330                 for(x = dxx; x < end; x++){
331                     int r, g, b, a;
332                     int rr, gg, bb, aa;
333                     unsigned int *pix;
334
335                     if(XAP > 0){
336                         pix = ypoints[dyy + y] + xpoints[x];
337                         r = R_VAL(pix) * INV_XAP;
338                         g = G_VAL(pix) * INV_XAP;
339                         b = B_VAL(pix) * INV_XAP;
340                         a = A_VAL(pix) * INV_XAP;
341                         pix++;
342                         r += R_VAL(pix) * XAP;
343                         g += G_VAL(pix) * XAP;
344                         b += B_VAL(pix) * XAP;
345                         a += A_VAL(pix) * XAP;
346                         pix += sow;
347                         rr = R_VAL(pix) * XAP;
348                         gg = G_VAL(pix) * XAP;
349                         bb = B_VAL(pix) * XAP;
350                         aa = A_VAL(pix) * XAP;
351                         pix--;
352                         rr += R_VAL(pix) * INV_XAP;
353                         gg += G_VAL(pix) * INV_XAP;
354                         bb += B_VAL(pix) * INV_XAP;
355                         aa += A_VAL(pix) * INV_XAP;
356                         r = ((rr * YAP) + (r * INV_YAP)) >> 16;
357                         g = ((gg * YAP) + (g * INV_YAP)) >> 16;
358                         b = ((bb * YAP) + (b * INV_YAP)) >> 16;
359                         a = ((aa * YAP) + (a * INV_YAP)) >> 16;
360                         *dptr++ = qRgba(r, g, b, a);
361                     }
362                     else{
363                         pix = ypoints[dyy + y] + xpoints[x];
364                         r = R_VAL(pix) * INV_YAP;
365                         g = G_VAL(pix) * INV_YAP;
366                         b = B_VAL(pix) * INV_YAP;
367                         a = A_VAL(pix) * INV_YAP;
368                         pix += sow;
369                         r += R_VAL(pix) * YAP;
370                         g += G_VAL(pix) * YAP;
371                         b += B_VAL(pix) * YAP;
372                         a += A_VAL(pix) * YAP;
373                         r >>= 8;
374                         g >>= 8;
375                         b >>= 8;
376                         a >>= 8;
377                         *dptr++ = qRgba(r, g, b, a);
378                     }
379                 }
380             }
381             else{
382                 for(x = dxx; x < end; x++){
383                     int r, g, b, a;
384                     unsigned int *pix;
385
386                     if(XAP > 0){
387                         pix = ypoints[dyy + y] + xpoints[x];
388                         r = R_VAL(pix) * INV_XAP;
389                         g = G_VAL(pix) * INV_XAP;
390                         b = B_VAL(pix) * INV_XAP;
391                         a = A_VAL(pix) * INV_XAP;
392                         pix++;
393                         r += R_VAL(pix) * XAP;
394                         g += G_VAL(pix) * XAP;
395                         b += B_VAL(pix) * XAP;
396                         a += A_VAL(pix) * XAP;
397                         r >>= 8;
398                         g >>= 8;
399                         b >>= 8;
400                         a >>= 8;
401                         *dptr++ = qRgba(r, g, b, a);
402                     }
403                     else
404                         *dptr++ = sptr[xpoints[x] ];
405                 }
406             }
407         }
408     }
409     /* if we're scaling down vertically */
410     else if(isi->xup_yup == 1){
411         /*\ 'Correct' version, with math units prepared for MMXification \*/
412         int Cy, j;
413         unsigned int *pix;
414         int r, g, b, a, rr, gg, bb, aa;
415         int yap;
416
417         /* go through every scanline in the output buffer */
418         for(y = 0; y < dh; y++){
419             Cy = YAP >> 16;
420             yap = YAP & 0xffff;
421
422             dptr = dest + dx + ((y + dy) * dow);
423             for(x = dxx; x < end; x++){
424                 pix = ypoints[dyy + y] + xpoints[x];
425                 r = R_VAL(pix) * yap;
426                 g = G_VAL(pix) * yap;
427                 b = B_VAL(pix) * yap;
428                 a = A_VAL(pix) * yap;
429                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
430                     pix += sow;
431                     r += R_VAL(pix) * Cy;
432                     g += G_VAL(pix) * Cy;
433                     b += B_VAL(pix) * Cy;
434                     a += A_VAL(pix) * Cy;
435                 }
436                 if(j > 0){
437                     pix += sow;
438                     r += R_VAL(pix) * j;
439                     g += G_VAL(pix) * j;
440                     b += B_VAL(pix) * j;
441                     a += A_VAL(pix) * j;
442                 }
443                 if(XAP > 0){
444                     pix = ypoints[dyy + y] + xpoints[x] + 1;
445                     rr = R_VAL(pix) * yap;
446                     gg = G_VAL(pix) * yap;
447                     bb = B_VAL(pix) * yap;
448                     aa = A_VAL(pix) * yap;
449                     for(j = (1 << 14) - yap; j > Cy; j -= Cy){
450                         pix += sow;
451                         rr += R_VAL(pix) * Cy;
452                         gg += G_VAL(pix) * Cy;
453                         bb += B_VAL(pix) * Cy;
454                         aa += A_VAL(pix) * Cy;
455                     }
456                     if(j > 0){
457                         pix += sow;
458                         rr += R_VAL(pix) * j;
459                         gg += G_VAL(pix) * j;
460                         bb += B_VAL(pix) * j;
461                         aa += A_VAL(pix) * j;
462                     }
463                     r = r * INV_XAP;
464                     g = g * INV_XAP;
465                     b = b * INV_XAP;
466                     a = a * INV_XAP;
467                     r = (r + ((rr * XAP))) >> 12;
468                     g = (g + ((gg * XAP))) >> 12;
469                     b = (b + ((bb * XAP))) >> 12;
470                     a = (a + ((aa * XAP))) >> 12;
471                 }
472                 else{
473                     r >>= 4;
474                     g >>= 4;
475                     b >>= 4;
476                     a >>= 4;
477                 }
478                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
479                 dptr++;
480             }
481         }
482     }
483     /* if we're scaling down horizontally */
484     else if(isi->xup_yup == 2){
485         /*\ 'Correct' version, with math units prepared for MMXification \*/
486         int Cx, j;
487         unsigned int *pix;
488         int r, g, b, a, rr, gg, bb, aa;
489         int xap;
490
491         /* go through every scanline in the output buffer */
492         for(y = 0; y < dh; y++){
493             dptr = dest + dx + ((y + dy) * dow);
494             for(x = dxx; x < end; x++){
495                 Cx = XAP >> 16;
496                 xap = XAP & 0xffff;
497
498                 pix = ypoints[dyy + y] + xpoints[x];
499                 r = R_VAL(pix) * xap;
500                 g = G_VAL(pix) * xap;
501                 b = B_VAL(pix) * xap;
502                 a = A_VAL(pix) * xap;
503                 for(j = (1 << 14) - xap; j > Cx; j -= Cx){
504                     pix++;
505                     r += R_VAL(pix) * Cx;
506                     g += G_VAL(pix) * Cx;
507                     b += B_VAL(pix) * Cx;
508                     a += A_VAL(pix) * Cx;
509                 }
510                 if(j > 0){
511                     pix++;
512                     r += R_VAL(pix) * j;
513                     g += G_VAL(pix) * j;
514                     b += B_VAL(pix) * j;
515                     a += A_VAL(pix) * j;
516                 }
517                 if(YAP > 0){
518                     pix = ypoints[dyy + y] + xpoints[x] + sow;
519                     rr = R_VAL(pix) * xap;
520                     gg = G_VAL(pix) * xap;
521                     bb = B_VAL(pix) * xap;
522                     aa = A_VAL(pix) * xap;
523                     for(j = (1 << 14) - xap; j > Cx; j -= Cx){
524                         pix++;
525                         rr += R_VAL(pix) * Cx;
526                         gg += G_VAL(pix) * Cx;
527                         bb += B_VAL(pix) * Cx;
528                         aa += A_VAL(pix) * Cx;
529                     }
530                     if(j > 0){
531                         pix++;
532                         rr += R_VAL(pix) * j;
533                         gg += G_VAL(pix) * j;
534                         bb += B_VAL(pix) * j;
535                         aa += A_VAL(pix) * j;
536                     }
537                     r = r * INV_YAP;
538                     g = g * INV_YAP;
539                     b = b * INV_YAP;
540                     a = a * INV_YAP;
541                     r = (r + ((rr * YAP))) >> 12;
542                     g = (g + ((gg * YAP))) >> 12;
543                     b = (b + ((bb * YAP))) >> 12;
544                     a = (a + ((aa * YAP))) >> 12;
545                 }
546                 else{
547                     r >>= 4;
548                     g >>= 4;
549                     b >>= 4;
550                     a >>= 4;
551                 }
552                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
553                 dptr++;
554             }
555         }
556     }
557     /* if we're scaling down horizontally & vertically */
558     else{
559         /*\ 'Correct' version, with math units prepared for MMXification:
560          |*|  The operation 'b = (b * c) >> 16' translates to pmulhw,
561          |*|  so the operation 'b = (b * c) >> d' would translate to
562          |*|  psllw (16 - d), %mmb; pmulh %mmc, %mmb
563          \*/
564         int Cx, Cy, i, j;
565         unsigned int *pix;
566         int a, r, g, b, ax, rx, gx, bx;
567         int xap, yap;
568
569         for(y = 0; y < dh; y++){
570             Cy = YAP >> 16;
571             yap = YAP & 0xffff;
572
573             dptr = dest + dx + ((y + dy) * dow);
574             for(x = dxx; x < end; x++){
575                 Cx = XAP >> 16;
576                 xap = XAP & 0xffff;
577
578                 sptr = ypoints[dyy + y] + xpoints[x];
579                 pix = sptr;
580                 sptr += sow;
581                 rx = R_VAL(pix) * xap;
582                 gx = G_VAL(pix) * xap;
583                 bx = B_VAL(pix) * xap;
584                 ax = A_VAL(pix) * xap;
585
586                 pix++;
587                 for(i = (1 << 14) - xap; i > Cx; i -= Cx){
588                     rx += R_VAL(pix) * Cx;
589                     gx += G_VAL(pix) * Cx;
590                     bx += B_VAL(pix) * Cx;
591                     ax += A_VAL(pix) * Cx;
592                     pix++;
593                 }
594                 if(i > 0){
595                     rx += R_VAL(pix) * i;
596                     gx += G_VAL(pix) * i;
597                     bx += B_VAL(pix) * i;
598                     ax += A_VAL(pix) * i;
599                 }
600
601                 r = (rx >> 5) * yap;
602                 g = (gx >> 5) * yap;
603                 b = (bx >> 5) * yap;
604                 a = (ax >> 5) * yap;
605
606                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
607                     pix = sptr;
608                     sptr += sow;
609                     rx = R_VAL(pix) * xap;
610                     gx = G_VAL(pix) * xap;
611                     bx = B_VAL(pix) * xap;
612                     ax = A_VAL(pix) * xap;
613                     pix++;
614                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
615                         rx += R_VAL(pix) * Cx;
616                         gx += G_VAL(pix) * Cx;
617                         bx += B_VAL(pix) * Cx;
618                         ax += A_VAL(pix) * Cx;
619                         pix++;
620                     }
621                     if(i > 0){
622                         rx += R_VAL(pix) * i;
623                         gx += G_VAL(pix) * i;
624                         bx += B_VAL(pix) * i;
625                         ax += A_VAL(pix) * i;
626                     }
627
628                     r += (rx >> 5) * Cy;
629                     g += (gx >> 5) * Cy;
630                     b += (bx >> 5) * Cy;
631                     a += (ax >> 5) * Cy;
632                 }
633                 if(j > 0){
634                     pix = sptr;
635                     sptr += sow;
636                     rx = R_VAL(pix) * xap;
637                     gx = G_VAL(pix) * xap;
638                     bx = B_VAL(pix) * xap;
639                     ax = A_VAL(pix) * xap;
640                     pix++;
641                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
642                         rx += R_VAL(pix) * Cx;
643                         gx += G_VAL(pix) * Cx;
644                         bx += B_VAL(pix) * Cx;
645                         ax += A_VAL(pix) * Cx;
646                         pix++;
647                     }
648                     if(i > 0){
649                         rx += R_VAL(pix) * i;
650                         gx += G_VAL(pix) * i;
651                         bx += B_VAL(pix) * i;
652                         ax += A_VAL(pix) * i;
653                     }
654
655                     r += (rx >> 5) * j;
656                     g += (gx >> 5) * j;
657                     b += (bx >> 5) * j;
658                     a += (ax >> 5) * j;
659                 }
660
661                 *dptr = qRgba(r >> 23, g >> 23, b >> 23, a >> 23);
662                 dptr++;
663             }
664         }
665     }
666 }
667
668 /* scale by area sampling - IGNORE the ALPHA byte*/
669 static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
670                                 int dxx, int dyy, int dx, int dy, int dw,
671                                 int dh, int dow, int sow)
672 {
673     unsigned int *sptr, *dptr;
674     int x, y, end;
675     unsigned int **ypoints = isi->ypoints;
676     int *xpoints = isi->xpoints;
677     int *xapoints = isi->xapoints;
678     int *yapoints = isi->yapoints;
679
680     end = dxx + dw;
681     /* scaling up both ways */
682     if(isi->xup_yup == 3){
683         /* go through every scanline in the output buffer */
684         for(y = 0; y < dh; y++){
685             /* calculate the source line we'll scan from */
686             dptr = dest + dx + ((y + dy) * dow);
687             sptr = ypoints[dyy + y];
688             if(YAP > 0){
689                 for(x = dxx; x < end; x++){
690                     int r = 0, g = 0, b = 0;
691                     int rr = 0, gg = 0, bb = 0;
692                     unsigned int *pix;
693
694                     if(XAP > 0){
695                         pix = ypoints[dyy + y] + xpoints[x];
696                         r = R_VAL(pix) * INV_XAP;
697                         g = G_VAL(pix) * INV_XAP;
698                         b = B_VAL(pix) * INV_XAP;
699                         pix++;
700                         r += R_VAL(pix) * XAP;
701                         g += G_VAL(pix) * XAP;
702                         b += B_VAL(pix) * XAP;
703                         pix += sow;
704                         rr = R_VAL(pix) * XAP;
705                         gg = G_VAL(pix) * XAP;
706                         bb = B_VAL(pix) * XAP;
707                         pix --;
708                         rr += R_VAL(pix) * INV_XAP;
709                         gg += G_VAL(pix) * INV_XAP;
710                         bb += B_VAL(pix) * INV_XAP;
711                         r = ((rr * YAP) + (r * INV_YAP)) >> 16;
712                         g = ((gg * YAP) + (g * INV_YAP)) >> 16;
713                         b = ((bb * YAP) + (b * INV_YAP)) >> 16;
714                         *dptr++ = qRgba(r, g, b, 0xff);
715                     }
716                     else{
717                         pix = ypoints[dyy + y] + xpoints[x];
718                         r = R_VAL(pix) * INV_YAP;
719                         g = G_VAL(pix) * INV_YAP;
720                         b = B_VAL(pix) * INV_YAP;
721                         pix += sow;
722                         r += R_VAL(pix) * YAP;
723                         g += G_VAL(pix) * YAP;
724                         b += B_VAL(pix) * YAP;
725                         r >>= 8;
726                         g >>= 8;
727                         b >>= 8;
728                         *dptr++ = qRgba(r, g, b, 0xff);
729                     }
730                 }
731             }
732             else{
733                 for(x = dxx; x < end; x++){
734                     int r = 0, g = 0, b = 0;
735                     unsigned int *pix;
736
737                     if(XAP > 0){
738                         pix = ypoints[dyy + y] + xpoints[x];
739                         r = R_VAL(pix) * INV_XAP;
740                         g = G_VAL(pix) * INV_XAP;
741                         b = B_VAL(pix) * INV_XAP;
742                         pix++;
743                         r += R_VAL(pix) * XAP;
744                         g += G_VAL(pix) * XAP;
745                         b += B_VAL(pix) * XAP;
746                         r >>= 8;
747                         g >>= 8;
748                         b >>= 8;
749                         *dptr++ = qRgba(r, g, b, 0xff);
750                     }
751                     else
752                         *dptr++ = sptr[xpoints[x] ];
753                 }
754             }
755         }
756     }
757     /* if we're scaling down vertically */
758     else if(isi->xup_yup == 1){
759         /*\ 'Correct' version, with math units prepared for MMXification \*/
760         int Cy, j;
761         unsigned int *pix;
762         int r, g, b, rr, gg, bb;
763         int yap;
764
765         /* go through every scanline in the output buffer */
766         for(y = 0; y < dh; y++){
767             Cy = YAP >> 16;
768             yap = YAP & 0xffff;
769
770             dptr = dest + dx + ((y + dy) * dow);
771             for(x = dxx; x < end; x++){
772                 pix = ypoints[dyy + y] + xpoints[x];
773                 r = R_VAL(pix) * yap;
774                 g = G_VAL(pix) * yap;
775                 b = B_VAL(pix) * yap;
776                 pix += sow;
777                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
778                     r += R_VAL(pix) * Cy;
779                     g += G_VAL(pix) * Cy;
780                     b += B_VAL(pix) * Cy;
781                     pix += sow;
782                 }
783                 if(j > 0){
784                     r += R_VAL(pix) * j;
785                     g += G_VAL(pix) * j;
786                     b += B_VAL(pix) * j;
787                 }
788                 if(XAP > 0){
789                     pix = ypoints[dyy + y] + xpoints[x] + 1;
790                     rr = R_VAL(pix) * yap;
791                     gg = G_VAL(pix) * yap;
792                     bb = B_VAL(pix) * yap;
793                     pix += sow;
794                     for(j = (1 << 14) - yap; j > Cy; j -= Cy){
795                         rr += R_VAL(pix) * Cy;
796                         gg += G_VAL(pix) * Cy;
797                         bb += B_VAL(pix) * Cy;
798                         pix += sow;
799                     }
800                     if(j > 0){
801                         rr += R_VAL(pix) * j;
802                         gg += G_VAL(pix) * j;
803                         bb += B_VAL(pix) * j;
804                     }
805                     r = r * INV_XAP;
806                     g = g * INV_XAP;
807                     b = b * INV_XAP;
808                     r = (r + ((rr * XAP))) >> 12;
809                     g = (g + ((gg * XAP))) >> 12;
810                     b = (b + ((bb * XAP))) >> 12;
811                 }
812                 else{
813                     r >>= 4;
814                     g >>= 4;
815                     b >>= 4;
816                 }
817                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
818                 dptr++;
819             }
820         }
821     }
822     /* if we're scaling down horizontally */
823     else if(isi->xup_yup == 2){
824         /*\ 'Correct' version, with math units prepared for MMXification \*/
825         int Cx, j;
826         unsigned int *pix;
827         int r, g, b, rr, gg, bb;
828         int xap;
829
830         /* go through every scanline in the output buffer */
831         for(y = 0; y < dh; y++){
832             dptr = dest + dx + ((y + dy) * dow);
833             for(x = dxx; x < end; x++){
834                 Cx = XAP >> 16;
835                 xap = XAP & 0xffff;
836
837                 pix = ypoints[dyy + y] + xpoints[x];
838                 r = R_VAL(pix) * xap;
839                 g = G_VAL(pix) * xap;
840                 b = B_VAL(pix) * xap;
841                 pix++;
842                 for(j = (1 << 14) - xap; j > Cx; j -= Cx){
843                     r += R_VAL(pix) * Cx;
844                     g += G_VAL(pix) * Cx;
845                     b += B_VAL(pix) * Cx;
846                     pix++;
847                 }
848                 if(j > 0){
849                     r += R_VAL(pix) * j;
850                     g += G_VAL(pix) * j;
851                     b += B_VAL(pix) * j;
852                 }
853                 if(YAP > 0){
854                     pix = ypoints[dyy + y] + xpoints[x] + sow;
855                     rr = R_VAL(pix) * xap;
856                     gg = G_VAL(pix) * xap;
857                     bb = B_VAL(pix) * xap;
858                     pix++;
859                     for(j = (1 << 14) - xap; j > Cx; j -= Cx){
860                         rr += R_VAL(pix) * Cx;
861                         gg += G_VAL(pix) * Cx;
862                         bb += B_VAL(pix) * Cx;
863                         pix++;
864                     }
865                     if(j > 0){
866                         rr += R_VAL(pix) * j;
867                         gg += G_VAL(pix) * j;
868                         bb += B_VAL(pix) * j;
869                     }
870                     r = r * INV_YAP;
871                     g = g * INV_YAP;
872                     b = b * INV_YAP;
873                     r = (r + ((rr * YAP))) >> 12;
874                     g = (g + ((gg * YAP))) >> 12;
875                     b = (b + ((bb * YAP))) >> 12;
876                 }
877                 else{
878                     r >>= 4;
879                     g >>= 4;
880                     b >>= 4;
881                 }
882                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
883                 dptr++;
884             }
885         }
886     }
887     /* fully optimized (i think) - onyl change of algorithm can help */
888     /* if we're scaling down horizontally & vertically */
889     else{
890         /*\ 'Correct' version, with math units prepared for MMXification \*/
891         int Cx, Cy, i, j;
892         unsigned int *pix;
893         int r, g, b, rx, gx, bx;
894         int xap, yap;
895
896         for(y = 0; y < dh; y++){
897             Cy = YAP >> 16;
898             yap = YAP & 0xffff;
899
900             dptr = dest + dx + ((y + dy) * dow);
901             for(x = dxx; x < end; x++){
902                 Cx = XAP >> 16;
903                 xap = XAP & 0xffff;
904
905                 sptr = ypoints[dyy + y] + xpoints[x];
906                 pix = sptr;
907                 sptr += sow;
908                 rx = R_VAL(pix) * xap;
909                 gx = G_VAL(pix) * xap;
910                 bx = B_VAL(pix) * xap;
911                 pix++;
912                 for(i = (1 << 14) - xap; i > Cx; i -= Cx){
913                     rx += R_VAL(pix) * Cx;
914                     gx += G_VAL(pix) * Cx;
915                     bx += B_VAL(pix) * Cx;
916                     pix++;
917                 }
918                 if(i > 0){
919                     rx += R_VAL(pix) * i;
920                     gx += G_VAL(pix) * i;
921                     bx += B_VAL(pix) * i;
922                 }
923
924                 r = (rx >> 5) * yap;
925                 g = (gx >> 5) * yap;
926                 b = (bx >> 5) * yap;
927
928                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
929                     pix = sptr;
930                     sptr += sow;
931                     rx = R_VAL(pix) * xap;
932                     gx = G_VAL(pix) * xap;
933                     bx = B_VAL(pix) * xap;
934                     pix++;
935                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
936                         rx += R_VAL(pix) * Cx;
937                         gx += G_VAL(pix) * Cx;
938                         bx += B_VAL(pix) * Cx;
939                         pix++;
940                     }
941                     if(i > 0){
942                         rx += R_VAL(pix) * i;
943                         gx += G_VAL(pix) * i;
944                         bx += B_VAL(pix) * i;
945                     }
946
947                     r += (rx >> 5) * Cy;
948                     g += (gx >> 5) * Cy;
949                     b += (bx >> 5) * Cy;
950                 }
951                 if(j > 0){
952                     pix = sptr;
953                     sptr += sow;
954                     rx = R_VAL(pix) * xap;
955                     gx = G_VAL(pix) * xap;
956                     bx = B_VAL(pix) * xap;
957                     pix++;
958                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
959                         rx += R_VAL(pix) * Cx;
960                         gx += G_VAL(pix) * Cx;
961                         bx += B_VAL(pix) * Cx;
962                         pix++;
963                     }
964                     if(i > 0){
965                         rx += R_VAL(pix) * i;
966                         gx += G_VAL(pix) * i;
967                         bx += B_VAL(pix) * i;
968                     }
969
970                     r += (rx >> 5) * j;
971                     g += (gx >> 5) * j;
972                     b += (bx >> 5) * j;
973                 }
974
975                 *dptr = qRgb(r >> 23, g >> 23, b >> 23);
976                 dptr++;
977             }
978         }
979     }
980 }
981
982 #if 0
983 static void qt_qimageScaleAARGBASetup(QImageScaleInfo *isi, unsigned int *dest,
984                                       int dxx, int dyy, int dx, int dy, int dw,
985                                       int dh, int dow, int sow)
986 {
987     qInitDrawhelperAsm();
988     qt_qimageScaleAARGBA(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
989 }
990
991 static void qt_qimageScaleAARGBSetup(QImageScaleInfo *isi, unsigned int *dest,
992                                  int dxx, int dyy, int dx, int dy, int dw,
993                                  int dh, int dow, int sow)
994 {
995     qInitDrawhelperAsm();
996     qt_qimageScaleAARGB(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
997 }
998 #endif
999
1000 QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
1001 {
1002     QImage buffer;
1003     if (src.isNull() || dw <= 0 || dh <= 0)
1004         return buffer;
1005
1006     int w = src.width();
1007     int h = src.height();
1008     QImageScaleInfo *scaleinfo =
1009         qimageCalcScaleInfo(src, w, h, dw, dh, true);
1010     if (!scaleinfo)
1011         return buffer;
1012
1013     buffer = QImage(dw, dh, src.format());
1014     if (buffer.isNull()) {
1015         qWarning("QImage: out of memory, returning null");
1016         qimageFreeScaleInfo(scaleinfo);
1017         return QImage();
1018     }
1019
1020     if (src.format() == QImage::Format_ARGB32_Premultiplied)
1021         qt_qimageScaleArgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
1022                            0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
1023     else
1024         qt_qimageScaleRgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
1025                           0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
1026
1027     qimageFreeScaleInfo(scaleinfo);
1028     return buffer;
1029 }
1030
1031 QT_END_NAMESPACE