1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://www.wtfpl.net/txt/copying/ for more details.
13 ////////////////////////////////////////////////////////////////////////////////
20 int sdl_scanlines
= 1;
21 sdl_filter_t sdl_filter
= SDL_FILTER_NONE
;
23 static int sdlc_mag2x
; /* effective sdl_mag2x */
24 static int sdl_inited
= 0;
27 ////////////////////////////////////////////////////////////////////////////////
28 SDL_Window
*sdl_win
= NULL
;
29 SDL_Renderer
*sdl_rend
= NULL
;
30 SDL_Texture
*sdl_scr
= NULL
;
31 Uint32
*sdl_vscr
= NULL
;
32 static SDL_Texture
*sdl_scr2x
= NULL
;
33 static Uint32
*sdl_vscr2x
= NULL
;
34 static int sdl_prev_log_size_1x
= 0;
37 ////////////////////////////////////////////////////////////////////////////////
38 void videolib_args (int *argc
, char *argv
[]) {
42 if (strcmp(argv
[f
], "--") == 0) break;
43 else if (strcmp(argv
[f
], "--fs") == 0) sdl_fs
= 1;
44 else if (strcmp(argv
[f
], "--realfs") == 0) sdl_real_fs
= 1;
45 else if (strcmp(argv
[f
], "--winfs") == 0) sdl_real_fs
= 0;
46 else if (strcmp(argv
[f
], "--win") == 0) sdl_fs
= 0;
47 else if (strcmp(argv
[f
], "--tv") == 0) sdl_scanlines
= 1;
48 else if (strcmp(argv
[f
], "--notv") == 0) sdl_scanlines
= 0;
49 else if (strcmp(argv
[f
], "--bw") == 0) sdl_filter
= SDL_FILTER_BLACKNWHITE
;
50 else if (strcmp(argv
[f
], "--green") == 0) sdl_filter
= SDL_FILTER_GREEN
;
51 else if (strcmp(argv
[f
], "--1x") == 0) sdl_mag2x
= 0;
52 else if (strcmp(argv
[f
], "--2x") == 0) sdl_mag2x
= 1;
53 else if (strcmp(argv
[f
], "--vbl") == 0) sdl_vsync
= 1;
54 else if (strcmp(argv
[f
], "--novbl") == 0) sdl_vsync
= 0;
57 for (int c
= f
+1; c
< *argc
; ++c
) argv
[c
-1] = argv
[c
];
66 ////////////////////////////////////////////////////////////////////////////////
67 static void cleanup (void) {
68 if (sdl_win
&& sdl_fs
&& sdl_real_fs
) SDL_SetWindowFullscreen(sdl_win
, 0);
69 if (sdl_scr
) SDL_DestroyTexture(sdl_scr
);
70 if (sdl_scr2x
) SDL_DestroyTexture(sdl_scr2x
);
71 if (sdl_rend
) SDL_DestroyRenderer(sdl_rend
);
72 if (sdl_win
) SDL_DestroyWindow(sdl_win
);
73 if (sdl_vscr
) free(sdl_vscr
);
74 if (sdl_vscr2x
) free(sdl_vscr2x
);
84 static void quit_cleanup (void) {
86 if (sdl_inited
) { SDL_Quit(); sdl_inited
= 0; }
90 int videolib_deinit (void) {
96 int videolib_init (const char *window_name
) {
97 if (sdl_win
== NULL
) {
98 SDL_Init(SDL_INIT_VIDEO
|SDL_INIT_EVENTS
|SDL_INIT_TIMER
);
100 atexit(quit_cleanup
);
101 sdlc_mag2x
= (!!sdl_mag2x
)+1;
102 sdl_prev_log_size_1x
= 1;
103 sdl_vscr
= realloc(sdl_vscr
, SCR_WIDTH
*SCR_HEIGHT
*sizeof(sdl_vscr
[0]));
104 if (sdl_vscr
== NULL
) {
105 fprintf(stderr
, "FATAL: out of memory for virtual screen!\n");
108 sdl_vscr2x
= realloc(sdl_vscr2x
, SCR_WIDTH
*sdlc_mag2x
*SCR_HEIGHT
*sdlc_mag2x
*sizeof(sdl_vscr2x
[0]));
109 if (sdl_vscr
== NULL
) {
110 fprintf(stderr
, "FATAL: out of memory for 2x virtual screen!\n");
113 sdl_win
= SDL_CreateWindow((window_name
? window_name
: "SDL Application"),
114 SDL_WINDOWPOS_UNDEFINED
, SDL_WINDOWPOS_UNDEFINED
, SCR_WIDTH
*sdlc_mag2x
, SCR_HEIGHT
*sdlc_mag2x
,
115 (sdl_fs
? (sdl_real_fs
? SDL_WINDOW_FULLSCREEN
: SDL_WINDOW_FULLSCREEN_DESKTOP
) : 0)|(sdl_opengl
? SDL_WINDOW_OPENGL
: 0));
116 if (sdl_win
== NULL
) {
117 fprintf(stderr
, "FATAL: can't create SDL window: %s\n", SDL_GetError());
120 sdl_rend
= SDL_CreateRenderer(sdl_win
, -1, (sdl_vsync
? SDL_RENDERER_PRESENTVSYNC
: 0));
121 if (sdl_rend
== NULL
) {
122 fprintf(stderr
, "FATAL: can't create SDL renderer: %s\n", SDL_GetError());
125 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY
, "nearest"); // "nearest" or "linear"
126 SDL_RenderSetLogicalSize(sdl_rend
, SCR_WIDTH
*(2-sdl_prev_log_size_1x
), SCR_HEIGHT
*(2-sdl_prev_log_size_1x
));
127 sdl_scr
= SDL_CreateTexture(sdl_rend
, SDL_PIXELFORMAT_ARGB8888
, SDL_TEXTUREACCESS_STREAMING
, SCR_WIDTH
, SCR_HEIGHT
);
128 if (sdl_scr
== NULL
) {
129 fprintf(stderr
, "FATAL: can't create SDL texture: %s\n", SDL_GetError());
132 if (sdlc_mag2x
== 2) {
133 sdl_scr2x
= SDL_CreateTexture(sdl_rend
, SDL_PIXELFORMAT_ARGB8888
, SDL_TEXTUREACCESS_STREAMING
, SCR_WIDTH
*2, SCR_HEIGHT
*2);
134 if (sdl_scr2x
== NULL
) {
135 fprintf(stderr
, "FATAL: can't create SDL texture: %s\n", SDL_GetError());
144 ////////////////////////////////////////////////////////////////////////////////
145 void switch_fullscreen (void) {
147 if (SDL_SetWindowFullscreen(sdl_win
, (sdl_fs
? (sdl_real_fs
? SDL_WINDOW_FULLSCREEN
: SDL_WINDOW_FULLSCREEN_DESKTOP
) : 0)) != 0) {
148 fprintf(stderr
, "FATAL: can't switch fullscreen mode: %s\n", SDL_GetError());
153 SDL_SetWindowSize(sdl_win
, SCR_WIDTH
*sdlc_mag2x
, SCR_HEIGHT
*sdlc_mag2x
);
154 SDL_SetWindowPosition(sdl_win
, SDL_WINDOWPOS_CENTERED
, SDL_WINDOWPOS_CENTERED
);
159 ////////////////////////////////////////////////////////////////////////////////
160 extern void post_quit_message (void) {
162 memset(&evt
, 0, sizeof(evt
));
168 ////////////////////////////////////////////////////////////////////////////////
169 int sdl_frame_changed
= 1;
172 ////////////////////////////////////////////////////////////////////////////////
173 static void blit1x_bw (void) {
174 const Uint8
*s
= (const Uint8
*)sdl_vscr
;
175 Uint8
*d
= (Uint8
*)sdl_vscr2x
;
176 int f
= SCR_WIDTH
*SCR_HEIGHT
;
178 Uint8 i
= (s
[0]*28+s
[1]*151+s
[2]*77)/256; /* intensity */
179 d
[0] = d
[1] = d
[2] = i
;
186 static void blit1x_green (void) {
187 const Uint8
*s
= (const Uint8
*)sdl_vscr
;
188 Uint8
*d
= (Uint8
*)sdl_vscr2x
;
189 int f
= SCR_WIDTH
*SCR_HEIGHT
;
191 Uint8 i
= (s
[0]*28+s
[1]*151+s
[2]*77)/256; /* intensity */
200 ////////////////////////////////////////////////////////////////////////////////
201 static void blit2xtv (void) {
202 const Uint32
*s
= sdl_vscr
;
203 Uint32
*d
= sdl_vscr2x
;
204 for (int y
= 0; y
< SCR_HEIGHT
; ++y
) {
207 Uint32 c0
= *s
++, c1
;
208 c1
= (((c0
&0x00ff00ff)*6)>>3)&0x00ff00ff;
209 c1
|= (((c0
&0x0000ff00)*6)>>3)&0x0000ff00;
211 d
[SCR_WIDTH
*2+0] = d
[SCR_WIDTH
*2+1] = c1
;
214 /* fix d: skip one scanline */
220 static void blit2xtv_bw (void) {
221 const Uint8
*s
= (const Uint8
*)sdl_vscr
;
222 Uint32
*d
= sdl_vscr2x
;
223 for (int y
= 0; y
< SCR_HEIGHT
; ++y
) {
227 Uint8 i
= (s
[0]*28+s
[1]*151+s
[2]*77)/256; /* intensity */
228 c0
= (i
<<16)|(i
<<8)|i
;
229 c1
= (((c0
&0x00ff00ff)*6)>>3)&0x00ff00ff;
230 c1
|= (((c0
&0x0000ff00)*6)>>3)&0x0000ff00;
232 d
[SCR_WIDTH
*2+0] = d
[SCR_WIDTH
*2+1] = c1
;
236 /* fix d: skip one scanline */
242 static void blit2xtv_green (void) {
243 const Uint8
*s
= (const Uint8
*)sdl_vscr
;
244 Uint32
*d
= sdl_vscr2x
;
245 for (int y
= 0; y
< SCR_HEIGHT
; ++y
) {
249 Uint8 i
= (s
[0]*28+s
[1]*151+s
[2]*77)/256; /* intensity */
251 c1
= (((c0
&0x00ff00ff)*6)>>3)&0x00ff00ff;
252 c1
|= (((c0
&0x0000ff00)*6)>>3)&0x0000ff00;
254 d
[SCR_WIDTH
*2+0] = d
[SCR_WIDTH
*2+1] = c1
;
258 /* fix d: skip one scanline */
264 ////////////////////////////////////////////////////////////////////////////////
265 void paint_screen (void) {
266 /* fix 'logical size' */
267 if (sdlc_mag2x
== 2 && sdl_scanlines
) {
268 /* mag2x and scanlines: size is 2x */
269 if (sdl_prev_log_size_1x
) {
270 sdl_prev_log_size_1x
= 0;
271 SDL_RenderSetLogicalSize(sdl_rend
, SCR_WIDTH
*2, SCR_HEIGHT
*2);
274 /* any other case: size is 2x */
275 if (!sdl_prev_log_size_1x
) {
276 sdl_prev_log_size_1x
= 1;
277 SDL_RenderSetLogicalSize(sdl_rend
, SCR_WIDTH
, SCR_HEIGHT
);
280 /* apply filters if any */
281 if (sdlc_mag2x
== 2 && sdl_scanlines
) {
282 /* heavy case: scanline filter turned on */
283 switch (sdl_filter
) {
284 case SDL_FILTER_NONE
: blit2xtv(); break;
285 case SDL_FILTER_BLACKNWHITE
: blit2xtv_bw(); break;
286 case SDL_FILTER_GREEN
: blit2xtv_green(); break;
288 SDL_UpdateTexture(sdl_scr2x
, NULL
, sdl_vscr2x
, SCR_WIDTH
*2*sizeof(sdl_vscr2x
[0]));
289 SDL_RenderCopy(sdl_rend
, sdl_scr2x
, NULL
, NULL
);
292 if (sdl_filter
== SDL_FILTER_NONE
) {
294 SDL_UpdateTexture(sdl_scr
, NULL
, sdl_vscr
, SCR_WIDTH
*sizeof(sdl_vscr
[0]));
296 switch (sdl_filter
) {
297 case SDL_FILTER_BLACKNWHITE
: blit1x_bw(); break;
298 case SDL_FILTER_GREEN
: blit1x_green(); break;
299 default: memcpy(sdl_vscr2x
, sdl_vscr
, SCR_WIDTH
*SCR_HEIGHT
); break; /* just in case */
301 SDL_UpdateTexture(sdl_scr
, NULL
, sdl_vscr2x
, SCR_WIDTH
*sizeof(sdl_vscr2x
[0]));
303 SDL_RenderCopy(sdl_rend
, sdl_scr
, NULL
, NULL
);
305 SDL_RenderPresent(sdl_rend
);
306 sdl_frame_changed
= 0;
310 ////////////////////////////////////////////////////////////////////////////////
311 #ifdef VIDEOLIB_ENABLE_TEXT
312 #include "vfont_msx.c"
315 void draw_char (int x
, int y
, char ch
, Uint32 col
, Uint32 bkcol
) {
316 int pos
= (ch
&0xff)*8;
317 for (int dy
= 0; dy
< 8; ++dy
) {
318 unsigned char b
= font_msx
[pos
++];
319 for (int dx
= 0; dx
< 6; ++dx
) {
320 if (b
&0x80) { if (col
!= TRANSPARENT_COLOR
) put_pixel(x
+dx
, y
+dy
, col
); }
321 else if (bkcol
!= TRANSPARENT_COLOR
) put_pixel(x
+dx
, y
+dy
, bkcol
);
328 void draw_str (int x
, int y
, const char *str
, Uint32 col
, Uint32 bkcol
) {
331 draw_char(x
, y
, *str
++, col
, bkcol
);
338 ////////////////////////////////////////////////////////////////////////////////
339 #ifdef VIDEOLIB_ENABLE_PRTEXT
340 #include "vfont_pr.c"
341 int char_width_pr (char ch
) {
342 return (prfontwdt
[ch
&0xff]);
346 int str_width_pr (const char *str
) {
348 if (str
!= NULL
&& str
[0]) {
350 wdt
+= prfontwdt
[str
[0]&0xff]+1;
359 int draw_char_pr (int x
, int y
, char ch
, Uint32 col
, Uint32 bkcol
) {
360 int pos
= (ch
&0xff)*8;
361 int wdt
= prfontwdt
[ch
&0xff];
362 for (int dy
= 0; dy
< 8; ++dy
) {
363 unsigned char b
= prfont
[pos
++];
364 for (int dx
= 0; dx
< wdt
; ++dx
) {
365 Uint32 c
= (b
&0x80 ? col
: bkcol
);
366 if (c
!= TRANSPARENT_COLOR
) put_pixel(x
+dx
, y
+dy
, c
);
374 int draw_str_pr (int x
, int y
, const char *str
, Uint32 col
, Uint32 bkcol
) {
376 if (str
!= NULL
&& str
[0]) {
378 wdt
+= prfontwdt
[str
[0]&0xff]+1;
379 x
+= draw_char_pr(x
, y
, *str
++, col
, bkcol
);
380 if (*str
&& bkcol
!= TRANSPARENT_COLOR
) for (int dy
= 0; dy
< 8; ++dy
) put_pixel(x
, y
+dy
, bkcol
);
390 ////////////////////////////////////////////////////////////////////////////////
391 #ifdef VIDEOLIB_ENABLE_SFONT
392 #include "vfont_sf.c"
395 int char_width_sf (char ch
) {
396 if (ch
>= 'a' && ch
<= 'z') ch
-= 32;
397 if (ch
< 33 || ch
> 95) ch
= '?';
399 const unsigned char *st
= font_sf
+(ch
-32)*2;
400 int ofs
= st
[0]+256*st
[1];
408 int str_width_sf (const char *str
) {
411 while (*str
) wdt
+= char_width_sf(*str
++);
417 int draw_char_sf (char ch
, int x
, int y
, Uint32 c0
, Uint32 c1
) {
418 if (ch
>= 'a' && ch
<= 'z') ch
-= 32;
419 if (ch
< 33 || ch
> 95) ch
= '?';
421 const unsigned char *st
= font_sf
+(ch
-32)*2;
422 int ofs
= st
[0]+256*st
[1], wdt
, yofs
, hgt
= font_sf
[0];
426 yofs
= ((wdt
>>4)&0x0f);
428 if ((c0
&0xff) == 0xff && (c1
&0xff) == 0xff) return wdt
;
432 for (int dx
= 0; dx
< wdt
; dx
+= 4) {
434 for (int c
= 0; c
< 4; ++c
, ++px
) {
435 switch ((b
>>6)&0x03) {
437 case 1: put_pixel(px
, y
, c0
); break;
438 case 2: put_pixel(px
, y
, c1
); break;
439 case 3: /*put_pixel(x+dx+c, y+dy, 2);*/ break;
453 int draw_str_sf (const char *str
, int x
, int y
, Uint32 c0
, Uint32 c1
) {
457 int w
= draw_char_sf(*str
++, x
, y
, c0
, c1
);
467 ////////////////////////////////////////////////////////////////////////////////
468 void draw_hline (int x0
, int y0
, int len
, Uint32 col
) {
469 while (len
-- > 0) put_pixel(x0
++, y0
, col
);
473 void draw_vline (int x0
, int y0
, int len
, Uint32 col
) {
474 while (len
-- > 0) put_pixel(x0
, y0
++, col
);
478 void draw_line (int x0
, int y0
, int x1
, int y1
, Uint32 col
) {
479 int dx
= abs(x1
-x0
), sx
= (x0
< x1
? 1 : -1);
480 int dy
= -abs(y1
-y0
), sy
= (y0
< y1
? 1 : -1);
481 int err
= dx
+dy
, e2
; /* error value e_xy */
483 put_pixel(x0
, y0
, col
);
484 if (x0
== x1
&& y0
== y1
) break;
486 if (e2
>= dy
) { err
+= dy
; x0
+= sx
; } /* e_xy+e_x > 0 */
487 if (e2
<= dx
) { err
+= dx
; y0
+= sy
; } /* e_xy+e_y < 0 */
492 void draw_line_no_last (int x0
, int y0
, int x1
, int y1
, Uint32 col
) {
493 int dx
= abs(x1
-x0
), sx
= (x0
< x1
? 1 : -1);
494 int dy
= -abs(y1
-y0
), sy
= (y0
< y1
? 1 : -1);
495 int err
= dx
+dy
, e2
; /* error value e_xy */
497 if (x0
== x1
&& y0
== y1
) break;
498 put_pixel(x0
, y0
, col
);
500 if (e2
>= dy
) { err
+= dy
; x0
+= sx
; } /* e_xy+e_x > 0 */
501 if (e2
<= dx
) { err
+= dx
; y0
+= sy
; } /* e_xy+e_y < 0 */
506 void fill_rect (int x
, int y
, int w
, int h
, Uint32 col
) {
507 if (w
> 0 && h
> 0 && x
< SCR_WIDTH
&& y
< SCR_HEIGHT
&& x
+w
>= 0 && y
+h
>= 0) {
509 sr
.x
= 0; sr
.y
= 0; sr
.w
= SCR_WIDTH
; sr
.h
= SCR_HEIGHT
;
510 r
.x
= x
; r
.y
= y
; r
.w
= w
; r
.h
= h
;
511 if (SDL_IntersectRect(&sr
, &r
, &dr
)) {
515 for (int dx
= dr
.w
; dx
> 0; --dx
, ++x
) put_pixel(x
, y
, col
);
519 Uint32 a = dr.y*SCR_WIDTH+dr.x;
522 for (int f = dr.w; f > 0; --f) sdl_vscr[da++] = col;
531 void draw_rect (int x
, int y
, int w
, int h
, Uint32 col
) {
532 if (w
> 0 && h
> 0) {
533 draw_hline(x
, y
, w
, col
);
534 draw_hline(x
, y
+h
-1, w
, col
);
535 draw_vline(x
, y
+1, h
-2, col
);
536 draw_vline(x
+w
-1, y
+1, h
-2, col
);
541 void draw_selection_rect (int phase
, int x0
, int y0
, int wdt
, int hgt
, Uint32 col0
, Uint32 col1
) {
542 if (wdt
> 0 && hgt
> 0) {
544 for (int f
= x0
; f
< x0
+wdt
; ++f
, ++phase
) put_pixel(f
, y0
, ((phase
%= 4) < 2 ? col0
: col1
));
546 for (int f
= y0
+1; f
< y0
+hgt
; ++f
, ++phase
) put_pixel(x0
+wdt
-1, f
, ((phase
%= 4) < 2 ? col0
: col1
));
548 for (int f
= x0
+wdt
-2; f
>= x0
; --f
, ++phase
) put_pixel(f
, y0
+hgt
-1, ((phase
%= 4) < 2 ? col0
: col1
));
550 for (int f
= y0
+hgt
-2; f
>= y0
; --f
, ++phase
) put_pixel(x0
, f
, ((phase
%= 4)<2 ? col0
: col1
));
555 ////////////////////////////////////////////////////////////////////////////////
556 #ifdef VIDEOLIB_ENABLE_CIRCLE_ELLIPSE
558 #define PLOT_4_POINTS(_cx,_cy,_x,_y) do { \
559 put_pixel((_cx)+(_x), (_cy)+(_y), clr); \
560 if ((_x) != 0) put_pixel((_cx)-(_x), (_cy)+(_y), clr); \
561 if ((_y) != 0) put_pixel((_cx)+(_x), (_cy)-(_y), clr); \
562 put_pixel((_cx)-(_x), (_cy)-(_y), clr); \
566 void draw_circle (int cx
, int cy
, int radius
, Uint32 clr
) {
567 if (radius
> 0 && (clr
&0xff000000u
) != 0xff000000u
) {
568 int error
= -radius
, x
= radius
, y
= 0;
569 if (radius
== 1) { put_pixel(cx
, cy
, clr
); return; }
571 PLOT_4_POINTS(cx
, cy
, x
, y
);
572 PLOT_4_POINTS(cx
, cy
, y
, x
);
575 if (error
>= 0) { --x
; error
-= x
*2; }
577 PLOT_4_POINTS(cx
, cy
, x
, y
);
582 void draw_filled_circle (int cx
, int cy
, int radius
, Uint32 clr
) {
583 if (radius
> 0 && (clr
&0xff000000u
) != 0xff000000u
) {
584 int error
= -radius
, x
= radius
, y
= 0;
585 if (radius
== 1) { put_pixel(cx
, cy
, clr
); return; }
591 draw_hline(cx
-x
, cy
+last_y
, 2*x
+1, clr
);
592 if (x
!= 0 && last_y
!= 0) draw_hline(cx
-x
, cy
-last_y
, 2*x
+1, clr
);
595 draw_hline(cx
-last_y
, cy
+x
, 2*last_y
+1, clr
);
596 if (last_y
!= 0 && x
!= 0) draw_hline(cx
-last_y
, cy
-x
, 2*last_y
+1, clr
);
607 void draw_ellipse (int x0
, int y0
, int x1
, int y1
, Uint32 clr
) {
608 int a
= abs(x1
-x0
), b
= abs(y1
-y0
), b1
= b
&1; /* values of diameter */
609 long dx
= 4*(1-a
)*b
*b
, dy
= 4*(b1
+1)*a
*a
; /* error increment */
610 long err
= dx
+dy
+b1
*a
*a
; /* error of 1.step */
611 if (x0
> x1
) { x0
= x1
; x1
+= a
; } /* if called with swapped points... */
612 if (y0
> y1
) y0
= y1
; /* ...exchange them */
613 y0
+= (b
+1)/2; y1
= y0
-b1
; /* starting pixel */
614 a
*= 8*a
; b1
= 8*b
*b
;
617 put_pixel(x1
, y0
, clr
); /* I. Quadrant */
618 put_pixel(x0
, y0
, clr
); /* II. Quadrant */
619 put_pixel(x0
, y1
, clr
); /* III. Quadrant */
620 put_pixel(x1
, y1
, clr
); /* IV. Quadrant */
622 if (e2
>= dx
) { ++x0
; --x1
; err
+= dx
+= b1
; } /* x step */
623 if (e2
<= dy
) { ++y0
; --y1
; err
+= dy
+= a
; } /* y step */
626 /* too early stop of flat ellipses a=1 */
627 put_pixel(x0
-1, ++y0
, clr
); /* -> complete tip of ellipse */
628 put_pixel(x0
-1, --y1
, clr
);
633 void draw_filled_ellipse (int x0
, int y0
, int x1
, int y1
, Uint32 clr
) {
634 int a
= abs(x1
-x0
), b
= abs(y1
-y0
), b1
= b
&1; /* values of diameter */
635 long dx
= 4*(1-a
)*b
*b
, dy
= 4*(b1
+1)*a
*a
; /* error increment */
636 long err
= dx
+dy
+b1
*a
*a
; /* error of 1.step */
637 int prev_y0
= -1, prev_y1
= -1;
638 if (x0
> x1
) { x0
= x1
; x1
+= a
; } /* if called with swapped points... */
639 if (y0
> y1
) y0
= y1
; /* ...exchange them */
640 y0
+= (b
+1)/2; y1
= y0
-b1
; /* starting pixel */
641 a
*= 8*a
; b1
= 8*b
*b
;
644 if (y0
!= prev_y0
) { draw_hline(x0
, y0
, x1
-x0
+1, clr
); prev_y0
= y0
; }
645 if (y1
!= y0
&& y1
!= prev_y1
) { draw_hline(x0
, y1
, x1
-x0
+1, clr
); prev_y1
= y1
; }
647 if (e2
>= dx
) { ++x0
; --x1
; err
+= dx
+= b1
; } /* x step */
648 if (e2
<= dy
) { ++y0
; --y1
; err
+= dy
+= a
; } /* y step */
651 /* too early stop of flat ellipses a=1 */
652 put_pixel(x0
-1, ++y0
, clr
); /* -> complete tip of ellipse */
653 put_pixel(x0
-1, --y1
, clr
);
659 #ifdef VIDEOLIB_ENABLE_POLYMOD
660 void vl_polymod_fill_scr (Uint32 col
) {
661 void hline (int x
, int y
, int len
) { draw_hline(x
, y
, len
, col
); }
663 vl_polymod_hline_fn ocb
= vl_polymod_hline
;
664 vl_polymod_hline
= hline
;
666 vl_polymod_hline
= ocb
;