Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Added SDL_DrawRect(), SDL_DrawRects(), SDL_BlendRect() and SDL_BlendR…

…ects()

Fixed line drawing so when blending a sequence of lines there are no overlapping pixels drawn.
  • Loading branch information
slouken committed Dec 18, 2009
1 parent 1492eda commit cdf547eb06379d537091390f764b8fa9b34d9853
Showing with 165 additions and 442 deletions.
  1. +0 −10 src/video/SDL_blendfillrect.c
  2. +54 −42 src/video/SDL_blendline.c
  3. +75 −0 src/video/SDL_blendrect.c
  4. +6 −2 src/video/SDL_draw.h
  5. +6 −6 src/video/SDL_drawline.c
  6. +24 −382 src/video/SDL_drawrect.c
@@ -203,11 +203,6 @@ SDL_BlendFillRect(SDL_Surface * dst, const SDL_Rect * rect,
return -1;
}

if (blendMode < SDL_BLENDMODE_BLEND) {
Uint32 color = SDL_MapRGBA(dst->format, r, g, b, a);
return SDL_FillRect(dst, rect, color);
}

/* This function doesn't work on surfaces < 8 bpp */
if (dst->format->BitsPerPixel < 8) {
SDL_SetError("SDL_BlendFillRect(): Unsupported surface format");
@@ -281,11 +276,6 @@ SDL_BlendFillRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
return -1;
}

if (blendMode < SDL_BLENDMODE_BLEND) {
Uint32 color = SDL_MapRGBA(dst->format, r, g, b, a);
return SDL_FillRects(dst, rects, color);
}

/* This function doesn't work on surfaces < 8 bpp */
if (dst->format->BitsPerPixel < 8) {
SDL_SetError("SDL_BlendFillRects(): Unsupported surface format");
@@ -25,99 +25,104 @@

static int
SDL_BlendLine_RGB555(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
{
unsigned inva = 0xff - a;

switch (blendMode) {
case SDL_BLENDMODE_BLEND:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB555);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB555, draw_end);
break;
case SDL_BLENDMODE_ADD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB555);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB555, draw_end);
break;
case SDL_BLENDMODE_MOD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB555);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB555, draw_end);
break;
default:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB555);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB555, draw_end);
break;
}
return 0;
}

static int
SDL_BlendLine_RGB565(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
{
unsigned inva = 0xff - a;

switch (blendMode) {
case SDL_BLENDMODE_BLEND:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB565);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB565, draw_end);
break;
case SDL_BLENDMODE_ADD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB565);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB565, draw_end);
break;
case SDL_BLENDMODE_MOD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB565);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB565, draw_end);
break;
default:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB565);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB565, draw_end);
break;
}
return 0;
}

static int
SDL_BlendLine_RGB888(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
{
unsigned inva = 0xff - a;

switch (blendMode) {
case SDL_BLENDMODE_BLEND:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB888, draw_end);
break;
case SDL_BLENDMODE_ADD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB888, draw_end);
break;
case SDL_BLENDMODE_MOD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB888, draw_end);
break;
default:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB888, draw_end);
break;
}
return 0;
}

static int
SDL_BlendLine_ARGB8888(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
{
unsigned inva = 0xff - a;

switch (blendMode) {
case SDL_BLENDMODE_BLEND:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_ARGB8888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_ARGB8888, draw_end);
break;
case SDL_BLENDMODE_ADD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_ARGB8888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_ARGB8888, draw_end);
break;
case SDL_BLENDMODE_MOD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_ARGB8888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_ARGB8888, draw_end);
break;
default:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ARGB8888);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ARGB8888, draw_end);
break;
}
return 0;
}

static int
SDL_BlendLine_RGB(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
{
SDL_PixelFormat *fmt = dst->format;
unsigned inva = 0xff - a;
@@ -126,32 +131,32 @@ SDL_BlendLine_RGB(SDL_Surface * dst, int x1, int y1, int x2, int y2,
case 2:
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_BLEND_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_BLEND_RGB, draw_end);
break;
case SDL_BLENDMODE_ADD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_ADD_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_ADD_RGB, draw_end);
break;
case SDL_BLENDMODE_MOD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_MOD_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_MOD_RGB, draw_end);
break;
default:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_RGB, draw_end);
break;
}
return 0;
case 4:
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGB, draw_end);
break;
case SDL_BLENDMODE_ADD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGB, draw_end);
break;
case SDL_BLENDMODE_MOD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGB, draw_end);
break;
default:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGB);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGB, draw_end);
break;
}
return 0;
@@ -163,7 +168,8 @@ SDL_BlendLine_RGB(SDL_Surface * dst, int x1, int y1, int x2, int y2,

static int
SDL_BlendLine_RGBA(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
{
SDL_PixelFormat *fmt = dst->format;
unsigned inva = 0xff - a;
@@ -172,16 +178,16 @@ SDL_BlendLine_RGBA(SDL_Surface * dst, int x1, int y1, int x2, int y2,
case 4:
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGBA);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGBA, draw_end);
break;
case SDL_BLENDMODE_ADD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGBA);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGBA, draw_end);
break;
case SDL_BLENDMODE_MOD:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGBA);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGBA, draw_end);
break;
default:
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGBA);
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGBA, draw_end);
break;
}
return 0;
@@ -218,25 +224,25 @@ SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
switch (dst->format->Rmask) {
case 0x7C00:
return SDL_BlendLine_RGB555(dst, x1, y1, x2, y2, blendMode, r, g,
b, a);
b, a, SDL_TRUE);
}
break;
case 16:
switch (dst->format->Rmask) {
case 0xF800:
return SDL_BlendLine_RGB565(dst, x1, y1, x2, y2, blendMode, r, g,
b, a);
b, a, SDL_TRUE);
}
break;
case 32:
switch (dst->format->Rmask) {
case 0x00FF0000:
if (!dst->format->Amask) {
return SDL_BlendLine_RGB888(dst, x1, y1, x2, y2, blendMode, r,
g, b, a);
g, b, a, SDL_TRUE);
} else {
return SDL_BlendLine_ARGB8888(dst, x1, y1, x2, y2, blendMode,
r, g, b, a);
r, g, b, a, SDL_TRUE);
}
break;
}
@@ -246,9 +252,11 @@ SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
}

if (!dst->format->Amask) {
return SDL_BlendLine_RGB(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
return SDL_BlendLine_RGB(dst, x1, y1, x2, y2, blendMode,
r, g, b, a, SDL_TRUE);
} else {
return SDL_BlendLine_RGBA(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
return SDL_BlendLine_RGBA(dst, x1, y1, x2, y2, blendMode,
r, g, b, a, SDL_TRUE);
}
}

@@ -260,7 +268,8 @@ SDL_BlendLines(SDL_Surface * dst, const SDL_Point * points, int count,
int x1, y1;
int x2, y2;
int (*func)(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end) = NULL;
int status = 0;

if (!dst) {
@@ -328,7 +337,10 @@ SDL_BlendLines(SDL_Surface * dst, const SDL_Point * points, int count,
continue;
}

status = func(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
status = func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, SDL_FALSE);
}
if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
SDL_BlendPoint(dst, points[count-1].x, points[count-1].y, r, g, b, a);
}
return status;
}
@@ -0,0 +1,75 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"

#include "SDL_video.h"


int
SDL_BlendRect(SDL_Surface * dst, const SDL_Rect * rect,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
SDL_Rect full_rect;
SDL_Point points[5];

if (!dst) {
SDL_SetError("Passed NULL destination surface");
return -1;
}

/* If 'rect' == NULL, then outline the whole surface */
if (!rect) {
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = dst->w;
full_rect.h = dst->h;
rect = &full_rect;
}

points[0].x = rect->x;
points[0].y = rect->y;
points[1].x = rect->x+rect->w-1;
points[1].y = rect->y;
points[2].x = rect->x+rect->w-1;
points[2].y = rect->y+rect->h-1;
points[3].x = rect->x;
points[3].y = rect->y+rect->h-1;
points[4].x = rect->x;
points[4].y = rect->y;
return SDL_BlendLines(dst, points, 5, blendMode, r, g, b, a);
}

int
SDL_BlendRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
int i;

for (i = 0; i < count; ++i) {
if (SDL_BlendRect(dst, rects[i], blendMode, r, g, b, a) < 0) {
return -1;
}
}
return 0;
}

/* vi: set ts=4 sw=4 expandtab: */
@@ -283,7 +283,7 @@ do { \

#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))

#define BRESENHAM(x1, y1, x2, y2, op) \
#define BRESENHAM(x1, y1, x2, y2, op, draw_end) \
{ \
int i, deltax, deltay, numpixels; \
int d, dinc1, dinc2; \
@@ -325,6 +325,9 @@ do { \
x = x1; \
y = y1; \
\
if (!draw_end) { \
--numpixels; \
} \
for (i = 0; i < numpixels; ++i) { \
op(x, y); \
if (d < 0) { \
@@ -338,10 +341,11 @@ do { \
} \
} \
}
#define DRAWLINE(x0, y0, x1, y1, op) BRESENHAM(x0, y0, x1, y1, op)
#define DRAWLINE BRESENHAM

/*
* Define draw rect macro
* (not tested, this level of optimization not needed ... yet?)
*/
#define DRAWRECT(type, op) \
do { \

0 comments on commit cdf547e

Please sign in to comment.