1 /*
2 
3   SDL_gfxPrimitives - Graphics primitives for SDL surfaces
4 
5   Note: Does not lock or update surfaces. Implement in calling routine.
6 
7 */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <string.h>
13 
14 #include <SDL.h>
15 
16 #include "SDL_gfxPrimitives.h"
17 #include "SDL_gfxPrimitives_font.h"
18 
19 /* -===================- */
20 
21 /* Define this flag to use surface blits for alpha blended drawing. */
22 /* This is usually slower that direct surface calculations.         */
23 
24 #undef SURFACE_ALPHA_PIXEL
25 
26 /* ----- Defines for pixel clipping tests */
27 
28 #define clip_xmin(surface) surface->clip_rect.x
29 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
30 #define clip_ymin(surface) surface->clip_rect.y
31 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
32 
33 /* ----- Pixel - fast, no blending, no locking, clipping */
34 
fastPixelColorNolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)35 int fastPixelColorNolock (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color)
36 {
37   int bpp;
38   Uint8 *p;
39 
40   /* Honor clipping setup at pixel level */
41   if ( (x >= clip_xmin(dst)) &&
42        (x <= clip_xmax(dst)) &&
43        (y >= clip_ymin(dst)) &&
44        (y <= clip_ymax(dst)) ) {
45 
46     /* Get destination format */
47     bpp = dst->format->BytesPerPixel;
48     p = (Uint8 *)dst->pixels + y * dst->pitch + x * bpp;
49     switch(bpp) {
50     case 1:
51         *p = color;
52         break;
53     case 2:
54         *(Uint16 *)p = color;
55         break;
56     case 3:
57         if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
58             p[0] = (color >> 16) & 0xff;
59             p[1] = (color >> 8) & 0xff;
60             p[2] = color & 0xff;
61         } else {
62             p[0] = color & 0xff;
63             p[1] = (color >> 8) & 0xff;
64             p[2] = (color >> 16) & 0xff;
65         }
66         break;
67     case 4:
68         *(Uint32 *)p = color;
69         break;
70     } /* switch */
71 
72 
73   }
74 
75   return(0);
76 }
77 
78 /* ----- Pixel - fast, no blending, no locking, no clipping */
79 
80 /* (faster but dangerous, make sure we stay in surface bounds) */
81 
fastPixelColorNolockNoclip(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)82 int fastPixelColorNolockNoclip (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color)
83 {
84   int bpp;
85   Uint8 *p;
86 
87   /* Get destination format */
88   bpp = dst->format->BytesPerPixel;
89   p = (Uint8 *)dst->pixels + y * dst->pitch + x * bpp;
90   switch(bpp) {
91     case 1:
92         *p = color;
93         break;
94     case 2:
95         *(Uint16 *)p = color;
96         break;
97     case 3:
98         if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
99             p[0] = (color >> 16) & 0xff;
100             p[1] = (color >> 8) & 0xff;
101             p[2] = color & 0xff;
102         } else {
103             p[0] = color & 0xff;
104             p[1] = (color >> 8) & 0xff;
105             p[2] = (color >> 16) & 0xff;
106         }
107         break;
108     case 4:
109         *(Uint32 *)p = color;
110         break;
111   } /* switch */
112 
113   return(0);
114 }
115 
116 /* ----- Pixel - fast, no blending, locking, clipping */
117 
fastPixelColor(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)118 int fastPixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color)
119 {
120  int result;
121 
122  /* Lock the surface */
123  if ( SDL_MUSTLOCK(dst) ) {
124   if ( SDL_LockSurface(dst) < 0 ) {
125    return(-1);
126   }
127  }
128 
129  result=fastPixelColorNolock (dst,x,y,color);
130 
131  /* Unlock surface */
132  if ( SDL_MUSTLOCK(dst) ) {
133   SDL_UnlockSurface (dst);
134  }
135 
136  return(result);
137 }
138 
139 /* ----- Pixel - fast, no blending, locking, RGB input */
140 
fastPixelRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)141 int fastPixelRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
142 {
143  Uint32 color;
144 
145  /* Setup color */
146  color=SDL_MapRGBA(dst->format, r, g, b, a);
147 
148  /* Draw */
149  return(fastPixelColor(dst, x, y, color));
150 
151 }
152 
153 /* ----- Pixel - fast, no blending, no locking RGB input */
154 
fastPixelRGBANolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)155 int fastPixelRGBANolock (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
156 {
157  Uint32 color;
158 
159  /* Setup color */
160  color=SDL_MapRGBA(dst->format, r, g, b, a);
161 
162  /* Draw */
163  return(fastPixelColorNolock(dst, x, y, color));
164 }
165 
166 #ifdef SURFACE_ALPHA_PIXEL
167 
168 /* ----- Pixel - using single pixel blit with blending enabled if a<255 */
169 
170 static SDL_Surface *gfxPrimitivesSinglePixel=NULL;
171 
pixelColor(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)172 int pixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color)
173 {
174  SDL_Rect srect;
175  SDL_Rect drect;
176  int result;
177 
178  /* Setup source rectangle for pixel */
179  srect.x=0;
180  srect.y=0;
181  srect.w=1;
182  srect.h=1;
183 
184  /* Setup destination rectangle for pixel */
185  drect.x=x;
186  drect.y=y;
187  drect.w=1;
188  drect.h=1;
189 
190  /* Create single pixel in 32bit RGBA format */
191  if (gfxPrimitivesSinglePixel==NULL) {
192   gfxPrimitivesSinglePixel=SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, 1, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
193  }
194 
195  /* Draw color into pixel*/
196  SDL_FillRect (gfxPrimitivesSinglePixel, &srect, color);
197 
198  /* Draw pixel onto destination surface */
199  result=SDL_BlitSurface (gfxPrimitivesSinglePixel, &srect, dst, &drect);
200 
201  return(result);
202 }
203 
204 #else
205 
206 /* PutPixel routine with alpha blending, input color in destination format */
207 
_putPixelAlpha(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color,Uint8 alpha)208 int _putPixelAlpha(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
209 {
210  Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
211  Uint32 R,G,B,A = 0;
212 
213  if (x>=clip_xmin(surface) && x<=clip_xmax(surface) && y>=clip_ymin(surface) && y<=clip_ymax(surface)) {
214 
215   switch (surface->format->BytesPerPixel) {
216 			case 1: { /* Assuming 8-bpp */
217 				if( alpha == 255 ){
218 					*((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
219 				} else {
220 					Uint8 *pixel = (Uint8 *)surface->pixels + y*surface->pitch + x;
221 
222 					Uint8 dR = surface->format->palette->colors[*pixel].r;
223 					Uint8 dG = surface->format->palette->colors[*pixel].g;
224 					Uint8 dB = surface->format->palette->colors[*pixel].b;
225 					Uint8 sR = surface->format->palette->colors[color].r;
226 					Uint8 sG = surface->format->palette->colors[color].g;
227 					Uint8 sB = surface->format->palette->colors[color].b;
228 
229 					dR = dR + ((sR-dR)*alpha >> 8);
230 					dG = dG + ((sG-dG)*alpha >> 8);
231 					dB = dB + ((sB-dB)*alpha >> 8);
232 
233 					*pixel = SDL_MapRGB(surface->format, dR, dG, dB);
234 				}
235 			}
236 			break;
237 
238 			case 2: { /* Probably 15-bpp or 16-bpp */
239 				if ( alpha == 255 ) {
240 					*((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
241 				} else {
242 					Uint16 *pixel = (Uint16 *)surface->pixels + y*surface->pitch/2 + x;
243 					Uint32 dc = *pixel;
244 
245 					R = ((dc & Rmask) + (( (color & Rmask) - (dc & Rmask) ) * alpha >> 8)) & Rmask;
246 					G = ((dc & Gmask) + (( (color & Gmask) - (dc & Gmask) ) * alpha >> 8)) & Gmask;
247 					B = ((dc & Bmask) + (( (color & Bmask) - (dc & Bmask) ) * alpha >> 8)) & Bmask;
248 					if( Amask )
249 						A = ((dc & Amask) + (( (color & Amask) - (dc & Amask) ) * alpha >> 8)) & Amask;
250 
251 					*pixel= R | G | B | A;
252 				}
253 			}
254 			break;
255 
256 			case 3: { /* Slow 24-bpp mode, usually not used */
257 				Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
258 				Uint8 rshift8=surface->format->Rshift/8;
259 				Uint8 gshift8=surface->format->Gshift/8;
260 				Uint8 bshift8=surface->format->Bshift/8;
261 				Uint8 ashift8=surface->format->Ashift/8;
262 
263 
264 				if ( alpha == 255 ) {
265   					*(pix+rshift8) = color>>surface->format->Rshift;
266   					*(pix+gshift8) = color>>surface->format->Gshift;
267   					*(pix+bshift8) = color>>surface->format->Bshift;
268 					*(pix+ashift8) = color>>surface->format->Ashift;
269 				} else {
270 					Uint8 dR, dG, dB, dA=0;
271 					Uint8 sR, sG, sB, sA=0;
272 
273 					pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
274 
275 					dR = *((pix)+rshift8);
276             				dG = *((pix)+gshift8);
277             				dB = *((pix)+bshift8);
278 					dA = *((pix)+ashift8);
279 
280 					sR = (color>>surface->format->Rshift)&0xff;
281 					sG = (color>>surface->format->Gshift)&0xff;
282 					sB = (color>>surface->format->Bshift)&0xff;
283 					sA = (color>>surface->format->Ashift)&0xff;
284 
285 					dR = dR + ((sR-dR)*alpha >> 8);
286 					dG = dG + ((sG-dG)*alpha >> 8);
287 					dB = dB + ((sB-dB)*alpha >> 8);
288 					dA = dA + ((sA-dA)*alpha >> 8);
289 
290 					*((pix)+rshift8) = dR;
291             				*((pix)+gshift8) = dG;
292             				*((pix)+bshift8) = dB;
293 					*((pix)+ashift8) = dA;
294 				}
295 			}
296 			break;
297 
298 			case 4: { /* Probably 32-bpp */
299 				if ( alpha == 255 ) {
300 					*((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
301 				} else {
302 					Uint32 *pixel = (Uint32 *)surface->pixels + y*surface->pitch/4 + x;
303 					Uint32 dc = *pixel;
304 
305 					R = ((dc & Rmask) + (( (color & Rmask) - (dc & Rmask) ) * alpha >> 8)) & Rmask;
306 					G = ((dc & Gmask) + (( (color & Gmask) - (dc & Gmask) ) * alpha >> 8)) & Gmask;
307 					B = ((dc & Bmask) + (( (color & Bmask) - (dc & Bmask) ) * alpha >> 8)) & Bmask;
308 					if ( Amask )
309 						A = ((dc & Amask) + (( (color & Amask) - (dc & Amask) ) * alpha >> 8)) & Amask;
310 
311 					*pixel = R | G | B | A;
312 				}
313 			}
314 			break;
315   }
316  }
317 
318  return(0);
319 }
320 
321 /* ----- Pixel - pixel draw with blending enabled if a<255 */
322 
pixelColor(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)323 int pixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color)
324 {
325  Uint8 alpha;
326  Uint32 mcolor;
327  int result=0;
328 
329  /* Lock the surface */
330  if ( SDL_MUSTLOCK(dst) ) {
331   if ( SDL_LockSurface(dst) < 0 ) {
332    return(-1);
333   }
334  }
335 
336  /* Setup color */
337  alpha=color &0x000000ff;
338  mcolor=SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
339 
340  /* Draw */
341  result = _putPixelAlpha(dst,x,y,mcolor,alpha);
342 
343  /* Unlock the surface */
344  if (SDL_MUSTLOCK(dst) ) {
345   SDL_UnlockSurface(dst);
346  }
347 
348  return(result);
349 }
350 
351 
352 /* Filled rectangle with alpha blending, color in destination format */
353 
_filledRectAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)354 int _filledRectAlpha (SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
355 {
356  Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
357  Uint32 R,G,B,A=0;
358  Sint16 x,y;
359 
360  switch (surface->format->BytesPerPixel) {
361 		case 1: { /* Assuming 8-bpp */
362 			Uint8 *row, *pixel;
363 			Uint8 dR, dG, dB;
364 
365 			Uint8 sR = surface->format->palette->colors[color].r;
366 			Uint8 sG = surface->format->palette->colors[color].g;
367 			Uint8 sB = surface->format->palette->colors[color].b;
368 
369 			for(y = y1; y<=y2; y++){
370 				row = (Uint8 *)surface->pixels + y*surface->pitch;
371 				for(x = x1; x <= x2; x++){
372 					pixel = row + x;
373 
374 					dR = surface->format->palette->colors[*pixel].r;
375 					dG = surface->format->palette->colors[*pixel].g;
376 					dB = surface->format->palette->colors[*pixel].b;
377 
378 					dR = dR + ((sR-dR)*alpha >> 8);
379 					dG = dG + ((sG-dG)*alpha >> 8);
380 					dB = dB + ((sB-dB)*alpha >> 8);
381 
382 					*pixel = SDL_MapRGB(surface->format, dR, dG, dB);
383 				}
384 			}
385 		}
386 		break;
387 
388 		case 2: { /* Probably 15-bpp or 16-bpp */
389 			Uint16 *row, *pixel;
390 			Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask);
391 
392 			for(y = y1; y<=y2; y++){
393 				row = (Uint16 *)surface->pixels + y*surface->pitch/2;
394 				for(x = x1; x <= x2; x++){
395 					pixel = row + x;
396 
397 					R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask;
398 					G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask;
399 					B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask;
400 					if( Amask )
401 						A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask;
402 
403 					*pixel= R | G | B | A;
404 				}
405 			}
406 		}
407 		break;
408 
409 		case 3: { /* Slow 24-bpp mode, usually not used */
410 			Uint8 *row,*pix;
411 			Uint8 dR, dG, dB, dA;
412   			Uint8 rshift8=surface->format->Rshift/8;
413 			Uint8 gshift8=surface->format->Gshift/8;
414 			Uint8 bshift8=surface->format->Bshift/8;
415 			Uint8 ashift8=surface->format->Ashift/8;
416 
417 			Uint8 sR = (color>>surface->format->Rshift)&0xff;
418 			Uint8 sG = (color>>surface->format->Gshift)&0xff;
419 			Uint8 sB = (color>>surface->format->Bshift)&0xff;
420 			Uint8 sA = (color>>surface->format->Ashift)&0xff;
421 
422 			for(y = y1; y<=y2; y++){
423 				row = (Uint8 *)surface->pixels + y * surface->pitch;
424 				for(x = x1; x <= x2; x++){
425 					pix = row + x*3;
426 
427 					dR = *((pix)+rshift8);
428             				dG = *((pix)+gshift8);
429             				dB = *((pix)+bshift8);
430 					dA = *((pix)+ashift8);
431 
432 					dR = dR + ((sR-dR)*alpha >> 8);
433 					dG = dG + ((sG-dG)*alpha >> 8);
434 					dB = dB + ((sB-dB)*alpha >> 8);
435 					dA = dA + ((sA-dA)*alpha >> 8);
436 
437 					*((pix)+rshift8) = dR;
438             				*((pix)+gshift8) = dG;
439             				*((pix)+bshift8) = dB;
440 					*((pix)+ashift8) = dA;
441 				}
442 			}
443 
444 		}
445 		break;
446 
447 		case 4: { /* Probably 32-bpp */
448 			Uint32 *row, *pixel;
449 			Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask);
450 
451 			for(y = y1; y<=y2; y++){
452 				row = (Uint32 *)surface->pixels + y*surface->pitch/4;
453 				for(x = x1; x <= x2; x++){
454 					pixel = row + x;
455 
456 					R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask;
457 					G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask;
458 					B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask;
459 					if( Amask )
460 						A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask;
461 
462 					*pixel= R | G | B | A;
463 				}
464 			}
465 		}
466 		break;
467  }
468 
469  return(0);
470 }
471 
472 /* Draw rectangle with alpha enabled from RGBA color. */
473 
filledRectAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)474 int filledRectAlpha (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
475 {
476  Uint8 alpha;
477  Uint32 mcolor;
478  int result=0;
479 
480  /* Lock the surface */
481  if ( SDL_MUSTLOCK(dst) ) {
482   if ( SDL_LockSurface(dst) < 0 ) {
483    return(-1);
484   }
485  }
486 
487  /* Setup color */
488  alpha = color & 0x000000ff;
489  mcolor=SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
490 
491  /* Draw */
492  result = _filledRectAlpha(dst,x1,y1,x2,y2,mcolor,alpha);
493 
494  /* Unlock the surface */
495  if (SDL_MUSTLOCK(dst) ) {
496   SDL_UnlockSurface(dst);
497  }
498 
499  return(result);
500 }
501 
502 /* Draw horizontal line with alpha enabled from RGBA color */
503 
HLineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)504 int HLineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
505 {
506  return (filledRectAlpha(dst, x1, y, x2, y, color));
507 }
508 
509 
510 /* Draw vertical line with alpha enabled from RGBA color */
511 
VLineAlpha(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)512 int VLineAlpha(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
513 {
514  return (filledRectAlpha(dst, x, y1, x, y2, color));
515 }
516 
517 #endif
518 
519 
520 /* Pixel - using alpha weight on color for AA-drawing */
521 
pixelColorWeight(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint32 weight)522 int pixelColorWeight (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
523 {
524  Uint32 a;
525 
526  /* Get alpha */
527  a=(color & (Uint32)0x000000ff);
528 
529  /* Modify Alpha by weight */
530  a = ((a*weight) >> 8);
531 
532  return(pixelColor (dst,x,y, (color & (Uint32)0xffffff00) | (Uint32)a ));
533 }
534 
pixelRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)535 int pixelRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
536 {
537  Uint32 color;
538 
539  /* Check Alpha */
540  if (a==255) {
541   /* No alpha blending required */
542   /* Setup color */
543   color=SDL_MapRGBA(dst->format, r, g, b, a);
544   /* Draw */
545   return(fastPixelColor (dst, x, y, color));
546  } else {
547   /* Alpha blending required */
548   /* Draw */
549   return(pixelColor (dst, x, y, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a ));
550  }
551 }
552 
553 /* ----- Horizontal line */
554 
555 #ifdef SURFACE_ALPHA_PIXEL
556  static SDL_Surface *gfxPrimitivesHline=NULL;
557 #endif
558 
hlineColor(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)559 int hlineColor (SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
560 {
561  Sint16 left,right,top,bottom;
562  Uint8 *pixel,*pixellast;
563  int dx;
564  int pixx, pixy;
565  Sint16 w;
566  Sint16 xtmp;
567  int result=-1;
568  Uint8 *colorptr;
569 #ifdef SURFACE_ALPHA_PIXEL
570  Uint32 a;
571  SDL_Rect srect;
572  SDL_Rect drect;
573 #endif
574 
575  /* Get clipping boundary */
576  left = dst->clip_rect.x;
577  right = dst->clip_rect.x+dst->clip_rect.w-1;
578  top = dst->clip_rect.y;
579  bottom = dst->clip_rect.y+dst->clip_rect.h-1;
580 
581  /* Swap x1, x2 if required */
582  if (x1>x2) {
583   xtmp=x1; x1=x2; x2=xtmp;
584  }
585 
586  /* Visible */
587  if ((x1>right) || (x2<left) || (y<top) || (y>bottom)) {
588   return(0);
589  }
590 
591  /* Clip x */
592  if (x1<left) {
593   x1=left;
594  }
595  if (x2>right) {
596   x2=right;
597  }
598 
599  /* Calculate width */
600  w=x2-x1;
601 
602  /* Sanity check on width */
603  if (w<0) {
604   return(0);
605  }
606 
607  /* Alpha check */
608  if ((color & 255)==255) {
609 
610   /* No alpha-blending required */
611 
612   /* Setup color */
613   colorptr=(Uint8 *)&color;
614   if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
615    color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
616   } else {
617    color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
618   }
619 
620   /* Lock surface */
621   SDL_LockSurface(dst);
622 
623   /* More variable setup */
624   dx=w;
625   pixx = dst->format->BytesPerPixel;
626   pixy = dst->pitch;
627   pixel = ((Uint8*)dst->pixels) + pixx * (int)x1 + pixy * (int)y;
628 
629   /* Draw */
630   switch(dst->format->BytesPerPixel) {
631    case 1:
632     memset (pixel, color, dx);
633     break;
634    case 2:
635     pixellast = pixel + dx + dx;
636     for (; pixel<=pixellast; pixel += pixx) {
637      *(Uint16*)pixel = color;
638     }
639     break;
640    case 3:
641     pixellast = pixel + dx + dx + dx;
642     for (; pixel<=pixellast; pixel += pixx) {
643      if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
644       pixel[0] = (color >> 16) & 0xff;
645       pixel[1] = (color >> 8) & 0xff;
646       pixel[2] = color & 0xff;
647      } else {
648       pixel[0] = color & 0xff;
649       pixel[1] = (color >> 8) & 0xff;
650       pixel[2] = (color >> 16) & 0xff;
651      }
652     }
653     break;
654    default: /* case 4*/
655     dx = dx + dx;
656     pixellast = pixel + dx + dx;
657     for (; pixel<=pixellast; pixel += pixx) {
658      *(Uint32*)pixel = color;
659     }
660     break;
661   }
662 
663   /* Unlock surface */
664   SDL_UnlockSurface(dst);
665 
666   /* Set result code */
667   result=0;
668 
669  } else {
670 
671   /* Alpha blending blit */
672 
673 #ifdef SURFACE_ALPHA_PIXEL
674 
675   /* Adjust width for Rect setup */
676   w++;
677 
678   /* Setup source rectangle for pixel */
679   srect.x=0;
680   srect.y=0;
681   srect.w=w;
682   srect.h=1;
683 
684   /* Setup rectangle for destination line */
685   drect.x=x1;
686   drect.y=y;
687   drect.w=w;
688   drect.h=1;
689 
690   /* Maybe deallocate existing surface if size is too small */
691   if ((gfxPrimitivesHline!=NULL) && (gfxPrimitivesHline->w<w) ) {
692    SDL_FreeSurface(gfxPrimitivesHline);
693    gfxPrimitivesHline=NULL;
694   }
695 
696   /* Create horizontal line surface in destination format if necessary */
697   if (gfxPrimitivesHline==NULL) {
698    gfxPrimitivesHline=SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, w, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
699   }
700 
701   /* Get alpha */
702   a=(color & (Uint32)0x000000ff);
703 
704   /* Toggle alpha blending if necessary, reset otherwise */
705   if (a != 255) {
706    SDL_SetAlpha (gfxPrimitivesHline, SDL_SRCALPHA, 255);
707   } else {
708    SDL_SetAlpha (gfxPrimitivesHline, 0, 255);
709   }
710 
711   /* Draw color into pixel*/
712   SDL_FillRect (gfxPrimitivesHline, &srect, color);
713 
714   /* Draw pixel onto destination surface */
715   result=SDL_BlitSurface (gfxPrimitivesHline, &srect, dst, &drect);
716 
717 #else
718 
719  result=HLineAlpha (dst, x1, x1+w, y, color);
720 
721 #endif
722 
723  }
724 
725  return(result);
726 }
727 
hlineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)728 int hlineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
729 {
730  /* Draw */
731  return(hlineColor(dst, x1, x2, y, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
732 }
733 
734 /* ----- Vertical line */
735 
736 #ifdef SURFACE_ALPHA_PIXEL
737  static SDL_Surface *gfxPrimitivesVline=NULL;
738 #endif
739 
vlineColor(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)740 int vlineColor (SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
741 {
742  Sint16 left,right,top,bottom;
743  Uint8 *pixel, *pixellast;
744  int dy;
745  int pixx, pixy;
746  Sint16 h;
747  Sint16 ytmp;
748  int result=-1;
749  Uint8 *colorptr;
750 #ifdef SURFACE_ALPHA_PIXEL
751  SDL_Rect srect;
752  SDL_Rect drect;
753  Uint32 a;
754 #endif
755 
756  /* Get clipping boundary */
757  left = dst->clip_rect.x;
758  right = dst->clip_rect.x+dst->clip_rect.w-1;
759  top = dst->clip_rect.y;
760  bottom = dst->clip_rect.y+dst->clip_rect.h-1;
761 
762  /* Swap y1, y2 if required */
763  if (y1>y2) {
764   ytmp=y1; y1=y2; y2=ytmp;
765  }
766 
767  /* Visible */
768  if ((y2<top) || (y1>bottom) || (x<left) || (x>right)) {
769   return(0);
770  }
771 
772  /* Clip y */
773  if (y1<top) {
774   y1=top;
775  }
776  if (y2>bottom) {
777   y2=bottom;
778  }
779 
780  /* Calculate height */
781  h=y2-y1;
782 
783  /* Sanity check on height */
784  if (h<0) {
785   return(0);
786  }
787 
788  /* Alpha check */
789  if ((color & 255)==255) {
790 
791   /* No alpha-blending required */
792 
793   /* Setup color */
794   colorptr=(Uint8 *)&color;
795   if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
796    color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
797   } else {
798    color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
799   }
800 
801   /* Lock surface */
802   SDL_LockSurface(dst);
803 
804   /* More variable setup */
805   dy=h;
806   pixx = dst->format->BytesPerPixel;
807   pixy = dst->pitch;
808   pixel = ((Uint8*)dst->pixels) + pixx * (int)x + pixy * (int)y1;
809   pixellast = pixel + pixy*dy;
810 
811   /* Draw */
812   switch(dst->format->BytesPerPixel) {
813    case 1:
814     for (; pixel<=pixellast; pixel += pixy) {
815      *(Uint8*)pixel = color;
816     }
817     break;
818    case 2:
819     for (; pixel<=pixellast; pixel += pixy) {
820      *(Uint16*)pixel = color;
821     }
822     break;
823    case 3:
824     for (; pixel<=pixellast; pixel += pixy) {
825      if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
826       pixel[0] = (color >> 16) & 0xff;
827       pixel[1] = (color >> 8) & 0xff;
828       pixel[2] = color & 0xff;
829      } else {
830       pixel[0] = color & 0xff;
831       pixel[1] = (color >> 8) & 0xff;
832       pixel[2] = (color >> 16) & 0xff;
833      }
834     }
835     break;
836    default: /* case 4*/
837     for (; pixel<=pixellast; pixel += pixy) {
838      *(Uint32*)pixel = color;
839     }
840     break;
841   }
842 
843   /* Unlock surface */
844   SDL_UnlockSurface(dst);
845 
846   /* Set result code */
847   result=0;
848 
849  } else {
850 
851   /* Alpha blending blit */
852 
853 #ifdef SURFACE_ALPHA_PIXEL
854 
855   /* Adjust height for Rect setup */
856   h++;
857 
858   /* Setup source rectangle for pixel */
859   srect.x=0;
860   srect.y=0;
861   srect.w=1;
862   srect.h=h;
863 
864   /* Setup rectangle for line */
865   drect.x=x;
866   drect.y=y1;
867   drect.w=1;
868   drect.h=h;
869 
870   /* Maybe deallocate existing surface if size is too small */
871   if ( (gfxPrimitivesVline!=NULL) && (gfxPrimitivesVline->h<h) ) {
872    SDL_FreeSurface(gfxPrimitivesVline);
873    gfxPrimitivesVline=NULL;
874   }
875 
876   /* Create horizontal line surface in destination format if necessary */
877   if (gfxPrimitivesVline==NULL) {
878    gfxPrimitivesVline=SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, 1, h, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
879   }
880 
881   /* Get alpha */
882   a=(color & (Uint32)0x000000ff);
883 
884   /* Toggle alpha blending if necessary, reset otherwise */
885   if (a != 255) {
886    SDL_SetAlpha (gfxPrimitivesVline, SDL_SRCALPHA, 255);
887   } else {
888    SDL_SetAlpha (gfxPrimitivesVline, 0, 255);
889   }
890 
891   /* Draw color into pixel*/
892   SDL_FillRect (gfxPrimitivesVline, &srect, color);
893 
894   /* Draw Vline onto destination surface */
895   result=SDL_BlitSurface (gfxPrimitivesVline, &srect, dst, &drect);
896 
897 #else
898 
899  result=VLineAlpha(dst,x, y1, y1+h, color);
900 
901 #endif
902 
903  }
904 
905  return(result);
906 }
907 
vlineRGBA(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)908 int vlineRGBA (SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
909 {
910  /* Draw */
911  return(vlineColor(dst, x, y1, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
912 }
913 
914 /* ----- Rectangle */
915 
rectangleColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)916 int rectangleColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
917 {
918  int result;
919  Sint16 w,h, xtmp, ytmp;
920 
921 
922  /* Swap x1, x2 if required */
923  if (x1>x2) {
924   xtmp=x1; x1=x2; x2=xtmp;
925  }
926 
927  /* Swap y1, y2 if required */
928  if (y1>y2) {
929   ytmp=y1; y1=y2; y2=ytmp;
930  }
931 
932  /* Calculate width&height */
933  w=x2-x1;
934  h=y2-y1;
935 
936  /* Sanity check */
937  if ((w<0) || (h<0)) {
938   return(0);
939  }
940 
941  /* Test for special cases of straight lines or single point */
942  if (x1==x2) {
943   if (y1==y2) {
944    return(pixelColor(dst, x1, y1, color));
945   } else {
946    return(vlineColor(dst, x1, y1, y2, color));
947   }
948  } else {
949   if (y1==y2) {
950    return(hlineColor(dst, x1, x2, y1, color));
951   }
952  }
953 
954  /* Draw rectangle */
955  result=0;
956  result |= vlineColor(dst, x1, y1, y2, color);
957  result |= vlineColor(dst, x2, y1, y2, color);
958  result |= hlineColor(dst, x1, x2, y1, color);
959  result |= hlineColor(dst, x1, x2, y2, color);
960 
961  return(result);
962 
963 }
964 
rectangleRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)965 int rectangleRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
966 {
967  /* Draw */
968  return(rectangleColor(dst, x1, y1, x2, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
969 }
970 
971 /* --------- Clipping routines for box/line */
972 
973 /* Clipping based heavily on code from                       */
974 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
975 
976 #define CLIP_LEFT_EDGE   0x1
977 #define CLIP_RIGHT_EDGE  0x2
978 #define CLIP_BOTTOM_EDGE 0x4
979 #define CLIP_TOP_EDGE    0x8
980 #define CLIP_INSIDE(a)   (!a)
981 #define CLIP_REJECT(a,b) (a&b)
982 #define CLIP_ACCEPT(a,b) (!(a|b))
983 
clipEncode(Sint16 x,Sint16 y,Sint16 left,Sint16 top,Sint16 right,Sint16 bottom)984 static int clipEncode (Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
985 {
986  int code = 0;
987  if (x < left) {
988   code |= CLIP_LEFT_EDGE;
989  } else if (x > right) {
990   code |= CLIP_RIGHT_EDGE;
991  }
992  if (y < top) {
993   code |= CLIP_TOP_EDGE;
994  } else if (y > bottom) {
995   code |= CLIP_BOTTOM_EDGE;
996  }
997  return code;
998 }
999 
clipLine(SDL_Surface * dst,Sint16 * x1,Sint16 * y1,Sint16 * x2,Sint16 * y2)1000 static int clipLine(SDL_Surface *dst, Sint16 *x1, Sint16 *y1, Sint16 *x2, Sint16 *y2)
1001 {
1002  Sint16 left,right,top,bottom;
1003  int code1, code2;
1004  int draw = 0;
1005  Sint16 swaptmp;
1006  float m;
1007 
1008  /* Get clipping boundary */
1009  left = dst->clip_rect.x;
1010  right = dst->clip_rect.x+dst->clip_rect.w-1;
1011  top = dst->clip_rect.y;
1012  bottom = dst->clip_rect.y+dst->clip_rect.h-1;
1013 
1014  while (1) {
1015   code1 = clipEncode (*x1, *y1, left, top, right, bottom);
1016   code2 = clipEncode (*x2, *y2, left, top, right, bottom);
1017   if (CLIP_ACCEPT(code1, code2)) {
1018    draw = 1;
1019    break;
1020   } else if (CLIP_REJECT(code1, code2))
1021    break;
1022   else {
1023    if(CLIP_INSIDE (code1)) {
1024     swaptmp = *x2; *x2 = *x1; *x1 = swaptmp;
1025     swaptmp = *y2; *y2 = *y1; *y1 = swaptmp;
1026     swaptmp = code2; code2 = code1; code1 = swaptmp;
1027    }
1028    if (*x2 != *x1) {
1029     m = (*y2 - *y1) / (float)(*x2 - *x1);
1030    } else {
1031     m = 1.0f;
1032    }
1033    if (code1 & CLIP_LEFT_EDGE) {
1034     *y1 += (Sint16)((left - *x1) * m);
1035     *x1 = left;
1036    } else if (code1 & CLIP_RIGHT_EDGE) {
1037     *y1 += (Sint16)((right - *x1) * m);
1038     *x1 = right;
1039    } else if (code1 & CLIP_BOTTOM_EDGE) {
1040     if (*x2 != *x1) {
1041      *x1 += (Sint16)((bottom - *y1) / m);
1042     }
1043     *y1 = bottom;
1044    } else if (code1 & CLIP_TOP_EDGE) {
1045     if (*x2 != *x1) {
1046      *x1 += (Sint16)((top - *y1) / m);
1047     }
1048     *y1 = top;
1049    }
1050   }
1051  }
1052 
1053  return draw;
1054 }
1055 
1056 /* ----- Filled rectangle (Box) */
1057 
1058 #ifdef SURFACE_ALPHA_PIXEL
1059  static SDL_Surface *gfxPrimitivesBox=NULL;
1060 #endif
1061 
boxColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1062 int boxColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1063 {
1064  Uint8 *pixel, *pixellast;
1065  int x, dx;
1066  int dy;
1067  int pixx, pixy;
1068  Sint16 w,h,tmp;
1069  int result;
1070  Uint8 *colorptr;
1071 #ifdef SURFACE_ALPHA_PIXEL
1072  Uint32 a;
1073  SDL_Rect srect;
1074  SDL_Rect drect;
1075 #endif
1076 
1077  /* Clip diagonal and test if we have to draw */
1078  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
1079   return(0);
1080  }
1081 
1082  /* Test for special cases of straight lines or single point */
1083  if (x1==x2) {
1084   if (y1<y2) {
1085    return(vlineColor(dst, x1, y1, y2, color));
1086   } else if (y1>y2) {
1087    return(vlineColor(dst, x1, y2, y1, color));
1088   } else {
1089    return(pixelColor(dst, x1, y1, color));
1090   }
1091  }
1092  if (y1==y2) {
1093   if (x1<x2) {
1094    return(hlineColor(dst, x1, x2, y1, color));
1095   } else if (x1>x2) {
1096    return(hlineColor(dst, x2, x1, y1, color));
1097   }
1098  }
1099 
1100  /* Order coordinates */
1101  if (x1>x2) {
1102   tmp=x1;
1103   x1=x2;
1104   x2=tmp;
1105  }
1106  if (y1>y2) {
1107   tmp=y1;
1108   y1=y2;
1109   y2=tmp;
1110  }
1111 
1112  /* Calculate width&height */
1113  w=x2-x1;
1114  h=y2-y1;
1115 
1116  /* Alpha check */
1117  if ((color & 255)==255) {
1118 
1119   /* No alpha-blending required */
1120 
1121   /* Setup color */
1122   colorptr=(Uint8 *)&color;
1123   if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1124    color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1125   } else {
1126    color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1127   }
1128 
1129   /* Lock surface */
1130   SDL_LockSurface(dst);
1131 
1132   /* More variable setup */
1133   dx=w;
1134   dy=h;
1135   pixx = dst->format->BytesPerPixel;
1136   pixy = dst->pitch;
1137   pixel = ((Uint8*)dst->pixels) + pixx * (int)x1 + pixy * (int)y1;
1138   pixellast = pixel + pixx*dx + pixy*dy;
1139 
1140   /* Draw */
1141   switch(dst->format->BytesPerPixel) {
1142    case 1:
1143     for (; pixel<=pixellast; pixel += pixy) {
1144      memset(pixel,(Uint8)color,dx);
1145     }
1146     break;
1147    case 2:
1148     pixy -= (pixx*dx);
1149     for (; pixel<=pixellast; pixel += pixy) {
1150      for (x=0; x<dx; x++) {
1151       *(Uint16*)pixel = color;
1152       pixel += pixx;
1153      }
1154     }
1155     break;
1156    case 3:
1157     pixy -= (pixx*dx);
1158     for (; pixel<=pixellast; pixel += pixy) {
1159      for (x=0; x<dx; x++) {
1160       if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1161        pixel[0] = (color >> 16) & 0xff;
1162        pixel[1] = (color >> 8) & 0xff;
1163        pixel[2] = color & 0xff;
1164       } else {
1165        pixel[0] = color & 0xff;
1166        pixel[1] = (color >> 8) & 0xff;
1167        pixel[2] = (color >> 16) & 0xff;
1168       }
1169       pixel += pixx;
1170      }
1171     }
1172     break;
1173    default: /* case 4*/
1174     pixy -= (pixx*dx);
1175     for (; pixel<=pixellast; pixel += pixy) {
1176      for (x=0; x<dx; x++) {
1177       *(Uint32*)pixel = color;
1178       pixel += pixx;
1179      }
1180     }
1181     break;
1182   }
1183 
1184   /* Unlock surface */
1185   SDL_UnlockSurface(dst);
1186 
1187   result=0;
1188 
1189  } else {
1190 
1191 #ifdef SURFACE_ALPHA_PIXEL
1192 
1193   /* Setup source rectangle for pixel */
1194   srect.x=0;
1195   srect.y=0;
1196   srect.w=w;
1197   srect.h=h;
1198 
1199   /* Setup rectangle for line */
1200   drect.x=x1;
1201   drect.y=y1;
1202   drect.w=w;
1203   drect.h=h;
1204 
1205   /* Maybe deallocate existing surface if size is too small */
1206   if ((gfxPrimitivesBox!=NULL) && ((gfxPrimitivesBox->w<w) || (gfxPrimitivesBox->h<h))) {
1207    SDL_FreeSurface(gfxPrimitivesBox);
1208    gfxPrimitivesBox=NULL;
1209   }
1210 
1211   /* Create box surface in destination format if necessary */
1212   if (gfxPrimitivesBox==NULL) {
1213    gfxPrimitivesBox=SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, w, h, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
1214   }
1215 
1216   /* Get alpha */
1217   a=(color & (Uint32)0x000000ff);
1218 
1219   /* Toggle alpha blending if necessary, reset otherwise */
1220   if (a != 255) {
1221    SDL_SetAlpha (gfxPrimitivesBox, SDL_SRCALPHA, 255);
1222   } else {
1223    SDL_SetAlpha (gfxPrimitivesBox, 0, 255);
1224   }
1225 
1226   /* Draw color into pixel*/
1227   SDL_FillRect (gfxPrimitivesBox, &srect, color);
1228 
1229   /* Draw pixel onto destination surface */
1230   result=SDL_BlitSurface (gfxPrimitivesBox, &srect, dst, &drect);
1231 
1232 #else
1233 
1234  result=filledRectAlpha(dst,x1,y1,x1+w,y1+h,color);
1235 
1236 #endif
1237 
1238  }
1239 
1240  return(result);
1241 }
1242 
boxRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1243 int boxRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1,  Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1244 {
1245  /* Draw */
1246  return(boxColor(dst, x1, y1, x2, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
1247 }
1248 
1249 /* ----- Line */
1250 
1251 /* Non-alpha line drawing code adapted from routine          */
1252 /* by Pete Shinners, pete@shinners.org                       */
1253 /* Originally from pygame, http://pygame.seul.org            */
1254 
1255 #define ABS(a) (((a)<0) ? -(a) : (a))
1256 
lineColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1257 int lineColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1258 {
1259  int pixx, pixy;
1260  int x,y;
1261  int dx,dy;
1262  int ax,ay;
1263  int sx,sy;
1264  int swaptmp;
1265  Uint8 *pixel;
1266  Uint8 *colorptr;
1267 
1268  /* Clip line and test if we have to draw */
1269  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
1270   return(0);
1271  }
1272 
1273  /* Test for special cases of straight lines or single point */
1274  if (x1==x2) {
1275   if (y1<y2) {
1276    return(vlineColor(dst, x1, y1, y2, color));
1277   } else if (y1>y2) {
1278    return(vlineColor(dst, x1, y2, y1, color));
1279   } else {
1280    return(pixelColor(dst, x1, y1, color));
1281   }
1282  }
1283  if (y1==y2) {
1284   if (x1<x2) {
1285    return(hlineColor(dst, x1, x2, y1, color));
1286   } else if (x1>x2) {
1287    return(hlineColor(dst, x2, x1, y1, color));
1288   }
1289  }
1290 
1291  /* Variable setup */
1292  dx = x2 - x1;
1293  dy = y2 - y1;
1294  sx = (dx >= 0) ? 1 : -1;
1295  sy = (dy >= 0) ? 1 : -1;
1296 
1297  /* Check for alpha blending */
1298  if ((color & 255)==255) {
1299 
1300   /* No alpha blending - use fast pixel routines */
1301 
1302   /* Setup color */
1303   colorptr=(Uint8 *)&color;
1304   if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1305    color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1306   } else {
1307    color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1308   }
1309 
1310   /* Lock surface */
1311   SDL_LockSurface(dst);
1312 
1313   /* More variable setup */
1314   dx = sx * dx + 1;
1315   dy = sy * dy + 1;
1316   pixx = dst->format->BytesPerPixel;
1317   pixy = dst->pitch;
1318   pixel = ((Uint8*)dst->pixels) + pixx * (int)x1 + pixy * (int)y1;
1319   pixx *= sx;
1320   pixy *= sy;
1321   if (dx < dy) {
1322    swaptmp = dx; dx = dy; dy = swaptmp;
1323    swaptmp = pixx; pixx = pixy; pixy = swaptmp;
1324   }
1325 
1326   /* Draw */
1327   x=0;
1328   y=0;
1329   switch(dst->format->BytesPerPixel) {
1330    case 1:
1331     for(; x < dx; x++, pixel += pixx) {
1332      *pixel = color;
1333      y += dy;
1334      if (y >= dx) {
1335       y -= dx; pixel += pixy;
1336      }
1337     }
1338     break;
1339    case 2:
1340     for (; x < dx; x++, pixel += pixx) {
1341      *(Uint16*)pixel = color;
1342      y += dy;
1343      if (y >= dx) {
1344       y -= dx;
1345       pixel += pixy;
1346      }
1347     }
1348     break;
1349    case 3:
1350     for(; x < dx; x++, pixel += pixx) {
1351      if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1352       pixel[0] = (color >> 16) & 0xff;
1353       pixel[1] = (color >> 8) & 0xff;
1354       pixel[2] = color & 0xff;
1355      } else {
1356       pixel[0] = color & 0xff;
1357       pixel[1] = (color >> 8) & 0xff;
1358       pixel[2] = (color >> 16) & 0xff;
1359      }
1360      y += dy;
1361      if (y >= dx) {
1362       y -= dx;
1363       pixel += pixy;
1364      }
1365     }
1366     break;
1367    default: /* case 4 */
1368      for(; x < dx; x++, pixel += pixx) {
1369       *(Uint32*)pixel = color;
1370       y += dy;
1371       if (y >= dx) {
1372        y -= dx;
1373        pixel += pixy;
1374       }
1375      }
1376      break;
1377   }
1378 
1379   /* Unlock surface */
1380   SDL_UnlockSurface(dst);
1381 
1382  } else {
1383 
1384   /* Alpha blending required - use single-pixel blits */
1385 
1386   ax = ABS(dx) << 1;
1387   ay = ABS(dy) << 1;
1388   x = x1;
1389   y = y1;
1390   if (ax > ay) {
1391     int d = ay - (ax >> 1);
1392     while (x != x2) {
1393      pixelColor(dst, x, y, color);
1394      if (d > 0 || (d == 0 && sx == 1)) {
1395       y += sy;
1396       d -= ax;
1397      }
1398      x += sx;
1399      d += ay;
1400     }
1401   } else {
1402     int d = ax - (ay >> 1);
1403     while (y != y2) {
1404      pixelColor(dst, x, y, color);
1405      if (d > 0 || ((d == 0) && (sy == 1))) {
1406       x += sx;
1407       d -= ay;
1408      }
1409      y += sy;
1410      d += ax;
1411     }
1412   }
1413   pixelColor(dst, x, y, color);
1414 
1415  }
1416 
1417  return(0);
1418 }
1419 
lineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1420 int lineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1421 {
1422  /* Draw */
1423  return(lineColor(dst, x1, y1, x2, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
1424 }
1425 
1426 /* AA Line */
1427 
1428 #define AAlevels 256
1429 #define AAbits 8
1430 
1431 /*
1432 
1433 This implementation of the Wu antialiasing code is based on Mike Abrash's
1434 DDJ article which was reprinted as Chapter 42 of his Graphics Programming
1435 Black Book, but has been optimized to work with SDL and utilizes 32-bit
1436 fixed-point arithmetic. (A. Schiffler).
1437 
1438 */
1439 
aalineColorInt(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,int draw_endpoint)1440 int aalineColorInt (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
1441 {
1442  Sint32 xx0,yy0,xx1,yy1;
1443  int result;
1444  Uint32 intshift, erracc, erradj;
1445  Uint32 erracctmp, wgt, wgtcompmask;
1446  int dx, dy, tmp, xdir, y0p1, x0pxdir;
1447 
1448  /* Clip line and test if we have to draw */
1449  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
1450   return(0);
1451  }
1452 
1453  /* Keep on working with 32bit numbers */
1454  xx0=x1;
1455  yy0=y1;
1456  xx1=x2;
1457  yy1=y2;
1458 
1459  /* Reorder points if required */
1460  if (yy0 > yy1) {
1461   tmp = yy0; yy0 = yy1; yy1 = tmp;
1462   tmp = xx0; xx0 = xx1; xx1 = tmp;
1463  }
1464 
1465  /* Calculate distance */
1466  dx = xx1 - xx0;
1467  dy = yy1 - yy0;
1468 
1469  /* Adjust for negative dx and set xdir */
1470  if (dx >= 0) {
1471    xdir=1;
1472  } else {
1473    xdir=-1;
1474    dx=(-dx);
1475  }
1476 
1477  /* Check for special cases */
1478  if (dx==0) {
1479    /* Vertical line */
1480    return (vlineColor(dst,x1,y1,y2,color));
1481  } else if (dy==0) {
1482    /* Horizontal line */
1483    return (hlineColor(dst,x1,x2,y1,color));
1484  } else if (dx==dy) {
1485    /* Diagonal line */
1486    return (lineColor(dst,x1,y1,x2,y2,color));
1487  }
1488 
1489   /* Line is not horizontal, vertical or diagonal */
1490   result=0;
1491   /* Zero accumulator */
1492   erracc = 0;
1493   /* # of bits by which to shift erracc to get intensity level */
1494   intshift = 32 - AAbits;
1495   /* Mask used to flip all bits in an intensity weighting */
1496   wgtcompmask = AAlevels - 1;
1497 
1498   /* Draw the initial pixel in the foreground color */
1499   result |= pixelColor (dst, x1, y1, color);
1500 
1501   /* x-major or y-major? */
1502   if (dy > dx) {
1503 
1504     /* y-major.  Calculate 16-bit fixed point fractional part of a pixel that
1505        X advances every time Y advances 1 pixel, truncating the result so that
1506        we won't overrun the endpoint along the X axis */
1507     /* Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; */
1508     erradj = ((dx << 16) / dy)<<16;
1509 
1510     /* draw all pixels other than the first and last */
1511     x0pxdir=xx0+xdir;
1512     while (--dy) {
1513       erracctmp = erracc;
1514       erracc += erradj;
1515       if (erracc <= erracctmp) {
1516 	/* rollover in error accumulator, x coord advances */
1517 	xx0=x0pxdir;
1518 	x0pxdir += xdir;
1519       }
1520       yy0++;			/* y-major so always advance Y */
1521 
1522       /* the AAbits most significant bits of erracc give us the intensity
1523 	 weighting for this pixel, and the complement of the weighting for
1524 	 the paired pixel. */
1525       wgt = (erracc >> intshift) & 255;
1526       result |= pixelColorWeight (dst, xx0, yy0, color, 255-wgt);
1527       result |= pixelColorWeight (dst, x0pxdir, yy0, color, wgt);
1528     }
1529 
1530   } else {
1531 
1532    /* x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
1533       that Y advances each time X advances 1 pixel, truncating the result so
1534       that we won't overrun the endpoint along the X axis. */
1535    /* Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; */
1536    erradj = ((dy << 16) / dx)<<16;
1537 
1538    /* draw all pixels other than the first and last */
1539    y0p1=yy0+1;
1540    while (--dx) {
1541 
1542     erracctmp = erracc;
1543     erracc += erradj;
1544     if (erracc <= erracctmp) {
1545       /* Accumulator turned over, advance y */
1546       yy0=y0p1;
1547       y0p1++;
1548     }
1549     xx0 += xdir;			/* x-major so always advance X */
1550     /* the AAbits most significant bits of erracc give us the intensity
1551        weighting for this pixel, and the complement of the weighting for
1552        the paired pixel. */
1553     wgt = (erracc >> intshift) & 255;
1554     result |= pixelColorWeight (dst, xx0, yy0, color, 255-wgt);
1555     result |= pixelColorWeight (dst, xx0, y0p1, color, wgt);
1556   }
1557  }
1558 
1559  /* Do we have to draw the endpoint */
1560  if (draw_endpoint) {
1561   /* Draw final pixel, always exactly intersected by the line and doesn't
1562      need to be weighted. */
1563   result |= pixelColor (dst, x2, y2, color);
1564  }
1565 
1566  return(result);
1567 }
1568 
aalineColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1569 int aalineColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1570 {
1571  return(aalineColorInt(dst,x1,y1,x2,y1,color,1));
1572 }
1573 
aalineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1574 int aalineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1575 {
1576  return(aalineColorInt(dst, x1, y1, x2, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a, 1));
1577 }
1578 
1579 
1580 /* ----- Circle */
1581 
1582 /* Note: Based on algorithm from sge library, modified by A. Schiffler */
1583 /* with multiple pixel-draw removal and other minor speedup changes.   */
1584 
circleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)1585 int circleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
1586 {
1587  int result;
1588  Sint16 x1,y1,x2,y2;
1589  Sint16 cx = 0;
1590  Sint16 cy = r;
1591  Sint16 ocx = (Sint16)0xffff;
1592  Sint16 ocy = (Sint16)0xffff;
1593  Sint16 df = 1 - r;
1594  Sint16 d_e = 3;
1595  Sint16 d_se = -2 * r + 5;
1596  Sint16 xpcx, xmcx, xpcy, xmcy;
1597  Sint16 ypcy, ymcy, ypcx, ymcx;
1598  Uint8 *colorptr;
1599 
1600  /* Sanity check radius */
1601  if (r<0) {
1602   return(-1);
1603  }
1604 
1605  /* Special case for r=0 - draw a point */
1606  if (r==0) {
1607   return(pixelColor (dst, x, y, color));
1608  }
1609 
1610  /* Test if bounding box of circle is visible */
1611  x1=x-r;
1612  y1=y-r;
1613  x2=x+r;
1614  y2=y+r;
1615  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
1616   return(0);
1617  }
1618 
1619  /* Draw circle */
1620  result=0;
1621  /* Alpha Check */
1622  if ((color & 255) ==255) {
1623 
1624   /* No Alpha - direct memory writes */
1625 
1626   /* Setup color */
1627   colorptr=(Uint8 *)&color;
1628   if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1629    color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1630   } else {
1631    color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1632   }
1633 
1634   /* Lock surface */
1635   SDL_LockSurface(dst);
1636 
1637   /* Draw */
1638   do {
1639    if ((ocy!=cy) || (ocx!=cx)) {
1640     xpcx=x+cx;
1641     xmcx=x-cx;
1642     if (cy>0) {
1643      ypcy=y+cy;
1644      ymcy=y-cy;
1645      result |= fastPixelColorNolock(dst,xmcx,ypcy,color);
1646      result |= fastPixelColorNolock(dst,xpcx,ypcy,color);
1647      result |= fastPixelColorNolock(dst,xmcx,ymcy,color);
1648      result |= fastPixelColorNolock(dst,xpcx,ymcy,color);
1649     } else {
1650      result |= fastPixelColorNolock(dst,xmcx,y,color);
1651      result |= fastPixelColorNolock(dst,xpcx,y,color);
1652     }
1653     ocy=cy;
1654     xpcy=x+cy;
1655     xmcy=x-cy;
1656     if (cx>0) {
1657      ypcx=y+cx;
1658      ymcx=y-cx;
1659      result |= fastPixelColorNolock(dst,xmcy,ypcx,color);
1660      result |= fastPixelColorNolock(dst,xpcy,ypcx,color);
1661      result |= fastPixelColorNolock(dst,xmcy,ymcx,color);
1662      result |= fastPixelColorNolock(dst,xpcy,ymcx,color);
1663     } else {
1664      result |= fastPixelColorNolock(dst,xmcy,y,color);
1665      result |= fastPixelColorNolock(dst,xpcy,y,color);
1666     }
1667     ocx=cx;
1668    }
1669    /* Update */
1670    if (df < 0)  {
1671     df += d_e;
1672     d_e += 2;
1673     d_se += 2;
1674    } else {
1675     df += d_se;
1676     d_e += 2;
1677     d_se += 4;
1678     cy--;
1679    }
1680    cx++;
1681   } while(cx <= cy);
1682 
1683   /* Unlock surface */
1684   SDL_UnlockSurface(dst);
1685 
1686  } else {
1687 
1688   /* Using Alpha - blended pixel blits */
1689 
1690   do {
1691    /* Draw */
1692    if ((ocy!=cy) || (ocx!=cx)) {
1693     xpcx=x+cx;
1694     xmcx=x-cx;
1695     if (cy>0) {
1696      ypcy=y+cy;
1697      ymcy=y-cy;
1698      result |= pixelColor(dst,xmcx,ypcy,color);
1699      result |= pixelColor(dst,xpcx,ypcy,color);
1700      result |= pixelColor(dst,xmcx,ymcy,color);
1701      result |= pixelColor(dst,xpcx,ymcy,color);
1702     } else {
1703      result |= pixelColor(dst,xmcx,y,color);
1704      result |= pixelColor(dst,xpcx,y,color);
1705     }
1706     ocy=cy;
1707     xpcy=x+cy;
1708     xmcy=x-cy;
1709     if (cx>0) {
1710      ypcx=y+cx;
1711      ymcx=y-cx;
1712      result |= pixelColor(dst,xmcy,ypcx,color);
1713      result |= pixelColor(dst,xpcy,ypcx,color);
1714      result |= pixelColor(dst,xmcy,ymcx,color);
1715      result |= pixelColor(dst,xpcy,ymcx,color);
1716     } else {
1717      result |= pixelColor(dst,xmcy,y,color);
1718      result |= pixelColor(dst,xpcy,y,color);
1719     }
1720     ocx=cx;
1721    }
1722    /* Update */
1723    if (df < 0)  {
1724     df += d_e;
1725     d_e += 2;
1726     d_se += 2;
1727    } else {
1728     df += d_se;
1729     d_e += 2;
1730     d_se += 4;
1731     cy--;
1732    }
1733    cx++;
1734   } while(cx <= cy);
1735 
1736  } /* Alpha check */
1737 
1738  return(result);
1739 }
1740 
circleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1741 int circleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1742 {
1743  /* Draw */
1744  return(circleColor(dst, x, y, rad, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
1745 }
1746 
1747 /* ----- AA Circle */
1748 
1749 /* Low-speed antialiased circle implementation by drawing aalines. */
1750 /* Works best for larger radii. */
1751 
aacircleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)1752 int aacircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
1753 {
1754  return (aaellipseColor(dst, x, y, r, r, color));
1755 }
1756 
aacircleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1757 int aacircleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1758 {
1759  /* Draw */
1760  return(aaellipseColor(dst, x, y, rad, rad, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
1761 }
1762 
1763 /* ----- Filled Circle */
1764 
1765 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
1766 /* and other speedup changes. */
1767 
filledCircleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)1768 int filledCircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
1769 {
1770  int result;
1771  Sint16 x1,y1,x2,y2;
1772  Sint16 cx = 0;
1773  Sint16 cy = r;
1774  Sint16 ocx = (Sint16)0xffff;
1775  Sint16 ocy = (Sint16)0xffff;
1776  Sint16 df = 1 - r;
1777  Sint16 d_e = 3;
1778  Sint16 d_se = -2 * r + 5;
1779  Sint16 xpcx, xmcx, xpcy, xmcy;
1780  Sint16 ypcy, ymcy, ypcx, ymcx;
1781 
1782  /* Sanity check radius */
1783  if (r<0) {
1784   return(-1);
1785  }
1786 
1787  /* Special case for r=0 - draw a point */
1788  if (r==0) {
1789   return(pixelColor (dst, x, y, color));
1790  }
1791 
1792  /* Test bounding box */
1793  x1=x-r;
1794  y1=y-r;
1795  x2=x+r;
1796  y2=y+r;
1797  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
1798   return(0);
1799  }
1800 
1801  /* Draw */
1802  result=0;
1803  do {
1804    xpcx=x+cx;
1805    xmcx=x-cx;
1806    xpcy=x+cy;
1807    xmcy=x-cy;
1808    if (ocy!=cy) {
1809     if (cy>0) {
1810      ypcy=y+cy;
1811      ymcy=y-cy;
1812      result |= hlineColor(dst,xmcx,xpcx,ypcy,color);
1813      result |= hlineColor(dst,xmcx,xpcx,ymcy,color);
1814     } else {
1815      result |= hlineColor(dst,xmcx,xpcx,y,color);
1816     }
1817     ocy=cy;
1818    }
1819    if (ocx!=cx) {
1820     if (cx!=cy) {
1821      if (cx>0) {
1822       ypcx=y+cx;
1823       ymcx=y-cx;
1824       result |= hlineColor(dst,xmcy,xpcy,ymcx,color);
1825       result |= hlineColor(dst,xmcy,xpcy,ypcx,color);
1826      } else {
1827       result |= hlineColor(dst,xmcy,xpcy,y,color);
1828      }
1829     }
1830     ocx=cx;
1831    }
1832    /* Update */
1833    if (df < 0)  {
1834     df += d_e;
1835     d_e += 2;
1836     d_se += 2;
1837    } else {
1838     df += d_se;
1839     d_e += 2;
1840     d_se += 4;
1841     cy--;
1842    }
1843    cx++;
1844  } while(cx <= cy);
1845 
1846  return(result);
1847 }
1848 
filledCircleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1849 int filledCircleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1850 {
1851  /* Draw */
1852  return(filledCircleColor(dst, x, y, rad, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
1853 }
1854 
1855 
1856 /* ----- Ellipse */
1857 
1858 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
1859 /* and other speedup changes. */
1860 
ellipseColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)1861 int ellipseColor (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1862 {
1863  int result;
1864  Sint16 x1, y1, x2, y2;
1865  int ix, iy;
1866  int h, i, j, k;
1867  int oh, oi, oj, ok;
1868  int xmh, xph, ypk, ymk;
1869  int xmi, xpi, ymj, ypj;
1870  int xmj, xpj, ymi, ypi;
1871  int xmk, xpk, ymh, yph;
1872  Uint8 *colorptr;
1873 
1874  /* Sanity check radii */
1875  if ((rx<0) || (ry<0)) {
1876   return(-1);
1877  }
1878 
1879  /* Special case for rx=0 - draw a vline */
1880  if (rx==0) {
1881   return(vlineColor (dst, x, y-ry, y+ry, color));
1882  }
1883  /* Special case for ry=0 - draw a hline */
1884  if (ry==0) {
1885   return(hlineColor (dst, x-rx, x+rx, y, color));
1886  }
1887 
1888  /* Test bounding box */
1889  x1=x-rx;
1890  y1=y-ry;
1891  x2=x+rx;
1892  y2=y+ry;
1893  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
1894   return(0);
1895  }
1896 
1897  /* Init vars */
1898  oh = oi = oj = ok = 0xFFFF;
1899 
1900  /* Draw */
1901  result=0;
1902  /* Check alpha */
1903  if ((color & 255)==255) {
1904 
1905   /* No Alpha - direct memory writes */
1906 
1907   /* Setup color */
1908   colorptr=(Uint8 *)&color;
1909   if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1910    color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1911   } else {
1912    color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1913   }
1914 
1915   /* Lock surface */
1916   SDL_LockSurface(dst);
1917 
1918   if (rx > ry) {
1919   	ix = 0;
1920    	iy = rx * 64;
1921 
1922  		do {
1923 	 		h = (ix + 32) >> 6;
1924 	 		i = (iy + 32) >> 6;
1925 	 		j = (h * ry) / rx;
1926 	 		k = (i * ry) / rx;
1927 
1928 			if (((ok!=k) && (oj!=k)) || ((oj!=j) && (ok!=j)) || (k!=j)) {
1929 			 xph=x+h;
1930 			 xmh=x-h;
1931  			 if (k>0) {
1932  			  ypk=y+k;
1933  			  ymk=y-k;
1934  			  result |= fastPixelColorNolock (dst,xmh,ypk, color);
1935  			  result |= fastPixelColorNolock (dst,xph,ypk, color);
1936  			  result |= fastPixelColorNolock (dst,xmh,ymk, color);
1937  			  result |= fastPixelColorNolock (dst,xph,ymk, color);
1938 			 } else {
1939  			  result |= fastPixelColorNolock (dst,xmh,y, color);
1940  			  result |= fastPixelColorNolock (dst,xph,y, color);
1941 			 }
1942  			 ok=k;
1943 			 xpi=x+i;
1944 			 xmi=x-i;
1945 			 if (j>0) {
1946 			  ypj=y+j;
1947 			  ymj=y-j;
1948  			  result |= fastPixelColorNolock (dst,xmi,ypj, color);
1949  			  result |= fastPixelColorNolock (dst,xpi,ypj, color);
1950  			  result |= fastPixelColorNolock (dst,xmi,ymj, color);
1951  			  result |= fastPixelColorNolock (dst,xpi,ymj, color);
1952 			 } else {
1953  			  result |= fastPixelColorNolock (dst,xmi,y, color);
1954  			  result |= fastPixelColorNolock (dst,xpi,y, color);
1955 			 }
1956 			 oj=j;
1957 			}
1958 
1959 			ix = ix + iy / rx;
1960 	 		iy = iy - ix / rx;
1961 
1962 		} while (i > h);
1963   } else {
1964   	ix = 0;
1965    	iy = ry * 64;
1966 
1967   	do {
1968 	 		h = (ix + 32) >> 6;
1969 	 		i = (iy + 32) >> 6;
1970 	 		j = (h * rx) / ry;
1971 	 		k = (i * rx) / ry;
1972 
1973 			if (((oi!=i) && (oh!=i)) || ((oh!=h) && (oi!=h) && (i!=h))) {
1974 			 xmj=x-j;
1975 			 xpj=x+j;
1976  			 if (i>0) {
1977  			  ypi=y+i;
1978  			  ymi=y-i;
1979 	 		  result |= fastPixelColorNolock (dst,xmj,ypi,color);
1980 	 		  result |= fastPixelColorNolock (dst,xpj,ypi,color);
1981 	 		  result |= fastPixelColorNolock (dst,xmj,ymi,color);
1982 	 		  result |= fastPixelColorNolock (dst,xpj,ymi,color);
1983 		  	 } else {
1984 	 		  result |= fastPixelColorNolock (dst,xmj,y,color);
1985 	 		  result |= fastPixelColorNolock (dst,xpj,y,color);
1986 			 }
1987 			 oi=i;
1988 			 xmk=x-k;
1989 			 xpk=x+k;
1990 			 if (h>0) {
1991 			  yph=y+h;
1992 			  ymh=y-h;
1993  	 		  result |= fastPixelColorNolock (dst,xmk,yph,color);
1994  	 		  result |= fastPixelColorNolock (dst,xpk,yph,color);
1995  	 		  result |= fastPixelColorNolock (dst,xmk,ymh,color);
1996  	 		  result |= fastPixelColorNolock (dst,xpk,ymh,color);
1997 			 } else {
1998  	 		  result |= fastPixelColorNolock (dst,xmk,y,color);
1999  	 		  result |= fastPixelColorNolock (dst,xpk,y,color);
2000 			 }
2001 			 oh=h;
2002 			}
2003 
2004 	 		ix = ix + iy / ry;
2005 	 		iy = iy - ix / ry;
2006 
2007   	} while(i > h);
2008   }
2009 
2010   /* Unlock surface */
2011   SDL_UnlockSurface(dst);
2012 
2013  } else {
2014 
2015  if (rx > ry) {
2016   	ix = 0;
2017    	iy = rx * 64;
2018 
2019  		do {
2020 	 		h = (ix + 32) >> 6;
2021 	 		i = (iy + 32) >> 6;
2022 	 		j = (h * ry) / rx;
2023 	 		k = (i * ry) / rx;
2024 
2025 			if (((ok!=k) && (oj!=k)) || ((oj!=j) && (ok!=j)) || (k!=j)) {
2026 			 xph=x+h;
2027 			 xmh=x-h;
2028  			 if (k>0) {
2029  			  ypk=y+k;
2030  			  ymk=y-k;
2031  			  result |= pixelColor (dst,xmh,ypk, color);
2032  			  result |= pixelColor (dst,xph,ypk, color);
2033  			  result |= pixelColor (dst,xmh,ymk, color);
2034  			  result |= pixelColor (dst,xph,ymk, color);
2035 			 } else {
2036  			  result |= pixelColor (dst,xmh,y, color);
2037  			  result |= pixelColor (dst,xph,y, color);
2038 			 }
2039  			 ok=k;
2040 			 xpi=x+i;
2041 			 xmi=x-i;
2042 			 if (j>0) {
2043 			  ypj=y+j;
2044 			  ymj=y-j;
2045  			  result |= pixelColor (dst,xmi,ypj, color);
2046  			  result |= pixelColor (dst,xpi,ypj, color);
2047  			  result |= pixelColor (dst,xmi,ymj, color);
2048  			  result |= pixelColor (dst,xpi,ymj, color);
2049 			 } else {
2050  			  result |= pixelColor (dst,xmi,y, color);
2051  			  result |= pixelColor (dst,xpi,y, color);
2052 			 }
2053 			 oj=j;
2054 			}
2055 
2056 			ix = ix + iy / rx;
2057 	 		iy = iy - ix / rx;
2058 
2059 		} while (i > h);
2060   } else {
2061   	ix = 0;
2062    	iy = ry * 64;
2063 
2064   	do {
2065 	 		h = (ix + 32) >> 6;
2066 	 		i = (iy + 32) >> 6;
2067 	 		j = (h * rx) / ry;
2068 	 		k = (i * rx) / ry;
2069 
2070 			if (((oi!=i) && (oh!=i)) || ((oh!=h) && (oi!=h) && (i!=h))) {
2071 			 xmj=x-j;
2072 			 xpj=x+j;
2073  			 if (i>0) {
2074  			  ypi=y+i;
2075  			  ymi=y-i;
2076 	 		  result |= pixelColor (dst,xmj,ypi,color);
2077 	 		  result |= pixelColor (dst,xpj,ypi,color);
2078 	 		  result |= pixelColor (dst,xmj,ymi,color);
2079 	 		  result |= pixelColor (dst,xpj,ymi,color);
2080 		  	 } else {
2081 	 		  result |= pixelColor (dst,xmj,y,color);
2082 	 		  result |= pixelColor (dst,xpj,y,color);
2083 			 }
2084 			 oi=i;
2085 			 xmk=x-k;
2086 			 xpk=x+k;
2087 			 if (h>0) {
2088 			  yph=y+h;
2089 			  ymh=y-h;
2090  	 		  result |= pixelColor (dst,xmk,yph,color);
2091  	 		  result |= pixelColor (dst,xpk,yph,color);
2092  	 		  result |= pixelColor (dst,xmk,ymh,color);
2093  	 		  result |= pixelColor (dst,xpk,ymh,color);
2094 			 } else {
2095  	 		  result |= pixelColor (dst,xmk,y,color);
2096  	 		  result |= pixelColor (dst,xpk,y,color);
2097 			 }
2098 			 oh=h;
2099 			}
2100 
2101 	 		ix = ix + iy / ry;
2102 	 		iy = iy - ix / ry;
2103 
2104   	} while(i > h);
2105  }
2106 
2107  } /* Alpha check */
2108 
2109  return(result);
2110 }
2111 
ellipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2112 int ellipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2113 {
2114  /* Draw */
2115  return(ellipseColor(dst, x, y, rx, ry, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
2116 }
2117 
2118 /* ----- AA Ellipse */
2119 
2120 /* Low-speed antialiased ellipse implementation by drawing aalines. */
2121 /* Works best for larger radii. */
2122 
aaellipseColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)2123 int aaellipseColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2124 {
2125  int result;
2126  Sint16 x1, y1, x2, y2;
2127  double angle;
2128  double deltaAngle;
2129  double drx, dry, dr;
2130  int posX, posY, oldPosX, oldPosY;
2131  int i, r;
2132 
2133  /* Sanity check radii */
2134  if ((rx<0) || (ry<0)) {
2135   return(-1);
2136  }
2137 
2138  /* Special case for rx=0 - draw a vline */
2139  if (rx==0) {
2140   return(vlineColor (dst, x, y-ry, y+ry, color));
2141  }
2142  /* Special case for ry=0 - draw a hline */
2143  if (ry==0) {
2144   return(hlineColor (dst, x-rx, x+rx, y, color));
2145  }
2146 
2147  /* Test bounding box */
2148  x1=x-rx;
2149  y1=y-ry;
2150  x2=x+rx;
2151  y2=y+ry;
2152  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
2153   return(0);
2154  }
2155 
2156  /* Draw */
2157  r=(rx+ry)>>1;
2158  dr=(double)r;
2159  drx=(double)rx;
2160  dry=(double)ry;
2161  deltaAngle=(2*M_PI)/dr;
2162  angle=deltaAngle;
2163  oldPosX=x+rx;
2164  oldPosY=y;
2165 
2166  result=0;
2167  for(i=0; i<r; i++) {
2168   posX=x+(int)(drx*cos(angle));
2169   posY=y+(int)(dry*sin(angle));
2170   result |= aalineColorInt (dst, oldPosX, oldPosY, posX, posY, color, 1);
2171   oldPosX=posX;
2172   oldPosY=posY;
2173   angle += deltaAngle;
2174  }
2175 
2176  return (result);
2177 }
2178 
aaellipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2179 int aaellipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2180 {
2181  /* Draw */
2182  return(aaellipseColor(dst, x, y, rx, ry, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
2183 }
2184 
2185 /* ---- Filled Ellipse */
2186 
2187 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
2188 /* and other speedup changes. */
2189 
filledEllipseColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)2190 int filledEllipseColor (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2191 {
2192  int result;
2193  Sint16 x1,y1,x2,y2;
2194  int ix, iy;
2195  int h, i, j, k;
2196  int oh, oi, oj, ok;
2197  int xmh, xph;
2198  int xmi, xpi;
2199  int xmj, xpj;
2200  int xmk, xpk;
2201 
2202  /* Sanity check radii */
2203  if ((rx<0) || (ry<0)) {
2204   return(-1);
2205  }
2206 
2207  /* Special case for rx=0 - draw a vline */
2208  if (rx==0) {
2209   return(vlineColor (dst, x, y-ry, y+ry, color));
2210  }
2211  /* Special case for ry=0 - draw a hline */
2212  if (ry==0) {
2213   return(hlineColor (dst, x-rx, x+rx, y, color));
2214  }
2215 
2216  /* Test bounding box */
2217  x1=x-rx;
2218  y1=y-ry;
2219  x2=x+rx;
2220  y2=y+ry;
2221  if (!(clipLine(dst,&x1,&y1,&x2,&y2))) {
2222   return(0);
2223  }
2224 
2225  /* Init vars */
2226  oh = oi = oj = ok = 0xFFFF;
2227 
2228  /* Draw */
2229  result=0;
2230  if (rx > ry) {
2231   	ix = 0;
2232    	iy = rx * 64;
2233 
2234  		do {
2235 	 		h = (ix + 32) >> 6;
2236 	 		i = (iy + 32) >> 6;
2237 	 		j = (h * ry) / rx;
2238 	 		k = (i * ry) / rx;
2239 
2240 			if ((ok!=k) && (oj!=k)) {
2241 			 xph=x+h;
2242 			 xmh=x-h;
2243  			 if (k>0) {
2244 	 		  result |= hlineColor (dst,xmh,xph,y+k,color);
2245 	   		  result |= hlineColor (dst,xmh,xph,y-k,color);
2246 			 } else {
2247 	   		  result |= hlineColor (dst,xmh,xph,y,color);
2248 			 }
2249  			 ok=k;
2250 			}
2251 			if ((oj!=j) && (ok!=j) && (k!=j))  {
2252 			 xmi=x-i;
2253 			 xpi=x+i;
2254 			 if (j>0) {
2255  	 		  result |= hlineColor (dst,xmi,xpi,y+j,color);
2256 	  		  result |= hlineColor (dst,xmi,xpi,y-j,color);
2257 			 } else {
2258 	  		  result |= hlineColor (dst,xmi,xpi,y  ,color);
2259 			 }
2260 			 oj=j;
2261 			}
2262 
2263 			ix = ix + iy / rx;
2264 	 		iy = iy - ix / rx;
2265 
2266 		} while (i > h);
2267   } else {
2268   	ix = 0;
2269    	iy = ry * 64;
2270 
2271   	do {
2272 	 		h = (ix + 32) >> 6;
2273 	 		i = (iy + 32) >> 6;
2274 	 		j = (h * rx) / ry;
2275 	 		k = (i * rx) / ry;
2276 
2277 			if ((oi!=i) && (oh!=i)) {
2278 			 xmj=x-j;
2279 			 xpj=x+j;
2280  			 if (i>0) {
2281 	 		  result |= hlineColor (dst,xmj,xpj,y+i,color);
2282 	   		  result |= hlineColor (dst,xmj,xpj,y-i,color);
2283 		  	 } else {
2284 	   		  result |= hlineColor (dst,xmj,xpj,y,color);
2285 			 }
2286 			 oi=i;
2287 			}
2288 			if ((oh!=h) && (oi!=h) && (i!=h)) {
2289 			 xmk=x-k;
2290 			 xpk=x+k;
2291 			 if (h>0) {
2292  	 		  result |= hlineColor (dst,xmk,xpk,y+h,color);
2293 	  		  result |= hlineColor (dst,xmk,xpk,y-h,color);
2294 			 } else {
2295 	  		  result |= hlineColor (dst,xmk,xpk,y  ,color);
2296 			 }
2297 			 oh=h;
2298 			}
2299 
2300 	 		ix = ix + iy / ry;
2301 	 		iy = iy - ix / ry;
2302 
2303   	} while(i > h);
2304  }
2305 
2306  return(result);
2307 }
2308 
2309 
filledEllipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2310 int filledEllipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2311 {
2312  /* Draw */
2313  return(filledEllipseColor(dst, x, y, rx, ry, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
2314 }
2315 
2316 /* ---- Polygon */
2317 
polygonColor(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint32 color)2318 int polygonColor (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, Uint32 color)
2319 {
2320  int result;
2321  int i;
2322  Sint16 *x1, *y1, *x2, *y2;
2323 
2324  /* Sanity check */
2325  if (n<3) {
2326   return(-1);
2327  }
2328 
2329  /* Pointer setup */
2330  x1=x2=vx;
2331  y1=y2=vy;
2332  x2++;
2333  y2++;
2334 
2335  /* Draw */
2336  result=0;
2337  for (i=1; i<n; i++) {
2338   result |= lineColor (dst, *x1, *y1, *x2, *y2, color);
2339   x1=x2;
2340   y1=y2;
2341   x2++;
2342   y2++;
2343  }
2344  result |= lineColor (dst, *x1, *y1, *vx, *vy, color);
2345 
2346  return(result);
2347 }
2348 
polygonRGBA(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2349 int polygonRGBA (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2350 {
2351  /* Draw */
2352  return(polygonColor(dst, vx, vy, n, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
2353 }
2354 
2355 /* ---- Filled Polygon */
2356 
2357 int gfxPrimitivesCompareInt(const void *a, const void *b);
2358 
2359 static int *gfxPrimitivesPolyInts=NULL;
2360 static int gfxPrimitivesPolyAllocated=0;
2361 
filledPolygonColor(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,int color)2362 int filledPolygonColor (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, int color)
2363 {
2364 	int result;
2365 	int i;
2366 	int y;
2367 	int miny, maxy;
2368 	int x1, y1;
2369 	int x2, y2;
2370 	int ind1, ind2;
2371 	int ints;
2372 
2373 	/* Sanity check */
2374 	if (n<3) {
2375 	 return -1;
2376 	}
2377 
2378 	/* Allocate temp array, only grow array */
2379 	if (!gfxPrimitivesPolyAllocated) {
2380 	 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
2381 	 gfxPrimitivesPolyAllocated = n;
2382 	} else {
2383 	 if (gfxPrimitivesPolyAllocated<n) {
2384  	  gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
2385 	  gfxPrimitivesPolyAllocated = n;
2386 	 }
2387 	}
2388 
2389 	/* Determine Y maxima */
2390 	miny = vy[0];
2391 	maxy = vy[0];
2392 	for (i=1; (i < n); i++) {
2393 		if (vy[i] < miny) {
2394 		 miny = vy[i];
2395 		} else if (vy[i] > maxy) {
2396 		 maxy = vy[i];
2397 		}
2398 	}
2399 
2400 	/* Draw, scanning y */
2401 	result=0;
2402 	for (y=miny; (y <= maxy); y++) {
2403 		ints = 0;
2404 		for (i=0; (i < n); i++) {
2405 			if (!i) {
2406 				ind1 = n-1;
2407 				ind2 = 0;
2408 			} else {
2409 				ind1 = i-1;
2410 				ind2 = i;
2411 			}
2412 			y1 = vy[ind1];
2413 			y2 = vy[ind2];
2414 			if (y1 < y2) {
2415 				x1 = vx[ind1];
2416 				x2 = vx[ind2];
2417 			} else if (y1 > y2) {
2418 				y2 = vy[ind1];
2419 				y1 = vy[ind2];
2420 				x2 = vx[ind1];
2421 				x1 = vx[ind2];
2422 			} else {
2423 				continue;
2424 			}
2425 			if ((y >= y1) && (y < y2)) {
2426 				gfxPrimitivesPolyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
2427 			} else if ((y == maxy) && (y > y1) && (y <= y2)) {
2428 				gfxPrimitivesPolyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
2429 			}
2430 		}
2431 		qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
2432 
2433 		for (i=0; (i<ints); i+=2) {
2434 			result |= hlineColor(dst, gfxPrimitivesPolyInts[i], gfxPrimitivesPolyInts[i+1], y, color);
2435 		}
2436 	}
2437 
2438  return (result);
2439 }
2440 
filledPolygonRGBA(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2441 int filledPolygonRGBA (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2442 {
2443  /* Draw */
2444  return(filledPolygonColor(dst, vx, vy, n, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
2445 }
2446 
gfxPrimitivesCompareInt(const void * a,const void * b)2447 int gfxPrimitivesCompareInt(const void *a, const void *b)
2448 {
2449  return (*(const int *)a) - (*(const int *)b);
2450 }
2451 
2452 /* ---- Character (8x8 internal font) */
2453 
2454 static SDL_Surface *gfxPrimitivesFont[256];
2455 static Uint32 gfxPrimitivesFontColor[256];
2456 
characterColor(SDL_Surface * dst,Sint16 x,Sint16 y,char c,Uint32 color)2457 int characterColor (SDL_Surface *dst, Sint16 x, Sint16 y, char c, Uint32 color)
2458 {
2459  SDL_Rect srect;
2460  SDL_Rect drect;
2461  int result;
2462  int ix, iy, k;
2463  unsigned char *charpos;
2464  unsigned char bits[8]={128,64,32,16,8,4,2,1};
2465  unsigned char *bitpos;
2466  Uint8 *curpos;
2467  int forced_redraw;
2468 
2469  /* Setup source rectangle for 8x8 bitmap */
2470  srect.x=0;
2471  srect.y=0;
2472  srect.w=8;
2473  srect.h=8;
2474 
2475  /* Setup destination rectangle for 8x8 bitmap */
2476  drect.x=x;
2477  drect.y=y;
2478  drect.w=8;
2479  drect.h=8;
2480 
2481  /* Create new 8x8 bitmap surface if not already present */
2482  if (gfxPrimitivesFont[(unsigned char)c]==NULL) {
2483   gfxPrimitivesFont[(unsigned char)c]=SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, 8, 8, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
2484   /* Check pointer */
2485   if (gfxPrimitivesFont[(unsigned char)c]==NULL) {
2486    return (-1);
2487   }
2488   /* Definitely redraw */
2489   forced_redraw=1;
2490  } else {
2491   forced_redraw=0;
2492  }
2493 
2494  /* Check if color has changed */
2495  if ((gfxPrimitivesFontColor[(unsigned char)c]!=color) || (forced_redraw)) {
2496    /* Redraw character */
2497    SDL_SetAlpha (gfxPrimitivesFont[(unsigned char)c], SDL_SRCALPHA, 255);
2498    gfxPrimitivesFontColor[(unsigned char)c]=color;
2499 
2500    /* Variable setup */
2501    k = (unsigned char)c;
2502    k *= 8;
2503    charpos=gfxPrimitivesFontdata;
2504    charpos += k;
2505 
2506    /* Clear bitmap */
2507    curpos=(Uint8 *)gfxPrimitivesFont[(unsigned char)c]->pixels;
2508    memset (curpos, 0, 8*8*4);
2509 
2510    /* Drawing loop */
2511    for (iy=0; iy<8; iy++) {
2512     bitpos=bits;
2513     for (ix=0; ix<8; ix++) {
2514      if ((*charpos & *bitpos)==*bitpos) {
2515       memcpy(curpos,&color,4);
2516      }
2517      bitpos++;
2518      curpos += 4;;
2519     }
2520     charpos++;
2521    }
2522  }
2523 
2524  /* Draw bitmap onto destination surface */
2525  result=SDL_BlitSurface (gfxPrimitivesFont[(unsigned char)c], &srect, dst, &drect);
2526 
2527  return(result);
2528 }
2529 
characterRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,char c,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2530 int characterRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2531 {
2532  /* Draw */
2533  return(characterColor(dst, x, y, c, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
2534 }
2535 
stringColor(SDL_Surface * dst,Sint16 x,Sint16 y,char * c,Uint32 color)2536 int stringColor (SDL_Surface *dst, Sint16 x, Sint16 y, char *c, Uint32 color)
2537 {
2538  int result;
2539  int i,length;
2540  char *curchar;
2541  int curx;
2542 
2543  length=strlen(c);
2544  curchar=c;
2545  curx=x;
2546  result=0;
2547  for (i=0; i<length; i++) {
2548   result |= characterColor(dst,curx,y,*curchar,color);
2549   curchar++;
2550   curx += 8;
2551  }
2552 
2553  return(result);
2554 }
2555 
stringRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,char * c,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2556 int stringRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, char *c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2557 {
2558  /* Draw */
2559  return(stringColor(dst, x, y, c, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a));
2560 }
2561 
2562