aboutsummaryrefslogtreecommitdiff
path: root/modules/libgrbase/g_blendop.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/libgrbase/g_blendop.c')
-rw-r--r--modules/libgrbase/g_blendop.c448
1 files changed, 448 insertions, 0 deletions
diff --git a/modules/libgrbase/g_blendop.c b/modules/libgrbase/g_blendop.c
new file mode 100644
index 0000000..d05784b
--- /dev/null
+++ b/modules/libgrbase/g_blendop.c
@@ -0,0 +1,448 @@
+/*
+ * 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 "libgrbase.h"
+
+/* --------------------------------------------------------------------------- */
+
+/* Fast macros for color component extraction from a 16 bits value */
+
+#define GETR(color) (((color & sys_pixel_format->Rmask) >> sys_pixel_format->Rshift) << sys_pixel_format->Rloss)
+#define GETG(color) (((color & sys_pixel_format->Gmask) >> sys_pixel_format->Gshift) << sys_pixel_format->Gloss)
+#define GETB(color) (((color & sys_pixel_format->Bmask) >> sys_pixel_format->Bshift) << sys_pixel_format->Bloss)
+
+/* Fast macros for color composition */
+
+#define MAKERGB_SATURATE(r,g,b) \
+ ( \
+ ((int)(r) > 255 ? sys_pixel_format->Rmask : (((int)(r) >> sys_pixel_format->Rloss) << sys_pixel_format->Rshift)) | \
+ ((int)(g) > 255 ? sys_pixel_format->Gmask : (((int)(g) >> sys_pixel_format->Gloss) << sys_pixel_format->Gshift)) | \
+ ((int)(b) > 255 ? sys_pixel_format->Bmask : (((int)(b) >> sys_pixel_format->Bloss) << sys_pixel_format->Bshift)) \
+ )
+
+#define MAKERGB(r,g,b) \
+ ( \
+ (((int)(r) >> sys_pixel_format->Rloss) << sys_pixel_format->Rshift) | \
+ (((int)(g) >> sys_pixel_format->Gloss) << sys_pixel_format->Gshift) | \
+ (((int)(b) >> sys_pixel_format->Bloss) << sys_pixel_format->Bshift) \
+ )
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_init
+ *
+ * Initialize a blend table as a copy operation
+ *
+ * Src_param = Src_color
+ * Dst_param = 0
+ *
+ * PARAMS :
+ * blend Pointer to the blend table
+ * amount Color component factor (1.0f leaves source unchanged)
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void blend_init( int16_t * blend )
+{
+ int i;
+ int16_t * blend2;
+
+ if ( !blend ) return ;
+
+ blend2 = blend + 65536;
+
+ for ( i = 0; i < 65536; i++ )
+ {
+ *blend++ = i;
+ *blend2++ = 0;
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+/* ************************* */
+/* Blendops public functions */
+/* ************************* */
+/*
+ * FUNCTION : blend_create
+ *
+ * Create a new blendop table and initialize it with blend_init
+ * A blendop table is a group of two tables that return intermediate
+ * colors to a composite (+) operation that does no saturation:
+ *
+ * Src_param = Src_color
+ * Dst_param = Dst_color
+ * Dst_color = Src_param + Dst_param // No clamp!
+ *
+ * The other blend_x funcions change the Src_param and Dst_param formulas.
+ * The Dst_color formula is immutable and embedded in the blitter
+ *
+ * PARAMS :
+ * None
+ *
+ * RETURN VALUE :
+ * Pointer to the new blendop table or NULL if not enough memory
+ */
+
+int16_t * blend_create( void )
+{
+ int16_t * blend = malloc( 65536 * 2 * sizeof( int16_t ) );
+ if ( !blend ) return NULL;
+
+ blend_init( blend );
+
+ return blend;
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_apply
+ *
+ * Apply a blend operation to the pixels of a graphic, as if it was
+ * rendered into a black (color 0) background
+ *
+ * PARAMS :
+ * graph Pointer to the graphic
+ * blend Pointer to the blend table
+ *
+ * RETURN VALUE :
+ * 0 Error
+ * 1 OK
+ */
+
+void blend_apply( GRAPH * graph, int16_t * blend )
+{
+ uint16_t * ptr;
+ uint32_t x, y;
+ uint8_t * ptr8;
+ int16_t * blend2;
+
+ if ( !graph || !blend || graph->format->depth != 16 ) return ;
+
+ blend2 = blend + 65536;
+
+ ptr = ( uint16_t * ) (ptr8 = ( uint8_t * ) graph->data);
+ y = graph->height;
+ while ( y-- )
+ {
+ x = graph->width;
+ while ( x-- )
+ {
+ if ( *ptr ) * ptr = blend[ *ptr ] + blend2[ *ptr ];
+ ptr++;
+ }
+ ptr = ( uint16_t * ) (ptr8 += graph->pitch);
+ }
+
+ graph->modified = 2;
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_assign
+ *
+ * Assign a blend operation to a graphic. The graphic will be
+ * drawn using this blend operation thereafter.
+ *
+ * PARAMS :
+ * graph Pointer to the graphic
+ * blend Pointer to the blend table
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void blend_assign( GRAPH * graph, int16_t * blend )
+{
+ if ( !graph ) return ;
+ graph->blend_table = blend;
+ graph->modified = 1; /* Don't needs analysis */
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_free
+ *
+ * Free the memory used by a blendop table
+ *
+ * PARAMS :
+ * blend Pointer to the blend table
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void blend_free( int16_t * blend )
+{
+ if ( !blend ) return ;
+ free( blend );
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_grayscale
+ *
+ * Initialize a blend table as a grayscale operation (changes the
+ * color value of the source object to grayscale). Three methods
+ * of operation are supported:
+ *
+ * 1. Luminance: result = 0.3R + 0.59G + 0.11B
+ * 2. Desaturate: result = (MAX(R,G,B)+MIN(R,G,B))/2
+ * 3. Maximum: result = MAX(R,G,B)
+ *
+ *
+ * Src_param = Grayscale_operation(previous Src_param)
+ *
+ * PARAMS :
+ * blend Pointer to the blend table
+ * method Method of operation
+ *
+ * RETURN VALUE :
+ * 0 Error
+ * 1 Ok
+ */
+
+void blend_grayscale( int16_t * blend, int method )
+{
+ int i, r, g, b, max, min;
+ int16_t * blend2;
+
+ if ( !blend ) return ;
+
+ switch ( method )
+ {
+ case 1:
+ blend2 = blend + 65536;
+
+ for ( i = 0; i < 65536; i++ )
+ {
+ r = ( int )( GETR( i ) * 0.3 );
+ g = ( int )( GETG( i ) * 0.59 );
+ b = ( int )( GETB( i ) * 0.11 );
+ r = r + g + b;
+ *blend++ = MAKERGB( r, r, r );
+ *blend2++ = 0;
+ }
+ break;
+
+ case 2:
+ blend2 = blend + 65536;
+
+ for ( i = 0; i < 65536; i++ )
+ {
+ r = GETR( i );
+ g = GETG( i );
+ b = GETB( i );
+
+ max = ( r > g ) ? ( r > b ) ? r : g : ( g > b ) ? g : b;
+ min = ( r < g ) ? ( r < b ) ? r : g : ( g < b ) ? g : b;
+
+ r = ( max + min ) / 2;
+ *blend++ = MAKERGB( r, r, r );
+ *blend2++ = 0;
+ }
+ break;
+
+ case 3:
+ blend2 = blend + 65536;
+
+ for ( i = 0; i < 65536; i++ )
+ {
+ r = GETR( i );
+ g = GETG( i );
+ b = GETB( i );
+
+ max = ( r > g ) ? ( r > b ) ? r : g : ( g > b ) ? g : b;
+
+ *blend++ = MAKERGB( max, max, max );
+ *blend2++ = 0;
+ }
+ break;
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_translucency
+ *
+ * Modify a blend table as a translucency combination operation
+ *
+ * Src_param = (previous Src_param) * amount
+ * Dst_param = Dst_color * (1.0 - amount)
+ *
+ * PARAMS :
+ * blend Pointer to the blend table
+ * amount Opacity factor (1.0f = opaque, 0.0f = transparent)
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void blend_translucency( int16_t * blend, float amount )
+{
+ int i, r, g, b;
+ float amount2;
+ int16_t * blend2;
+
+ if ( !blend ) return ;
+
+ blend2 = blend + 65536;
+
+ if ( amount > 1.0f ) amount = 1.0f;
+ if ( amount < 0.0f ) amount = 0.0f;
+
+ amount = 1.0f - amount;
+ amount2 = 1.0f - amount;
+
+ for ( i = 0; i < 65536; i++ )
+ {
+ r = ( int )( GETR( *blend ) * amount );
+ g = ( int )( GETG( *blend ) * amount );
+ b = ( int )( GETB( *blend ) * amount );
+ *blend++ = MAKERGB( r, g, b );
+
+ r = ( int )( GETR( i ) * amount2 );
+ g = ( int )( GETG( i ) * amount2 );
+ b = ( int )( GETB( i ) * amount2 );
+ *blend2++ = MAKERGB( r, g, b );
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_intensity
+ *
+ * Modify a blend table as an intensity operation (changes the
+ * color value of the source object as the factor amount but
+ * does no transparency or other operation with the background)
+ *
+ * Src_param = (previous Src_param) * amount
+ *
+ * PARAMS :
+ * blend Pointer to the blend table
+ * amount Color component factor (1.0f leaves source unchanged)
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void blend_intensity( int16_t * blend, float amount )
+{
+ int i, r, g, b;
+
+ if ( !blend ) return ;
+
+ if ( amount < 0.0f ) amount = 0.0f;
+
+ for ( i = 65536; i--; )
+ {
+ r = ( int )( GETR( *blend ) * amount );
+ g = ( int )( GETG( *blend ) * amount );
+ b = ( int )( GETB( *blend ) * amount );
+ *blend++ = MAKERGB_SATURATE( r, g, b );
+ }
+}
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_swap
+ *
+ * Swaps a blendop table. That is, change the blend operation so
+ * the Dst_color and Src_color are exchanged in the formulas.
+ *
+ * PARAMS :
+ * blend Pointer to the blend table
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void blend_swap( int16_t * blend )
+{
+ int i, j;
+ int16_t * blend2;
+
+ if ( !blend ) return ;
+
+ blend2 = blend + 65536;
+
+ for ( i = 65536; i--; )
+ {
+ j = *blend;
+ *blend++ = *blend2;
+ *blend2++ = j;
+ }
+}
+
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : blend_tint
+ *
+ * Modify a blend table as a tint operation (changes the
+ * color value of the source object as a combination of a given
+ * color and the source color with the factor given)
+ *
+ * Src_param = Const_color * amount
+ * + (previous Src_Param) * (1.0f-amount)
+ *
+ * PARAMS :
+ * blend Pointer to the blend table
+ * amount Color component factor (1.0f = Full Const color)
+ * cr Constant color, red component (0-255)
+ * cg Constant color, green component (0-255)
+ * cb Constant color, blue component (0-255)
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void blend_tint( int16_t * blend, float amount, uint8_t cr, uint8_t cg, uint8_t cb )
+{
+ int i, r, g, b;
+
+ if ( !blend ) return ;
+
+ if ( amount > 1.0f ) amount = 1.0f;
+ if ( amount < 0.0f ) amount = 0.0f;
+
+ for ( i = 65536; i--; )
+ {
+ r = ( int )( amount * cr + ( 1.0f - amount ) * GETR( *blend ) );
+ g = ( int )( amount * cg + ( 1.0f - amount ) * GETG( *blend ) );
+ b = ( int )( amount * cb + ( 1.0f - amount ) * GETB( *blend ) );
+ *blend = MAKERGB_SATURATE( r, g, b );
+ blend++;
+ }
+}
+
+/* --------------------------------------------------------------------------- */