summaryrefslogtreecommitdiffhomepage
path: root/src/textures.c
diff options
context:
space:
mode:
authorAlexander Buhl <[email protected]>2021-07-23 23:17:04 +0200
committerGitHub <[email protected]>2021-07-23 23:17:04 +0200
commitff2b8d6db19b4de0b3acaefdf2b50d63dbc029f9 (patch)
tree707315bf63432ddb36fcb6dfa46a74c7e4a4dcbc /src/textures.c
parent0fa295c72ddaff928dc883bb29b785d8be063154 (diff)
downloadraylib-ff2b8d6db19b4de0b3acaefdf2b50d63dbc029f9.tar.gz
raylib-ff2b8d6db19b4de0b3acaefdf2b50d63dbc029f9.zip
Fixes #1873 Implemented remaining 7/8 of ImageDrawLine (#1874)
* Implemented remaining 7/8 of ImageDrawLine The existing code was correct for one octant, it now works for all 8 Added two internal functions, _ImageDrawLineHorizontal and _ImageDrawLineVertical, whithout which it would've been 4 times as much code. * ImageDrawLine: Replaced 3 functions with 1 Removed both freshly added internal functions Crammed it all into one * ImageDrawLine shortened significantly using maths Substituted X and Y, then wrote one abstract loop instead of 4 specific loops. Lots of comments to explain what I'm doing for future maintainers. * Now conforms with style conventions Also reworded a comment to sound more... fomal.
Diffstat (limited to 'src/textures.c')
-rw-r--r--src/textures.c106
1 files changed, 94 insertions, 12 deletions
diff --git a/src/textures.c b/src/textures.c
index 9bef90c4..e906980b 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -2414,26 +2414,108 @@ void ImageDrawPixelV(Image *dst, Vector2 position, Color color)
{
ImageDrawPixel(dst, (int)position.x, (int)position.y, color);
}
-
+
// Draw line within an image
void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color)
{
- int m = 2*(endPosY - startPosY);
- int slopeError = m - (endPosX - startPosX);
-
- for (int x = startPosX, y = startPosY; x <= endPosX; x++)
+ // Using Bresenham's algorithm as described in
+ // Drawing Lines with Pixels - Joshua Scott - March 2012
+ // https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf
+
+ int changeInX = (endPosX - startPosX);
+ int abs_changeInX = (changeInX < 0)? -changeInX : changeInX;
+ int changeInY = (endPosY - startPosY);
+ int abs_changeInY = (changeInY < 0)? -changeInY : changeInY;
+
+ int startU, startV, endU, V_step; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function
+ //int endV; // This is not needed, but to aid understanding it is left in the code below.
+
+ int A, B, P; // See linked paper above. Explained down in the main loop.
+
+ int is_x_y_reversed = (abs_changeInY < abs_changeInX);
+
+ if (is_x_y_reversed)
{
- ImageDrawPixel(dst, x, y, color);
- slopeError += m;
-
- if (slopeError >= 0)
+ A = 2*abs_changeInY;
+ B = A - 2*abs_changeInX;
+ P = A - abs_changeInX;
+
+ if (changeInX > 0)
+ {
+ startU = startPosX;
+ startV = startPosY;
+ endU = endPosX;
+ //endV = endPosY;
+ }
+ else
+ {
+ startU = endPosX;
+ startV = endPosY;
+ endU = startPosX;
+ //endV = startPosY;
+
+ // since start and end are reversed:
+ changeInX = -changeInX;
+ changeInY = -changeInY;
+ }
+
+ V_step = (changeInY < 0)? -1 : 1;
+
+ ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered...
+ }
+ else // all X and Y are reversed in here:
+ {
+ A = 2*abs_changeInX;
+ B = A - 2*abs_changeInY;
+ P = A - abs_changeInY;
+
+ if (changeInY > 0)
+ {
+ startU = startPosY;
+ startV = startPosX;
+ endU = endPosY;
+ //endV = endPosX;
+ }
+ else
{
- y++;
- slopeError -= 2*(endPosX - startPosX);
+ startU = endPosY;
+ startV = endPosX;
+ endU = startPosY;
+ //endV = startPosX;
+
+ // since start and end are reversed:
+ changeInX = -changeInX;
+ changeInY = -changeInY;
+ }
+
+ V_step = (changeInX < 0)? -1 : 1;
+
+ ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below.
+ }
+
+ // We already drew the start point. If we started at startU+0, the line would be crooked and too short.
+ for (int U = startU+1, V = startV; U <= endU; U += 1)
+ {
+ if (P >= 0)
+ {
+ V += V_step; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above.
+ P += B; // Remembers that we corrected our path.
+ }
+ else
+ {
+ P += A; // Remembers how far we are from the direct line.
+ }
+ if (is_x_y_reversed) // Substitutions may be in wrong order for drawing:
+ {
+ ImageDrawPixel(dst, U, V, color);
+ }
+ else
+ {
+ ImageDrawPixel(dst, V, U, color);
}
}
}
-
+
// Draw line within an image (Vector version)
void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)
{