debian/spiv.manpages: +spiv.1
[gfxprim/pasky.git] / libs / gfx / GP_Line.gen.c.t
blobd91b45a063963597d6eef4c860636044eeae4bea
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-2012 Jiri "BlueBear" Dluhos                            *
20  *                         <jiri.bluebear.dluhos@gmail.com>                  *
21  *                                                                           *
22  * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz>                       *
23  *                                                                           *
24  *****************************************************************************/
26 %% extends "base.c.t"
28 {% block descr %}Line drawing algorithm{% endblock %}
30 %% block body
32 #include "core/GP_Common.h"
33 #include "core/GP_GetPutPixel.h"
34 #include "core/GP_FnPerBpp.h"
36 #include "gfx/GP_VLine.h"
37 #include "gfx/GP_HLine.h"
38 #include "gfx/GP_Line.h"
39 #include "gfx/GP_LineClip.h"
42  * The classical Bresenham line drawing algorithm.
43  * Please see http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
44  * for a nice and understandable description.
45  */
47 %% for ps in pixelsizes
49 void GP_Line_Raw_{{ ps.suffix }}(GP_Context *context, int x0, int y0,
50         int x1, int y1, GP_Pixel pixval)
52         if (!GP_LineClip(&x0, &y0, &x1, &y1, context->w - 1, context->h - 1))
53                 return;
55         GP_ASSERT(x0 >= 0 && x0 <= (int) context->w-1);
56         GP_ASSERT(x1 >= 0 && x1 <= (int) context->w-1);
57         GP_ASSERT(y0 >= 0 && y0 <= (int) context->h-1);
58         GP_ASSERT(y1 >= 0 && y1 <= (int) context->h-1);
60         /* special cases: vertical line, horizontal line, single point */
61         if (x0 == x1) {
62                 if (y0 == y1) {
63                         GP_PutPixel_Raw_Clipped_{{ ps.suffix }}(context,
64                                         x0, y0, pixval);
65                         return;
66                 }
67                 GP_VLine_Raw(context, x0, y0, y1, pixval);
68                 return;
69         }
70         if (y0 == y1) {
71                 GP_HLine_Raw(context, x0, x1, y0, pixval);
72                 return;
73         }
75         /*
76          * Which axis is longer? Swap the coordinates if necessary so
77          * that the X axis is always the longer one and Y is shorter.
78          */
79         int steep = abs(y1 - y0) / abs(x1 - x0);
80         if (steep) {
81                 GP_SWAP(x0, y0);
82                 GP_SWAP(x1, y1);
83         }
84         if (x0 > x1) {
85                 GP_SWAP(x0, x1);
86                 GP_SWAP(y0, y1);
87         }
89         /* iterate over the longer axis, calculate values on the shorter */
90         int deltax = x1 - x0;
91         int deltay = abs(y1 - y0);
93         /*
94          * start with error of 0.5 (multiplied by deltax for integer-only math),
95          * this reflects the fact that ideally, the coordinate should be
96          * in the middle of the pixel
97          */
98         int error = deltax / 2;
100         int y = y0, x;
101         int ystep = (y0 < y1) ? 1 : -1;
102         for (x = x0; x <= x1; x++) {
104                 if (steep)
105                         GP_PutPixel_Raw_{{ ps.suffix }}(context, y, x,
106                                                                 pixval);
107                 else
108                         GP_PutPixel_Raw_{{ ps.suffix }}(context, x, y,
109                                                                 pixval);
111                 error -= deltay;
112                 if (error < 0) {
113                         y += ystep;     /* next step on the shorter axis */
114                         error += deltax;
115                 }
116         }
119 %% endfor
121 void GP_Line_Raw(GP_Context *context, GP_Coord x0, GP_Coord y0,
122                  GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
124         GP_CHECK_CONTEXT(context);
126         GP_FN_PER_BPP_CONTEXT(GP_Line_Raw, context, context, x0, y0, x1, y1,
127                               pixel);
130 void GP_Line(GP_Context *context, GP_Coord x0, GP_Coord y0,
131              GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
133         GP_CHECK_CONTEXT(context);
135         GP_TRANSFORM_POINT(context, x0, y0);
136         GP_TRANSFORM_POINT(context, x1, y1);
138         GP_Line_Raw(context, x0, y0, x1, y1, pixel);
141 %% endblock body