Rename GP_Context -> GP_Pixmap
[gfxprim.git] / libs / gfx / GP_Line.gen.c.t
blobb45bfacd00b5cded92ebb0c6418a8b9b90db79f5
1 @ include source.t
2 /*
3  * Line drawing algorithm.
4  *
5  * Copyright (C) 2009-2012 Jiri "BlueBear" Dluhos
6  *                         <jiri.bluebear.dluhos@gmail.com>
7  * Copyright (C) 2009-2014 Cyril Hrubis <metan@ucw.cz>
8  */
10 #include "core/GP_Common.h"
11 #include "core/GP_GetPutPixel.h"
12 #include "core/GP_FnPerBpp.h"
14 #include "gfx/GP_VLine.h"
15 #include "gfx/GP_HLine.h"
16 #include "gfx/GP_Line.h"
17 #include "gfx/GP_LineClip.h"
20  * The classical Bresenham line drawing algorithm.
21  * Please see http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
22  * for a nice and understandable description.
23  */
25 @ for ps in pixelsizes:
26 void GP_Line_Raw_{{ ps.suffix }}(GP_Pixmap *pixmap, int x0, int y0,
27         int x1, int y1, GP_Pixel pixval)
29         if (!GP_LineClip(&x0, &y0, &x1, &y1, pixmap->w - 1, pixmap->h - 1))
30                 return;
32         GP_ASSERT(x0 >= 0 && x0 <= (int) pixmap->w-1);
33         GP_ASSERT(x1 >= 0 && x1 <= (int) pixmap->w-1);
34         GP_ASSERT(y0 >= 0 && y0 <= (int) pixmap->h-1);
35         GP_ASSERT(y1 >= 0 && y1 <= (int) pixmap->h-1);
37         /* special cases: vertical line, horizontal line, single point */
38         if (x0 == x1) {
39                 if (y0 == y1) {
40                         GP_PutPixel_Raw_Clipped_{{ ps.suffix }}(pixmap,
41                                         x0, y0, pixval);
42                         return;
43                 }
44                 GP_VLine_Raw(pixmap, x0, y0, y1, pixval);
45                 return;
46         }
47         if (y0 == y1) {
48                 GP_HLine_Raw(pixmap, x0, x1, y0, pixval);
49                 return;
50         }
52         /*
53          * Which axis is longer? Swap the coordinates if necessary so
54          * that the X axis is always the longer one and Y is shorter.
55          */
56         int steep = abs(y1 - y0) / abs(x1 - x0);
57         if (steep) {
58                 GP_SWAP(x0, y0);
59                 GP_SWAP(x1, y1);
60         }
61         if (x0 > x1) {
62                 GP_SWAP(x0, x1);
63                 GP_SWAP(y0, y1);
64         }
66         /* iterate over the longer axis, calculate values on the shorter */
67         int deltax = x1 - x0;
68         int deltay = abs(y1 - y0);
70         /*
71          * start with error of 0.5 (multiplied by deltax for integer-only math),
72          * this reflects the fact that ideally, the coordinate should be
73          * in the middle of the pixel
74          */
75         int error = deltax / 2;
77         int y = y0, x;
78         int ystep = (y0 < y1) ? 1 : -1;
79         for (x = x0; x <= x1; x++) {
81                 if (steep)
82                         GP_PutPixel_Raw_{{ ps.suffix }}(pixmap, y, x,
83                                                                 pixval);
84                 else
85                         GP_PutPixel_Raw_{{ ps.suffix }}(pixmap, x, y,
86                                                                 pixval);
88                 error -= deltay;
89                 if (error < 0) {
90                         y += ystep;     /* next step on the shorter axis */
91                         error += deltax;
92                 }
93         }
96 @ end
98 void GP_Line_Raw(GP_Pixmap *pixmap, GP_Coord x0, GP_Coord y0,
99                  GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
101         GP_CHECK_PIXMAP(pixmap);
103         GP_FN_PER_BPP_PIXMAP(GP_Line_Raw, pixmap, pixmap, x0, y0, x1, y1,
104                               pixel);
107 void GP_Line(GP_Pixmap *pixmap, GP_Coord x0, GP_Coord y0,
108              GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
110         GP_CHECK_PIXMAP(pixmap);
112         GP_TRANSFORM_POINT(pixmap, x0, y0);
113         GP_TRANSFORM_POINT(pixmap, x1, y1);
115         GP_Line_Raw(pixmap, x0, y0, x1, y1, pixel);