3 {% block descr %}Anti Aliased Line{% endblock %}
7 #include "core/GP_Context.h"
8 #include "core/GP_MixPixels.h"
9 #include "core/GP_FixedPoint.h"
10 #include "core/GP_GammaCorrection.h"
12 #include "gfx/GP_HLineAA.h"
13 #include "gfx/GP_VLineAA.h"
15 #define FP_TO_PERC(a) (GP_FP_ROUND_TO_INT((a) * 255))
17 static inline void line_aa_x(GP_Context *context,
18 GP_Coord x0, GP_Coord y0,
19 GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
21 GP_Coord xend, yend, xgap, xpx0, ypx0, xpx1, ypx1;
32 xend = GP_FP_ROUND(x1);
33 yend = y1 + GP_FP_DIV(GP_FP_MUL(dy, xend - x1), dx);
34 xgap = GP_FP_FRAC(x1 + GP_FP_1_2);
35 xpx1 = GP_FP_TO_INT(xend);
36 ypx1 = GP_FP_TO_INT(yend);
38 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(yend), xgap));
39 GP_MixPixel_Raw_Clipped(context, xpx1, ypx1, pixel, perc);
40 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(yend), xgap));
41 GP_MixPixel_Raw_Clipped(context, xpx1, ypx1+1, pixel, perc);
43 xend = GP_FP_ROUND(x0);
44 yend = y0 + GP_FP_DIV(GP_FP_MUL(dy, xend - x0), dx);
45 xgap = GP_FP_RFRAC(x0 + GP_FP_1_2);
46 xpx0 = GP_FP_TO_INT(xend);
47 ypx0 = GP_FP_TO_INT(yend);
49 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(yend), xgap));
50 GP_MixPixel_Raw_Clipped(context, xpx0, ypx0, pixel, perc);
51 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(yend), xgap));
52 GP_MixPixel_Raw_Clipped(context, xpx0, ypx0+1, pixel, perc);
57 for (x = xpx0 + 1; x < xpx1; x++) {
58 intery = yend + GP_FP_DIV((x - xpx0) * dy, dx);
60 perc = FP_TO_PERC(GP_FP_RFRAC(intery));
61 GP_MixPixel_Raw_Clipped(context, x, GP_FP_TO_INT(intery), pixel, perc);
62 perc = FP_TO_PERC(GP_FP_FRAC(intery));
63 GP_MixPixel_Raw_Clipped(context, x, GP_FP_TO_INT(intery)+1, pixel, perc);
67 static inline void line_aa_y(GP_Context *context,
68 GP_Coord x0, GP_Coord y0,
69 GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
71 GP_Coord xend, yend, ygap, xpx0, ypx0, xpx1, ypx1;
82 yend = GP_FP_ROUND(y1);
83 xend = x1 + GP_FP_DIV(GP_FP_MUL(dx, yend - y1), dy);
84 ygap = GP_FP_FRAC(y1 + GP_FP_1_2);
85 ypx1 = GP_FP_TO_INT(yend);
86 xpx1 = GP_FP_TO_INT(xend);
88 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(xend), ygap));
89 GP_MixPixel_Raw_Clipped(context, xpx1, ypx1, pixel, perc);
90 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(xend), ygap));
91 GP_MixPixel_Raw_Clipped(context, xpx1, ypx1+1, pixel, perc);
93 yend = GP_FP_ROUND(y0);
94 xend = x0 + GP_FP_DIV(GP_FP_MUL(dx, yend - y0), dy);
95 ygap = GP_FP_RFRAC(y0 + GP_FP_1_2);
96 ypx0 = GP_FP_TO_INT(yend);
97 xpx0 = GP_FP_TO_INT(xend);
99 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_RFRAC(xend), ygap));
100 GP_MixPixel_Raw_Clipped(context, xpx0, ypx0, pixel, perc);
101 perc = FP_TO_PERC(GP_FP_MUL(GP_FP_FRAC(xend), ygap));
102 GP_MixPixel_Raw_Clipped(context, xpx0, ypx0+1, pixel, perc);
107 for (y = ypx0 + 1; y < ypx1; y++) {
108 intery = xend + GP_FP_DIV((y - ypx0) * dx, dy);
110 perc = FP_TO_PERC(GP_FP_RFRAC(intery));
111 GP_MixPixel_Raw_Clipped(context, GP_FP_TO_INT(intery), y, pixel, perc);
112 perc = FP_TO_PERC(GP_FP_FRAC(intery));
113 GP_MixPixel_Raw_Clipped(context, GP_FP_TO_INT(intery)+1, y, pixel, perc);
117 void GP_LineAA_Raw(GP_Context *context, GP_Coord x0, GP_Coord y0,
118 GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
120 int64_t dx = x1 - x0;
121 int64_t dy = y1 - y0;
124 GP_HLineAA_Raw(context, x0, x1, y0, pixel);
129 GP_VLineAA_Raw(context, x0, y0, y1, pixel);
133 if (GP_ABS(dx) < GP_ABS(dy))
134 line_aa_y(context, x0, y0, x1, y1, pixel);
136 line_aa_x(context, x0, y0, x1, y1, pixel);