diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index cb3f9cc6a..06d8382f1 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1044,6 +1044,57 @@ METAL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL return 0; } +static int +METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count) +{ + SDL_assert(count >= 2); /* should have been checked at the higher level. */ + + const size_t vertlen = (sizeof (float) * 2) * count; + float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first); + if (!verts) { + return -1; + } + cmd->data.draw.count = count; + SDL_memcpy(verts, points, vertlen); + + /* If the line segment is completely horizontal or vertical, + make it one pixel longer, to satisfy the diamond-exit rule. + We should probably do this for diagonal lines too, but we'd have to + do some trigonometry to figure out the correct pixel and generally + when we have problems with pixel perfection, it's for straight lines + that are missing a pixel that frames something and not arbitrary + angles. Maybe !!! FIXME for later, though. */ + + points += count - 2; /* update the last line. */ + verts += count - 2; + + float xstart = /*0.5f +*/ points[0].x; /* 0.5f to get to the center of the pixel. */ + float ystart = /*0.5f +*/ points[0].y; + float xend = /*0.5f +*/ points[1].x; + float yend = /*0.5f +*/ points[1].y; + + if (xstart == xend) { /* vertical line */ + if (yend > ystart) { + yend += 1.0f; + } else { + ystart += 1.0f; + } + } else if (ystart == yend) { /* horizontal line */ + if (xend > xstart) { + xend += 1.0f; + } else { + xstart += 1.0f; + } + } + + *(verts++) = xstart; + *(verts++) = ystart; + *(verts++) = xend; + *(verts++) = yend; + + return 0; +} + static int METAL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count) { @@ -1813,7 +1864,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->QueueSetViewport = METAL_QueueSetViewport; renderer->QueueSetDrawColor = METAL_QueueSetDrawColor; renderer->QueueDrawPoints = METAL_QueueDrawPoints; - renderer->QueueDrawLines = METAL_QueueDrawPoints; // lines and points queue the same way. + renderer->QueueDrawLines = METAL_QueueDrawLines; renderer->QueueFillRects = METAL_QueueFillRects; renderer->QueueCopy = METAL_QueueCopy; renderer->QueueCopyEx = METAL_QueueCopyEx;