#include "config.h" #include #include /****h* libAfterImage/tutorials/ASGrad * NAME * ASGrad * SYNOPSIS * libAfterImage application for drawing multipoint linear gradients. * DESCRIPTION * New steps described in this tutorial are : * ASGrad.1. Building gradient specs. * ASGrad.2. Actual rendering gradient. * SEE ALSO * Tutorial 1: ASView - explanation of basic steps needed to use * libAfterImage and some other simple things. * Tutorial 2: ASScale - image scaling basics. * Tutorial 3: ASTile - image tiling and tinting. * Tutorial 4: ASMerge - scaling and blending of arbitrary number of * images. * SOURCE */ #include "../afterbase.h" #include "../afterimage.h" #include "common.h" ARGB32 default_colors[] = { 0xFF000000, 0xFF700070, /* violet */ 0xFF0000FF, /* blue */ 0xFF00FFFF, /* cyan */ 0xFF00FF00, 0XFFFFFF00, 0XFF700000, 0XFFFF0000, 0xFF8080A0, 0xFFE0E0FF, 0xFFa0a0FF, }; double default_offsets[] = { 0, 0.1, 0.15, 0.20, 0.35, 0.45, 0.55, 0.50, 0.65, 0.8, 1.0} ; void usage() { printf( " Usage: asgrad -h | " " [ ...]\n"); printf( " Where: geometry - size of the resulting image and window;\n"); printf( " gradient_type - One of the fiollowing values :\n"); printf( " 0 - linear left-to-right gradient,\n"); printf( " 1 - diagonal lefttop-to-rightbottom,\n"); printf( " 2 - linear top-to-bottom gradient,\n"); printf( " 3 - diagonal righttop-to-leftbottom;\n"); printf( " offset - floating point value from 0.0 to 1.0\n"); } int main(int argc, char* argv[]) { ASVisual *asv ; int screen = 0, depth = 0; int dummy, geom_flags = 0; unsigned int to_width, to_height ; ASGradient grad ; ASGradient default_grad = { 1, 11, &(default_colors[0]), &(default_offsets[0])} ; ASImage *grad_im = NULL; /* see ASView.1 : */ set_application_name( argv[0] ); #if (HAVE_AFTERBASE_FLAG==1) set_output_threshold(OUTPUT_LEVEL_DEBUG); #endif if( argc > 1 ) { if( strcmp( argv[1], "-h") == 0 ) { usage(); return 0; } /* see ASScale.1 : */ geom_flags = XParseGeometry( argv[1], &dummy, &dummy, &to_width, &to_height ); }else usage(); memset( &grad, 0x00, sizeof(ASGradient)); #ifndef X_DISPLAY_MISSING dpy = XOpenDisplay(NULL); _XA_WM_DELETE_WINDOW = XInternAtom( dpy, "WM_DELETE_WINDOW", False); screen = DefaultScreen(dpy); depth = DefaultDepth( dpy, screen ); #endif if( argc >= 5 ) { int i = 2; /* see ASGrad.1 : */ grad.type = atoi( argv[2] ); grad.npoints = 0 ; grad.color = safemalloc( ((argc-2)/2)*sizeof(ARGB32)); grad.offset = safemalloc( ((argc-2)/2)*sizeof(double)); while( ++i < argc ) { if( grad.npoints > 0 ) { if( i == argc-1 ) grad.offset[grad.npoints] = 1.0; else grad.offset[grad.npoints] = atof( argv[i] ); ++i ; } /* see ASTile.1 : */ if( parse_argb_color( argv[i], &(grad.color[grad.npoints])) != argv[i] ) if( grad.offset[grad.npoints] >= 0. && grad.offset[grad.npoints]<= 1.0 ) grad.npoints++ ; } }else { grad = default_grad ; if( argc >= 3 ) grad.type = atoi( argv[2] ); } if( grad.npoints <= 0 ) { show_error( " not enough gradient points specified."); return 1; } /* Making sure tiling geometry is sane : */ #ifndef X_DISPLAY_MISSING if( !get_flags(geom_flags, WidthValue ) ) to_width = DisplayWidth(dpy, screen)*2/3 ; if( !get_flags(geom_flags, HeightValue ) ) to_height = DisplayHeight(dpy, screen)*2/3 ; #else if( !get_flags(geom_flags, WidthValue ) ) to_width = 500 ; if( !get_flags(geom_flags, HeightValue ) ) to_height = 500 ; #endif printf( "%s: rendering gradient of type %d to %dx%d\n", get_application_name(), grad.type&GRADIENT_TYPE_MASK, to_width, to_height ); /* see ASView.3 : */ asv = create_asvisual( dpy, screen, depth, NULL ); /* see ASGrad.2 : */ grad_im = make_gradient( asv, &grad, to_width, to_height, SCL_DO_ALL, #ifndef X_DISPLAY_MISSING ASA_XImage, #else ASA_ASImage, #endif 0, ASIMAGE_QUALITY_DEFAULT ); if( grad_im ) { #ifndef X_DISPLAY_MISSING /* see ASView.4 : */ Window w = create_top_level_window( asv, DefaultRootWindow(dpy), 32, 32, to_width, to_height, 1, 0, NULL, "ASGradient", NULL ); if( w != None ) { Pixmap p ; XMapRaised (dpy, w); /* see ASView.5 : */ p = asimage2pixmap( asv, DefaultRootWindow(dpy), grad_im, NULL, True ); destroy_asimage( &grad_im ); /* see common.c: set_window_background_and_free() : */ p = set_window_background_and_free( w, p ); /* see common.c: wait_closedown() : */ wait_closedown(w); } if( dpy ) XCloseDisplay (dpy); #else ASImage2file( grad_im, NULL, "asgrad.jpg", ASIT_Jpeg, NULL ); destroy_asimage( &grad_im ); #endif } return 0 ; } /**************/ /****f* libAfterImage/tutorials/ASGrad.1 [5.1] * SYNOPSIS * Step 1. Building gradient specs. * DESCRIPTION * Multipoint gradient is defined as set of color values with offsets * of each point from the beginning of the gradient on 1.0 scale. * Offsets of the first and last point in gradient should always be * 0. and 1.0 respectively, and other points should go in between. * For example 2 point gradient will have always offsets 0. and 1.0, * 3 points gradient will have 0. for first color, 1.0 for last color * and anything in between for middle color. * If offset is incorrect - point will be skipped at the time of * rendering. * * There are 4 types of gradients supported : horizontal, top-left to * bottom-right diagonal, vertical and top-right to bottom-left diagonal. * Any cilindrical gradient could be drawn as a 3 point gradient with * border colors being the same. * * Each gradient point has ARGB color, which means that it is possible * to draw gradients in alpha channel as well as RGB. That makes for * semitransparent gradients, fading gradients, etc. * EXAMPLE * grad.type = atoi( argv[2] ); * grad.npoints = 0 ; * grad.color = safemalloc( ((argc-2)/2)*sizeof(ARGB32)); * grad.offset = safemalloc( ((argc-2)/2)*sizeof(double)); * while( ++i < argc ) * { * if( grad.npoints > 0 ) * { * if( i == argc-1 ) * grad.offset[grad.npoints] = 1.0; * else * grad.offset[grad.npoints] = atof( argv[i] ); * ++i ; * } * if( parse_argb_color( argv[i], &(grad.color[grad.npoints])) * != argv[i] ) * if(grad.offset[grad.npoints] >= 0. && * grad.offset[grad.npoints]<= 1.0 ) * grad.npoints++ ; * } * SEE ALSO * ARGB32, parse_argb_color(), ASGradient ********/ /****f* libAfterImage/tutorials/ASGrad.2 [5.2] * SYNOPSIS * Step 2. Actually rendering gradient. * DESCRIPTION * All that is needed to draw gradient is to call make_gradient(), * passing pointer to ASGradient structure, that describes gradient. * Naturally size of the gradient is needed too. Another parameter is * filter - that is a bit mask that allows to draw gradient using only a * subset of the channels, represented by set bits. SCL_DO_ALL means * that all 4 channels must be rendered. * make_gradient() creates ASImage of requested size and fills it with * gradient. Special techinque based on error diffusion is utilized to * avoid sharp steps between grades of colors when limited range of * colors is used for gradient. * EXAMPLE * grad_im = make_gradient( asv, &grad, to_width, to_height, * SCL_DO_ALL, * ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT ); * NOTES * make_gradient(), ASScanline, ASImage. ********/