1 /*****************************************************************************
2 * This file is part of gfxprim library. *
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. *
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. *
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 *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
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;
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);
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);
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;
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);
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);
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;
142 GP_HLineAA_Raw(pixmap, x0, x1, y0, pixel);
147 GP_VLineAA_Raw(pixmap, x0, y0, y1, pixel);
151 if (GP_ABS(dx) < GP_ABS(dy))
152 line_aa_y(pixmap, x0, y0, x1, y1, pixel);
154 line_aa_x(pixmap, x0, y0, x1, y1, pixel);