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-2012 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
22 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
24 *****************************************************************************/
28 {% block descr %}Line drawing algorithm{% endblock %}
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.
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))
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 */
63 GP_PutPixel_Raw_Clipped_{{ ps.suffix }}(context,
67 GP_VLine_Raw(context, x0, y0, y1, pixval);
71 GP_HLine_Raw(context, x0, x1, y0, pixval);
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.
79 int steep = abs(y1 - y0) / abs(x1 - x0);
89 /* iterate over the longer axis, calculate values on the shorter */
91 int deltay = abs(y1 - y0);
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
98 int error = deltax / 2;
101 int ystep = (y0 < y1) ? 1 : -1;
102 for (x = x0; x <= x1; x++) {
105 GP_PutPixel_Raw_{{ ps.suffix }}(context, y, x,
108 GP_PutPixel_Raw_{{ ps.suffix }}(context, x, y,
113 y += ystep; /* next step on the shorter axis */
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,
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);