aboutsummaryrefslogtreecommitdiff
path: root/modules/libdraw/libdraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/libdraw/libdraw.c')
-rw-r--r--modules/libdraw/libdraw.c1633
1 files changed, 1633 insertions, 0 deletions
diff --git a/modules/libdraw/libdraw.c b/modules/libdraw/libdraw.c
new file mode 100644
index 0000000..9884ec9
--- /dev/null
+++ b/modules/libdraw/libdraw.c
@@ -0,0 +1,1633 @@
+/*
+ * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd)
+ * Copyright © 2002-2006 Fenix Team (Fenix)
+ * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix)
+ *
+ * This file is part of Bennu - Game Development
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ */
+
+/* --------------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "bgdrtm.h"
+
+#include "bgddl.h"
+#include "libblit.h"
+#include "libdraw.h"
+#include "fmath.h"
+
+/* --------------------------------------------------------------------------- */
+
+uint32_t drawing_stipple = 0xFFFFFFFF;
+
+/* --------------------------------------------------------------------------- */
+
+#ifdef __GNUC__
+#define _inline inline
+#endif
+
+_inline void _HLine8_nostipple( uint8_t * ptr, uint32_t length )
+{
+ if ( pixel_alpha == 255 )
+ {
+ memset( ptr, pixel_color8, length + 1 ) ;
+ }
+ else
+ {
+ register int n;
+ for ( n = length; n >= 0; n--, ptr++ )
+ *ptr = pixel_alpha8[( pixel_color8 << 8 ) + *ptr ];
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+
+_inline void _HLine8_stipple( uint8_t * ptr, uint32_t length )
+{
+ register int n;
+
+ if ( pixel_alpha == 255 )
+ {
+ for ( n = length; n >= 0; n--, ptr++ )
+ {
+ if ( drawing_stipple & 1 ) * ptr = pixel_color8;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+ else
+ {
+ for ( n = length; n >= 0; n--, ptr++ )
+ {
+ if ( drawing_stipple & 1 ) * ptr = pixel_alpha8[( pixel_color8 << 8 ) + *ptr ];
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+
+_inline void _HLine16_nostipple( uint16_t * ptr, uint32_t length )
+{
+ register int n ;
+
+ if ( pixel_alpha == 255 )
+ {
+ for ( n = length; n >= 0; n-- ) *ptr++ = pixel_color16 ;
+ }
+ else
+ {
+ for ( n = length; n >= 0; n--, ptr++ ) *ptr = pixel_alpha16[ *ptr ] + pixel_color16_alpha ;
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+
+_inline void _HLine16_stipple( uint16_t * ptr, uint32_t length )
+{
+ register int n ;
+
+ if ( pixel_alpha == 255 )
+ {
+ for ( n = length; n >= 0; n--, ptr++ )
+ {
+ if ( drawing_stipple & 1 ) * ptr = pixel_color16 ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+ else
+ {
+ for ( n = length; n >= 0; n--, ptr++ )
+ {
+ if ( drawing_stipple & 1 ) * ptr = pixel_alpha16[ *ptr ] + pixel_color16_alpha ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+
+_inline void _HLine32_nostipple( uint32_t * ptr, uint32_t length )
+{
+ register int n ;
+
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ for ( n = length; n >= 0; n-- ) *ptr++ = pixel_color32 ;
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ for ( n = length; n >= 0; n-- )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr++ = _f | r | g | b ;
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ for ( n = length; n >= 0; n-- )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr++ = 0xff000000 | r | g | b ;
+ }
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+
+_inline void _HLine32_stipple( uint32_t * ptr, uint32_t length )
+{
+ register int n ;
+
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ for ( n = length; n >= 0; n-- )
+ {
+ if ( drawing_stipple & 1 ) *ptr = pixel_color32 ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ for ( n = length; n >= 0; n-- )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr++ = _f | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ for ( n = length; n >= 0; n-- )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr++ = 0xff000000 | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : draw_vline
+ *
+ * Draw a vertical line
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * x, y Coordinates of the top-left pixel
+ * h Height in pixels
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_vline( GRAPH * dest, REGION * clip, int x, int y, int h )
+{
+ REGION base_clip ;
+ int old_stipple = drawing_stipple;
+
+ if ( !dest ) dest = scrbitmap ;
+ if ( !clip )
+ {
+ clip = &base_clip ;
+ clip->x = 0 ;
+ clip->y = 0 ;
+ clip->x2 = dest->width - 1 ;
+ clip->y2 = dest->height - 1 ;
+ }
+ else
+ {
+ base_clip = *clip ;
+ clip = &base_clip ;
+ clip->x = MAX( MIN( clip->x, clip->x2 ), 0 ) ;
+ clip->y = MAX( MIN( clip->y, clip->y2 ), 0 ) ;
+ clip->x2 = MIN( MAX( clip->x, clip->x2 ), dest->width - 1 ) ;
+ clip->y2 = MIN( MAX( clip->y, clip->y2 ), dest->height - 1 ) ;
+ }
+
+ dest->modified = 2 ;
+ dest->info_flags &= ~GI_CLEAN;
+
+ if ( h < 0 ) h = -h, y -= ( h /*- 1*/ ) ;
+
+ if ( x < clip->x || x > clip->x2 ) return ;
+
+ if ( y < clip->y ) h += y - clip->y, y = clip->y;
+ if ( y + h > clip->y2 ) h = clip->y2 - y /*+ 1*/ ;
+
+ switch ( dest->format->depth )
+ {
+ case 1:
+ {
+ uint8_t * ptr = dest->data;
+ int mask ;
+ ptr += dest->pitch * y + ( x >> 3 ) ;
+ mask = ( 1 << ( 7 - ( x & 7 ) ) );
+ if ( drawing_stipple != 0xFFFFFFFF )
+ {
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ if ( !pixel_color8 )
+ * ptr &= ~mask;
+ else
+ *ptr |= mask;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += dest->pitch ;
+ }
+ }
+ else
+ {
+ while ( h-- >= 0 )
+ {
+ if ( !pixel_color8 )
+ * ptr &= ~mask;
+ else
+ *ptr |= mask;
+ ptr += dest->pitch ;
+ }
+ }
+ }
+
+ case 8:
+ {
+ uint8_t * ptr = dest->data ;
+ ptr += dest->pitch * y + x ;
+ if ( drawing_stipple != 0xFFFFFFFF )
+ {
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 ) _Pixel8( ptr, pixel_color8 ) ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += dest->pitch ;
+ }
+ }
+ else
+ {
+ while ( h-- >= 0 )
+ {
+ _Pixel8( ptr, pixel_color8 ) ;
+ ptr += dest->pitch ;
+ }
+ }
+ }
+ break;
+
+ case 16:
+ {
+ uint16_t * ptr = dest->data ;
+ int inc = dest->pitch >> 1 ;
+ ptr += inc * y + x ;
+ if ( drawing_stipple != 0xFFFFFFFF )
+ {
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 ) _Pixel16( ptr, pixel_color16, pixel_color16_alpha ) ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += inc ;
+ }
+ }
+ else
+ {
+ while ( h-- >= 0 )
+ {
+ _Pixel16( ptr, pixel_color16, pixel_color16_alpha ) ;
+ ptr += inc ;
+ }
+ }
+ }
+ break;
+
+ case 32:
+ {
+ uint32_t * ptr = dest->data ;
+ int inc = dest->pitch >> 2 ;
+ ptr += inc * y + x ;
+ if ( drawing_stipple != 0xFFFFFFFF )
+ {
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 ) * ptr = pixel_color32 ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += inc ;
+ }
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = _f | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += inc;
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = 0xff000000 | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += inc;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ while ( h-- >= 0 )
+ {
+ * ptr = pixel_color32 ;
+ ptr += inc ;
+ }
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ while ( h-- >= 0 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = _f | r | g | b ;
+ ptr += inc;
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ while ( h-- >= 0 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = 0xff000000 | r | g | b ;
+ ptr += inc;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ drawing_stipple = old_stipple;
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : gr_gline
+ *
+ * Draw an horizontal line
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * x, y Coordinates of the top-left pixel
+ * w Width in pixels
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_hline( GRAPH * dest, REGION * clip, int x, int y, int w )
+{
+ REGION base_clip ;
+ int old_stipple = drawing_stipple;
+
+ if ( !dest ) dest = scrbitmap ;
+ if ( !clip )
+ {
+ clip = &base_clip ;
+ clip->x = 0 ;
+ clip->y = 0 ;
+ clip->x2 = dest->width - 1 ;
+ clip->y2 = dest->height - 1 ;
+ }
+ else
+ {
+ base_clip = *clip ;
+ clip = &base_clip ;
+ clip->x = MAX( MIN( clip->x, clip->x2 ), 0 ) ;
+ clip->y = MAX( MIN( clip->y, clip->y2 ), 0 ) ;
+ clip->x2 = MIN( MAX( clip->x, clip->x2 ), dest->width - 1 ) ;
+ clip->y2 = MIN( MAX( clip->y, clip->y2 ), dest->height - 1 ) ;
+ }
+
+ dest->modified = 2 ;
+ dest->info_flags &= ~GI_CLEAN;
+
+ if ( w < 0 ) w = -w, x -= ( w /*- 1*/ ) ;
+
+ if ( y < clip->y || y > clip->y2 ) return ;
+
+ if ( x < clip->x ) w += x - clip->x, x = clip->x ;
+ if ( x + w > clip->x2 ) w = clip->x2 - x /* + 1*/ ;
+
+ switch ( dest->format->depth )
+ {
+ case 1:
+ {
+ uint8_t * ptr = dest->data;
+ int mask ;
+ ptr += dest->pitch * y + ( x >> 3 );
+ mask = ( 1 << ( 7 - ( x & 7 ) ) );
+
+ if ( drawing_stipple != 0xFFFFFFFF )
+ {
+ while ( w-- > 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ if ( !pixel_color8 )
+ * ptr &= ~mask;
+ else
+ *ptr |= mask;
+ }
+ mask >>= 1;
+ if ( !mask )
+ {
+ mask = 0x80;
+ ptr++;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ }
+ }
+ else
+ {
+ while ( w-- > 0 )
+ {
+ if ( !pixel_color8 )
+ * ptr &= ~mask;
+ else
+ *ptr |= mask;
+ mask >>= 1;
+ if ( !mask )
+ {
+ mask = 0x80;
+ ptr++;
+ }
+ }
+ }
+ }
+ break;
+
+ case 8:
+ {
+ uint8_t * ptr = dest->data ;
+ ptr += dest->pitch * y + x ;
+ if ( drawing_stipple == 0xFFFFFFFF )
+ _HLine8_nostipple( ptr, w ) ;
+ else
+ _HLine8_stipple( ptr, w ) ;
+ }
+ break;
+
+ case 16:
+ {
+ uint16_t * ptr = dest->data ;
+ ptr += ( dest->pitch >> 1 ) * y + x ;
+ if ( drawing_stipple == 0xFFFFFFFF )
+ _HLine16_nostipple( ptr, w ) ;
+ else
+ _HLine16_stipple( ptr, w ) ;
+ }
+ break;
+
+ case 32:
+ {
+ uint32_t * ptr = dest->data ;
+ ptr += ( dest->pitch >> 2 ) * y + x ;
+ if ( drawing_stipple == 0xFFFFFFFF )
+ _HLine32_nostipple( ptr, w ) ;
+ else
+ _HLine32_stipple( ptr, w ) ;
+ }
+ break;
+ }
+
+ drawing_stipple = old_stipple;
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : draw_box
+ *
+ * Draw a filled rectangle
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * x, y Coordinates of the top-left pixel
+ * w Width in pixels
+ * h Height in pixels
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_box( GRAPH * dest, REGION * clip, int x, int y, int w, int h )
+{
+ REGION base_clip ;
+
+ if ( !dest ) dest = scrbitmap ;
+ if ( !clip )
+ {
+ clip = &base_clip ;
+ clip->x = 0 ;
+ clip->y = 0 ;
+ clip->x2 = dest->width - 1 ;
+ clip->y2 = dest->height - 1 ;
+ }
+ else
+ {
+ base_clip = *clip ;
+ clip = &base_clip ;
+ clip->x = MAX( MIN( clip->x, clip->x2 ), 0 ) ;
+ clip->y = MAX( MIN( clip->y, clip->y2 ), 0 ) ;
+ clip->x2 = MIN( MAX( clip->x, clip->x2 ), dest->width - 1 ) ;
+ clip->y2 = MIN( MAX( clip->y, clip->y2 ), dest->height - 1 ) ;
+ }
+
+ dest->modified = 2 ;
+ dest->info_flags &= ~GI_CLEAN;
+
+ if ( w < 0 ) w = -w, x -= ( w /*- 1*/ ) ;
+ if ( h < 0 ) h = -h, y -= ( h /*- 1*/ ) ;
+
+ if ( x < clip->x ) w += x - clip->x, x = clip->x ;
+ if ( y < clip->y ) h += y - clip->y, y = clip->y ;
+
+ if ( x + w > clip->x2 ) w = clip->x2 - ( x /*+ 1*/ ) ;
+ if ( y + h > clip->y2 ) h = clip->y2 - ( y /*+ 1*/ ) ;
+
+ if ( w < 0 || h < 0 ) return ;
+
+ switch ( dest->format->depth )
+ {
+ case 1:
+ {
+ int old_stipple = drawing_stipple;
+ drawing_stipple = 0xFFFFFFFF;
+
+ while ( h-- >= 0 ) draw_hline( dest, clip, x, y + h, w );
+
+ drawing_stipple = old_stipple;
+ }
+ break;
+
+ case 8:
+ {
+ uint8_t * ptr = dest->data ;
+ ptr += dest->pitch * y + x ;
+ while ( h-- >= 0 )
+ {
+ _HLine8_nostipple( ptr, w ) ;
+ ptr += dest->pitch ;
+ }
+ }
+ break;
+
+ case 16:
+ {
+ uint16_t * ptr = dest->data ;
+ int inc = dest->pitch >> 1 ;
+ ptr += inc * y + x ;
+ while ( h-- >= 0 )
+ {
+ _HLine16_nostipple( ptr, w ) ;
+ ptr += inc ;
+ }
+ }
+ break;
+
+ case 32:
+ {
+ uint32_t * ptr = dest->data ;
+ int inc = dest->pitch >> 2 ;
+ ptr += inc * y + x ;
+ while ( h-- >= 0 )
+ {
+ _HLine32_nostipple( ptr, w ) ;
+ ptr += inc ;
+ }
+ }
+ break;
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : draw_rectangle
+ *
+ * Draw a rectangle (non-filled)
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * x, y Coordinates of the top-left pixel
+ * w Width in pixels
+ * h Height in pixels
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_rectangle( GRAPH * dest, REGION * clip, int x, int y, int w, int h )
+{
+ int stipple = drawing_stipple ;
+ int iw, ih;
+
+ iw = SGN( w );
+ ih = SGN( h );
+
+ draw_hline( dest, clip, x, y, w - iw );
+ if ( h ) draw_vline( dest, clip, x + w, y, h - ih );
+ if ( w && h ) draw_hline( dest, clip, x + w, y + h, -( w - iw ) );
+ if ( h && w ) draw_vline( dest, clip, x, y + h, -( h - ih ) );
+
+ drawing_stipple = stipple ;
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : draw_circle
+ *
+ * Draw a circle
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * x, y Coordinates of the center
+ * r Radius, in pixels
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_circle( GRAPH * dest, REGION * clip, int x, int y, int r )
+{
+ int cx = 0, cy = r;
+ int lcy = -1;
+ int df = 1 - r, de = 3, dse = -2 * r + 5;
+ int old_stipple = drawing_stipple;
+ REGION base_clip ;
+ int color = 0;
+
+ if ( !dest ) dest = scrbitmap ;
+ if ( !clip )
+ {
+ clip = &base_clip ;
+ clip->x = 0 ;
+ clip->y = 0 ;
+ clip->x2 = dest->width - 1 ;
+ clip->y2 = dest->height - 1 ;
+ }
+ else
+ {
+ base_clip = *clip ;
+ clip = &base_clip ;
+ clip->x = MAX( MIN( clip->x, clip->x2 ), 0 ) ;
+ clip->y = MAX( MIN( clip->y, clip->y2 ), 0 ) ;
+ clip->x2 = MIN( MAX( clip->x, clip->x2 ), dest->width - 1 ) ;
+ clip->y2 = MIN( MAX( clip->y, clip->y2 ), dest->height - 1 ) ;
+ }
+
+ dest->modified = 2 ;
+ dest->info_flags &= ~GI_CLEAN;
+
+ if ( dest->format->depth == 8 || dest->format->depth == 1 )
+ {
+ color = pixel_color8;
+ }
+ else if ( dest->format->depth == 16 )
+ {
+ color = pixel_color16;
+ }
+ else if ( dest->format->depth == 32 )
+ {
+ color = pixel_color32;
+ }
+
+ do
+ {
+ if ( drawing_stipple & 1 )
+ {
+ gr_put_pixelc( dest, clip, x - cx, y - cy, color ) ;
+ if ( cx ) gr_put_pixelc( dest, clip, x + cx, y - cy, color ) ;
+
+ if ( cy )
+ {
+ gr_put_pixelc( dest, clip, x - cx, y + cy, color ) ;
+ if ( cx ) gr_put_pixelc( dest, clip, x + cx, y + cy, color ) ;
+ }
+
+ if ( cx != cy )
+ {
+ gr_put_pixelc( dest, clip, x - cy, y - cx, color ) ;
+ if ( cy ) gr_put_pixelc( dest, clip, x + cy, y - cx, color ) ;
+ }
+
+ if ( cx && cy != cx )
+ {
+ gr_put_pixelc( dest, clip, x - cy, y + cx, color ) ;
+ if ( cy ) gr_put_pixelc( dest, clip, x + cy, y + cx, color ) ;
+ }
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+
+ lcy = cy;
+ cx++ ;
+ if ( df < 0 ) df += de, de += 2, dse += 2 ;
+ else df += dse, de += 2, dse += 4, cy-- ;
+ }
+ while ( cx <= cy ) ;
+
+ drawing_stipple = old_stipple;
+
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : draw_fcircle
+ *
+ * Draw a filled circle
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * x, y Coordinates of the center
+ * r Radius, in pixels
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_fcircle( GRAPH * dest, REGION * clip, int x, int y, int r )
+{
+ int cx = 0, cy = r;
+ int df = 1 - r, de = 3, dse = -2 * r + 5;
+ int old_stipple = drawing_stipple;
+ drawing_stipple = 0xFFFFFFFF;
+
+ do
+ {
+ if ( cx != cy )
+ {
+ draw_hline( dest, clip, x - cy, y - cx, cy << 1 /*+1*/ ) ;
+ if ( cx ) draw_hline( dest, clip, x - cy, y + cx, cy << 1 /*+1*/ ) ;
+ }
+ if ( df < 0 )
+ {
+ df += de, de += 2, dse += 2 ;
+ }
+ else
+ {
+ df += dse, de += 2, dse += 4;
+ draw_hline( dest, clip, x - cx, y - cy, cx << 1 /*+1*/ ) ;
+ if ( cy ) draw_hline( dest, clip, x - cx, y + cy, cx << 1 /*+1*/ ) ;
+ cy-- ;
+ }
+ cx++ ;
+ }
+ while ( cx <= cy ) ;
+
+ drawing_stipple = old_stipple;
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : draw_line
+ *
+ * Draw a line
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * x, y Coordinates of the first point
+ * w, h Distance to the second point
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_line( GRAPH * dest, REGION * clip, int x, int y, int w, int h )
+{
+ int n, m, hinc, vinc ;
+ REGION base_clip ;
+ int old_stipple = drawing_stipple;
+ int i1, i2, dd ;
+ int w1, h1;
+
+ if ( !w )
+ {
+ draw_vline( dest, clip, x, y, h ) ;
+ return ;
+ }
+
+ if ( !h )
+ {
+ draw_hline( dest, clip, x, y, w ) ;
+ return ;
+ }
+
+ if ( !dest ) dest = scrbitmap ;
+ if ( !clip )
+ {
+ clip = &base_clip ;
+ clip->x = 0 ;
+ clip->y = 0 ;
+ clip->x2 = dest->width - 1 ;
+ clip->y2 = dest->height - 1 ;
+ }
+ else
+ {
+ base_clip = *clip ;
+ clip = &base_clip ;
+ clip->x = MAX( MIN( clip->x, clip->x2 ), 0 ) ;
+ clip->y = MAX( MIN( clip->y, clip->y2 ), 0 ) ;
+ clip->x2 = MIN( MAX( clip->x, clip->x2 ), dest->width - 1 ) ;
+ clip->y2 = MIN( MAX( clip->y, clip->y2 ), dest->height - 1 ) ;
+ }
+
+ dest->modified = 2 ;
+ dest->info_flags &= ~GI_CLEAN;
+
+ w1 = ABS( w );
+ h1 = ABS( h );
+
+ /* Clipping de la línea - INCORRECTO pero funcional */
+
+ /* TODO: SE NECESITA CORREGIR CLIPPING EN LINE */
+
+ if ( x < clip->x )
+ { /* izquierda */
+ if (( x + w ) < clip->x ) return ;
+ n = clip->x - x;
+ m = w ? ( n * h ) / ABS( w ) : 0;
+ x += n, w -= n, y += m, h -= m ; // if (w == 0) return ;
+ }
+ if (( x + w ) < clip->x )
+ { /* w < 0 */
+ n = clip->x - ( x + w );
+ m = w ? ( n * h ) / ABS( w ) : 0;
+ w += n, h -= m ; // if (w == 0) return ;
+ }
+ if ( y < clip->y )
+ { /* arriba */
+ if (( y + h ) < clip->y ) return ;
+ m = clip->y - y;
+ n = h ? ( m * w ) / ABS( h ) : 0;
+ x += n, w -= n, y += m, h -= m ; // if (h == 0) return ;
+ }
+ if (( y + h ) < clip->y )
+ { /* h < 0 */
+ m = clip->y - ( y + h );
+ n = h ? ( m * w ) / ABS( h ) : 0;
+ w -= n, h += m ; // if (h == 0) return ;
+ }
+ if ( x > clip->x2 )
+ { /* derecha */
+ if (( x + w ) > clip->x2 ) return ;
+ n = x - clip->x2;
+ m = w ? ( n * h ) / ABS( w ) : 0;
+ x -= n, w += n, y += m, h -= m ; // if (w == 0) return ;
+ }
+ if (( x + w ) > clip->x2 )
+ { /* w > 0 */
+ n = ( x + w ) - clip->x2;
+ m = w ? ( n * h ) / ABS( w ) : 0;
+ w -= n, h -= m ; // if (w == 0) return ;
+ }
+ if ( y > clip->y2 )
+ { /* abajo */
+ if (( y + h ) > clip->y2 ) return ;
+ m = y - clip->y2;
+ n = h ? ( m * w ) / ABS( h ) : 0;
+ x += n, w -= n, y -= m, h += m ; // if (h == 0) return ;
+ }
+ if (( y + h ) > clip->y2 )
+ { /* h > 0 */
+ m = ( y + h ) - clip->y2;
+ n = h ? ( m * w ) / ABS( h ) : 0;
+ w -= n, h -= m ; // if (h == 0) return ;
+ }
+
+ hinc = ( w > 0 ) ? 1 : -1 ;
+ vinc = ( h > 0 ) ? dest->pitch : -( int ) dest->pitch ;
+
+ if ( dest->format->depth > 8 ) vinc /= dest->format->depthb;
+
+ /* Aquí va una implementación deprisa y corriendo de Bresenham */
+
+ w = ABS( w );
+ h = ABS( h );
+
+ if ( w > h )
+ {
+ i1 = 2 * h1;
+ dd = i1 - w1;
+ i2 = dd - w1;
+ dd -= w1 - w;
+ }
+ else
+ {
+ i1 = 2 * w1;
+ dd = i1 - h1;
+ i2 = dd - h1;
+ dd -= h1 - h;
+ }
+
+ switch ( dest->format->depth )
+ {
+ case 1:
+ {
+ uint8_t * ptr = dest->data + dest->pitch * y + ( x >> 3 ) ;
+ uint8_t mask, rmask ;
+ mask = ( 1 << ( 7 - ( x & 7 ) ) );
+
+ if ( hinc < 0 ) rmask = 0x01 ;
+ else rmask = 0x80 ;
+
+ if ( w > h ) while ( w-- > 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ if ( !pixel_color8 )
+ {
+ * ptr &= ~mask;
+ }
+ else
+ {
+ *ptr |= mask;
+ }
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ /* Vertical */
+ if ( dd >= 0 )
+ {
+ ptr += vinc, dd += i2 ;
+ }
+ else
+ {
+ dd += i1 ;
+ }
+ /* Horizontal */
+ if ( hinc < 0 )
+ {
+ mask <<= 1;
+ }
+ else
+ {
+ mask >>= 1;
+ }
+ if ( !mask ) mask = rmask, ptr += hinc ;
+ }
+ else while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ if ( !pixel_color8 )
+ {
+ * ptr &= ~mask ;
+ }
+ else
+ {
+ *ptr |= mask;
+ }
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ /* Vertical */
+ ptr += vinc;
+ if ( dd >= 0 )
+ {
+ dd += i2 ;
+ /* Horizontal */
+ if ( hinc < 0 )
+ {
+ mask <<= 1;
+ }
+ else
+ {
+ mask >>= 1;
+ }
+ if ( !mask ) mask = rmask, ptr += hinc ;
+ }
+ else
+ dd += i1 ;
+ }
+ }
+ break;
+
+ case 8:
+ {
+ uint8_t * ptr = ( uint8_t * ) dest->data + dest->pitch * y + x;
+
+ if ( w > h ) while ( w-- > 0 )
+ {
+ if ( drawing_stipple & 1 ) _Pixel8( ptr, pixel_color8 ) ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ else while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 ) _Pixel8( ptr, pixel_color8 ) ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ break;
+ case 16:
+ {
+ uint16_t * ptr = ( uint16_t * ) dest->data + ( dest->pitch >> 1 ) * y + x;
+
+ if ( w > h ) while ( w-- > 0 )
+ {
+ if ( drawing_stipple & 1 ) _Pixel16( ptr, pixel_color16, pixel_color16_alpha ) ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ else while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 ) _Pixel16( ptr, pixel_color16, pixel_color16_alpha ) ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ break;
+ case 32:
+ {
+ uint32_t * ptr = ( uint32_t * ) dest->data + ( dest->pitch >> 2 ) * y + x;
+
+ if ( drawing_stipple == 0xffffffff )
+ {
+ if ( w > h )
+ {
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ while ( w-- > 0 )
+ {
+ *ptr = pixel_color32 ;
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ while ( w-- > 0 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = _f | r | g | b ;
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ while ( w-- > 0 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = 0xff000000 | r | g | b ;
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ while ( h-- >= 0 )
+ {
+ *ptr = pixel_color32 ;
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ while ( h-- >= 0 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = _f | r | g | b ;
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ while ( h-- >= 0 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = 0xff000000 | r | g | b ;
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( w > h )
+ {
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ while ( w-- > 0 )
+ {
+ if ( drawing_stipple & 1 ) *ptr = pixel_color32 ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ while ( w-- > 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = _f | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ while ( w-- > 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = 0xff000000 | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += hinc;
+ if ( dd >= 0 ) ptr += vinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( pixel_alpha == 255 && ( pixel_color32 & 0xff000000 ) == 0xff000000 )
+ {
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 ) *ptr = pixel_color32 ;
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ unsigned int _f = pixel_color32 & 0xff000000, _f2 ;
+ unsigned int _c1, _c2, _c3 ;
+ unsigned int r, g, b ;
+
+ _f = ( _f >> 24 ) * pixel_alpha / 255 ;
+ _f2 = 255 - _f ;
+
+ if ( _f != 0x000000ff )
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * _f ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * _f ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * _f ;
+
+ _f <<= 24 ;
+
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = _f | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ else
+ {
+ _c1 = ( pixel_color32 & 0x00ff0000 ) * pixel_alpha ;
+ _c2 = ( pixel_color32 & 0x0000ff00 ) * pixel_alpha ;
+ _c3 = ( pixel_color32 & 0x000000ff ) * pixel_alpha ;
+
+ while ( h-- >= 0 )
+ {
+ if ( drawing_stipple & 1 )
+ {
+ r = ( _c1 + (( *ptr & 0x00ff0000 ) * _f2 ) ) >> 8 ;
+ g = ( _c2 + (( *ptr & 0x0000ff00 ) * _f2 ) ) >> 8 ;
+ b = ( _c3 + (( *ptr & 0x000000ff ) * _f2 ) ) >> 8 ;
+
+ if ( r > 0x00ff0000 ) r = 0x00ff0000 ; else r &= 0x00ff0000 ;
+ if ( g > 0x0000ff00 ) g = 0x0000ff00 ; else g &= 0x0000ff00 ;
+ if ( b > 0x000000ff ) b = 0x000000ff ; else b &= 0x000000ff ;
+
+ *ptr = 0xff000000 | r | g | b ;
+ }
+ drawing_stipple = (( drawing_stipple << 1 ) | (( drawing_stipple & 0x80000000 ) ? 1 : 0 ) );
+ ptr += vinc;
+ if ( dd >= 0 ) ptr += hinc, dd += i2 ;
+ else dd += i1 ;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ drawing_stipple = old_stipple;
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : draw_bezier
+ *
+ * Draw a bezier curve
+ *
+ * PARAMS :
+ * dest Destination bitmap or NULL for screen
+ * clip Clipping region or NULL for the whole screen
+ * params Pointer to an integer array with the parameters:
+ *
+ * x1, y1
+ * x2, y2
+ * x3, y3
+ * x4, y4 Curve points
+ * level Curve smoothness (1 to 15, 15 is more)
+ *
+ * RETURN VALUE :
+ * None
+ *
+ */
+
+void draw_bezier( GRAPH * dest, REGION * clip, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int level )
+{
+ float x = ( float ) x1, y = ( float ) y1;
+ float xp = x, yp = y;
+ float delta;
+ float dx, d2x, d3x;
+ float dy, d2y, d3y;
+ float a, b, c;
+ int i;
+ int n = 1;
+
+ dest->modified = 2 ;
+ dest->info_flags &= ~GI_CLEAN;
+
+ /* Compute number of iterations */
+
+ if ( level < 1 ) level = 1;
+ if ( level >= 15 ) level = 15;
+ while ( level-- > 0 ) n *= 2;
+ delta = 1.0f / ( float ) n;
+
+ /* Compute finite differences */
+ /* a, b, c are the coefficient of the polynom in t defining the parametric curve */
+ /* The computation is done independently for x and y */
+
+ a = ( float )( -x1 + 3 * x2 - 3 * x3 + x4 );
+ b = ( float )( 3 * x1 - 6 * x2 + 3 * x3 );
+ c = ( float )( -3 * x1 + 3 * x2 );
+
+ d3x = 6 * a * delta * delta * delta;
+ d2x = d3x + 2 * b * delta * delta;
+ dx = a * delta * delta * delta + b * delta * delta + c * delta;
+
+ a = ( float )( -y1 + 3 * y2 - 3 * y3 + y4 );
+ b = ( float )( 3 * y1 - 6 * y2 + 3 * y3 );
+ c = ( float )( -3 * y1 + 3 * y2 );
+
+ d3y = 6 * a * delta * delta * delta;
+ d2y = d3y + 2 * b * delta * delta;
+ dy = a * delta * delta * delta + b * delta * delta + c * delta;
+
+ for ( i = 0; i < n; i++ )
+ {
+ x += dx;
+ dx += d2x;
+ d2x += d3x;
+ y += dy;
+ dy += d2y;
+ d2y += d3y;
+ if (( int16_t )( xp ) != ( int16_t )( x ) || ( int16_t )( yp ) != ( int16_t )( y ) )
+ {
+ draw_line( dest, clip, ( int16_t ) xp, ( int16_t ) yp, ( int16_t ) x - ( int16_t ) xp, ( int16_t ) y - ( int16_t ) yp );
+ }
+ xp = x;
+ yp = y;
+ }
+}
+
+/* --------------------------------------------------------------------------- */