loaders: PNG: Handle gamma on 16bpp conversion
[gfxprim.git] / libs / gfx / GP_LineAA.gen.c.t
blob3eed710d69068454f43690eb1ae56ecdc163450c
1 /*****************************************************************************
2  * This file is part of gfxprim library.                                     *
3  *                                                                           *
4  * Gfxprim is free software; you can redistribute it and/or                  *
5  * modify it under the terms of the GNU Lesser General Public                *
6  * License as published by the Free Software Foundation; either              *
7  * version 2.1 of the License, or (at your option) any later version.        *
8  *                                                                           *
9  * Gfxprim is distributed in the hope that it will be useful,                *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
12  * Lesser General Public License for more details.                           *
13  *                                                                           *
14  * You should have received a copy of the GNU Lesser General Public          *
15  * License along with gfxprim; if not, write to the Free Software            *
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor,                        *
17  * Boston, MA  02110-1301  USA                                               *
18  *                                                                           *
19  * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz>                       *
20  *                                                                           *
21  *****************************************************************************/
23 /* Anti Aliased Line */
25 #include "core/GP_Pixmap.h"
26 #include "core/GP_MixPixels.h"
27 #include "core/GP_FixedPoint.h"
28 #include "core/GP_GammaCorrection.h"
30 #include "gfx/GP_HLineAA.h"
31 #include "gfx/GP_VLineAA.h"
33 #define FP_TO_PERC(a) (GP_FP_ROUND_TO_INT((a) * 255))
35 static inline void line_aa_x(GP_Pixmap *pixmap,
36                              GP_Coord x0, GP_Coord y0,
37                              GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
39         GP_Coord xend, yend, xgap, xpx0, ypx0, xpx1, ypx1;
40         uint8_t perc;
42         int64_t dx = x1 - x0;
43         int64_t dy = y1 - y0;
45         if (x1 < x0) {
46                 GP_SWAP(x0, x1);
47                 GP_SWAP(y0, y1);
48         }
50         xend = GP_FP_ROUND(x1);
51         yend = y1 + GP_FP_DIV(GP_FP_MUL(dy, xend - x1), dx);
52         xgap = GP_FP_FRAC(x1 + GP_FP_1_2);
53         xpx1 = GP_FP_TO_INT(xend);
54         ypx1 = GP_FP_TO_INT(yend);
56         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(yend), xgap));
57         GP_MixPixel_Raw_Clipped(pixmap, xpx1, ypx1, pixel, perc);
58         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(yend), xgap));
59         GP_MixPixel_Raw_Clipped(pixmap, xpx1, ypx1+1, pixel, perc);
61         xend = GP_FP_ROUND(x0);
62         yend = y0 + GP_FP_DIV(GP_FP_MUL(dy, xend - x0), dx);
63         xgap = GP_FP_RFRAC(x0 + GP_FP_1_2);
64         xpx0 = GP_FP_TO_INT(xend);
65         ypx0 = GP_FP_TO_INT(yend);
67         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(yend), xgap));
68         GP_MixPixel_Raw_Clipped(pixmap, xpx0, ypx0, pixel, perc);
69         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(yend), xgap));
70         GP_MixPixel_Raw_Clipped(pixmap, xpx0, ypx0+1, pixel, perc);
72         GP_Coord x;
73         GP_Coord intery;
75         for (x = xpx0 + 1; x < xpx1; x++) {
76                 intery = yend + GP_FP_DIV((x - xpx0) * dy, dx);
78                 perc = FP_TO_PERC(GP_FP_RFRAC(intery));
79                 GP_MixPixel_Raw_Clipped(pixmap, x, GP_FP_TO_INT(intery), pixel, perc);
80                 perc = FP_TO_PERC(GP_FP_FRAC(intery));
81                 GP_MixPixel_Raw_Clipped(pixmap, x, GP_FP_TO_INT(intery)+1, pixel, perc);
82         }
85 static inline void line_aa_y(GP_Pixmap *pixmap,
86                              GP_Coord x0, GP_Coord y0,
87                              GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
89         GP_Coord xend, yend, ygap, xpx0, ypx0, xpx1, ypx1;
90         uint8_t perc;
92         int64_t dx = x1 - x0;
93         int64_t dy = y1 - y0;
95         if (y1 < y0) {
96                 GP_SWAP(x0, x1);
97                 GP_SWAP(y0, y1);
98         }
100         yend = GP_FP_ROUND(y1);
101         xend = x1 + GP_FP_DIV(GP_FP_MUL(dx, yend - y1), dy);
102         ygap = GP_FP_FRAC(y1 + GP_FP_1_2);
103         ypx1 = GP_FP_TO_INT(yend);
104         xpx1 = GP_FP_TO_INT(xend);
106         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(xend), ygap));
107         GP_MixPixel_Raw_Clipped(pixmap, xpx1, ypx1, pixel, perc);
108         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(xend), ygap));
109         GP_MixPixel_Raw_Clipped(pixmap, xpx1, ypx1+1, pixel, perc);
111         yend = GP_FP_ROUND(y0);
112         xend = x0 + GP_FP_DIV(GP_FP_MUL(dx, yend - y0), dy);
113         ygap = GP_FP_RFRAC(y0 + GP_FP_1_2);
114         ypx0 = GP_FP_TO_INT(yend);
115         xpx0 = GP_FP_TO_INT(xend);
117         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(xend), ygap));
118         GP_MixPixel_Raw_Clipped(pixmap, xpx0, ypx0, pixel, perc);
119         perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(xend), ygap));
120         GP_MixPixel_Raw_Clipped(pixmap, xpx0, ypx0+1, pixel, perc);
122         GP_Coord y;
123         GP_Coord intery;
125         for (y = ypx0 + 1; y < ypx1; y++) {
126                 intery = xend + GP_FP_DIV((y - ypx0) * dx, dy);
128                 perc = FP_TO_PERC(GP_FP_RFRAC(intery));
129                 GP_MixPixel_Raw_Clipped(pixmap, GP_FP_TO_INT(intery), y, pixel, perc);
130                 perc = FP_TO_PERC(GP_FP_FRAC(intery));
131                 GP_MixPixel_Raw_Clipped(pixmap, GP_FP_TO_INT(intery)+1, y, pixel, perc);
132         }
135 void GP_LineAA_Raw(GP_Pixmap *pixmap, GP_Coord x0, GP_Coord y0,
136                    GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
138         int64_t dx = x1 - x0;
139         int64_t dy = y1 - y0;
141         if (dy == 0) {
142                 GP_HLineAA_Raw(pixmap, x0, x1, y0, pixel);
143                 return;
144         }
146         if (dx == 0) {
147                 GP_VLineAA_Raw(pixmap, x0, y0, y1, pixel);
148                 return;
149         }
151         if (GP_ABS(dx) < GP_ABS(dy))
152                 line_aa_y(pixmap, x0, y0, x1, y1, pixel);
153         else
154                 line_aa_x(pixmap, x0, y0, x1, y1, pixel);