/* * Copyright (c) 2001 Sasha Vasko * Copyright (c) 2001 Eric Kowalski * Copyright (c) 2001 Ethan Fisher * * This module is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #define LOCAL_DEBUG #include #include #include #include #include #include #include #include #include #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include "../afterbase.h" #include "../afterimage.h" #include "common.h" #if defined(SHAPE) && !defined(X_DISPLAY_MISSING) #include #endif /* SHAPE */ /****h* libAfterImage/ascompose * NAME * ascompose is a tool to compose image(s) and display/save it based on * supplied XML input file. * * SYNOPSIS * ascompose -f file|-s string [-o file] [-t type] [-V] * ascompose -i include_file [-i more_include_file ... ] * -f file|-s string [-o file] [-t type] [-V] * ascompose -f file|-s string [-o file] [-t type] [-V] [-n] * ascompose -f file|-s string [-o file] [-t type [-c compression_level]] * [-V] [-r] * ascompose [-h] * ascompose [-v] * * DESCRIPTION * ascompose reads supplied XML data, and manipulates image accordingly. * It could transform images from files of any supported file format, * draw gradients, render antialiased texturized text, perform * superimposition of arbitrary number of images, and save images into * files of any of supported output file formats. * * At any point, the result of any operation could be assigned a name, * and later on referenced under this name. * * At any point during the script processing, result of any operation * could be saved into a file of any supported file types. * * Internal image format is 32bit ARGB with 8bit per channel. * * Last image referenced, will be displayed in X window, unless -n option * is specified. If -r option is specified, then this image will be * displayed in root window of X display, effectively setting a background * for a desktop. If -o option is specified, this image will also be * saved into the file or requested type. * * ascompose can be compiled to not reference X Window System, thus * allowing it to be used on web servers and any other place. It does not * even require X libraries in that case. * * Supported file types for input are : * XPM - via internal code, or libXpm library. * JPEG - via libJpeg library. * PNG - via libPNG library. * XCF - via internal code. For now XCF support is not complete as it * does not merge layers. * PPM/PNM - via internal code. * BMP, ICO, CUR - via internal code. * GIF - via libungif library. * TIFF - via libtiff library (including alpha channel support). * see libAfterImage/ASImageFileTypes for more. * * Supported file types for output : * XPM - via internal code, or libXpm library. * JPEG - via libJpeg library. * PNG - via libPNG library. * GIF - via libungif library. * TIFF - via libtiff library (including alpha channel support). * * OPTIONS * -h --help display help and exit. * -f --file file an XML file to use as input. * -s --string string an XML string to use as input. * -n --no-display don't display the last referenced image. * -r --root-window draw last referenced image image on root window. * -o --output file output last referenced image in to a file. * You should use -t to specify what file type to * use. Filenames are meaningless when it comes to * determining what file type to use. * -t --type type type of file to output to. * -c --compress level compression level. * -v --version display version and exit. * -V --verbose increase verbosity. To increase verbosity level * use several of these, like: ascompose -V -V -V. * -D --debug maximum verbosity - show everything and * debug messages. * -i --include file include file as input prior to processing main * file. * PORTABILITY * ascompose could be used both with and without X window system. It has * been tested on most UNIX flavors on both 32 and 64 bit architecture. * It has also been tested under CYGWIN environment on Windows 95/NT/2000 * USES * libAfterImage all the image manipulation routines. * libAfterBase Optionally. Misc data handling such as hash * tables and console io. Must be used when compiled * without X Window support. * libJPEG JPEG image format support. * libPNG PNG image format support. * libungif GIF image format support. * libTIFF TIFF image format support. * AUTHOR * Ethan Fisher * Sasha Vasko * Eric Kowalski *******/ ASVisual *asv; int verbose = 0; void version(void) { printf("ascompose version 1.2\n"); } void usage(void) { fprintf( stdout, "Usage:\n" "ascompose [options] [-f file|-|-s string] [-o file]" "Available options :\n" " -h --help display this help and exit\n" " -v --version display version and exit\n" " Input options : \n" " -f --file file an XML file to use as input\n" " use '-' for filename to read input from STDIN\n" " -s --string string an XML string to use as input\n" " -i --include file process file prior to processing other input\n" " Output options : \n" #ifndef X_DISPLAY_MISSING " -g --geometry WxX+X+Y set window geometry \n" " -T --title title set window's title\n" " --override override window Manager's controls \n" " (use for splash windows to avoid window frame)\n" " --center center window on screen\n" " --topmost raise window to the top\n" " --no-shape do not shape window\n" " -n --no-display don't display the final image\n" " -r --root-window draw result image on root window\n" #endif /* X_DISPLAY_MISSING */ " -o --output file output to file\n" " -t --type type type of file to output to\n" " -c --compress level compression level\n" " Feedback options : \n" " -V --verbose increase verbosity\n" " -q --quiet output as little information as possible\n" " -D --debug show everything and debug messages\n" " Interactive options : \n" " -I --interactivee run ascompose in interactive mode - tags are processed,\n" " as soon as they are closed.\n" " --timeout value time to wait inbetween displaying images\n" " --endless endlessly loop through file or string\n" " Note that when -I option is used in conjunction with input from\n" " string or a file - ascompose will endlesly loop through the contents\n" " untill it is killed - usefull for slideshow type of activity.\n" " When input comes from STDIN, then ascompose will loop untill Ctrl+D\n" " is received (EOF).\n" "\n" " -C --clipboard run ascompose waiting for data being copied into clipboard,\n" " and displaying/processing it, if it is xml.\n" ); } /****** libAfterImage/ascompose/sample * EXAMPLE * Here is the default script that gets executed by ascompose, if no * parameters are given : * SOURCE */ #if 1 static char* default_doc_str = "\ \ \ \ \ \ \ \ \ \ \ "; #else static char* default_doc_str = "\ \ \ \ \ "; #endif /*******/ char *load_stdin(); typedef struct ASComposeWinProps { Bool center ; int geom_x, geom_y ; unsigned int geom_width, geom_height ; unsigned long geom_flags ; Bool override_redirect ; int timeout ; Bool on_top ; const char *title ; Bool no_shape ; Bool mapped ; int last_x, last_y ; unsigned int last_width, last_height ; int move_resize_count ; Pixmap last_root_pmap ; ASImage *last_root_im ; }ASComposeWinProps; Window showimage(ASImage* im, Bool looping, Window main_window, ASComposeWinProps *props); Window make_main_window(Bool on_root, ASComposeWinProps *props); int screen = 0, depth = 0; int main(int argc, char** argv) { ASImage* im = NULL; char* doc_str = default_doc_str; char* doc_file = NULL; char* doc_save = NULL; char* doc_save_type = NULL; char *doc_compress = NULL ; int i; int display = 1, onroot = 0; Bool quiet = False ; enum { COMPOSE_Once = 0, COMPOSE_Interactive, COMPOSE_XClipboard }compose_type = COMPOSE_Once ; Bool endless_loop = False ; Window main_window = None ; ASComposeWinProps main_window_props ; memset(&main_window_props, 0x00, sizeof( main_window_props)); /* see ASView.1 : */ set_application_name(argv[0]); /* scrap asvisual so we can work on include files ( not displaying anything ) */ asv = create_asvisual(NULL, 0, 32, NULL); /* Parse command line. */ for (i = 1 ; i < argc ; i++) { if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) { version(); usage(); exit(0); } else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) { version(); exit(0); } else if (!strcmp(argv[i], "--quiet") || !strcmp(argv[i], "-q")) { #if (HAVE_AFTERBASE_FLAG==1) set_output_threshold(0); #endif verbose = 0; quiet = True ; } else if (!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-V")) { #if (HAVE_AFTERBASE_FLAG==1) set_output_threshold(OUTPUT_VERBOSE_THRESHOLD); #endif verbose++; } else if (!strcmp(argv[i], "--debug") || !strcmp(argv[i], "-D")) { #if (HAVE_AFTERBASE_FLAG==1) set_output_threshold(OUTPUT_LEVEL_DEBUG); #endif verbose+=2; } else if ((!strcmp(argv[i], "--file") || !strcmp(argv[i], "-f")) && i < argc + 1) { doc_file = argv[++i]; } else if ((!strcmp(argv[i], "--include") || !strcmp(argv[i], "-i")) && i < argc + 1) { char *incl_str = load_file(argv[++i]); if (!incl_str) { fprintf(stderr, "Unable to load file [%s]: %s.\n", argv[i], strerror(errno)); }else { ASImage *im = compose_asimage_xml(asv, NULL, NULL, incl_str, ASFLAGS_EVERYTHING, verbose, None, NULL); free( incl_str ); if( im ) destroy_asimage(&im); } } else if ((!strcmp(argv[i], "--string") || !strcmp(argv[i], "-s")) && i < argc + 1) { doc_str = argv[++i]; } else if ((!strcmp(argv[i], "--output") || !strcmp(argv[i], "-o")) && i < argc + 1) { doc_save = argv[++i]; } else if ((!strcmp(argv[i], "--type") || !strcmp(argv[i], "-t")) && i < argc + 1) { doc_save_type = argv[++i]; } else if ((!strcmp(argv[i], "--compress") || !strcmp(argv[i], "-c")) && i < argc + 1) { doc_compress = argv[++i]; } else if (!strcmp(argv[i], "--interactive") || !strcmp(argv[i], "-I")) { compose_type = COMPOSE_Interactive ; } else if (strcmp(argv[i], "--timeout") == 0 && i < argc + 1) { main_window_props.timeout = strtod( argv[++i ], NULL ); } else if (!strcmp(argv[i], "--endless")) { endless_loop = True ; } #ifndef X_DISPLAY_MISSING else if ((!strcmp(argv[i], "--geometry") || !strcmp(argv[i], "-g")) && i < argc + 1) { main_window_props.geom_flags = XParseGeometry ( argv[++i], &main_window_props.geom_x, &main_window_props.geom_y, &main_window_props.geom_width, &main_window_props.geom_height); } else if (strcmp(argv[i], "--override") == 0 ) { main_window_props.override_redirect = True; } else if ((!strcmp(argv[i], "--title") || !strcmp(argv[i], "-T")) && i < argc + 1) { main_window_props.title = argv[++i]; } else if (strcmp(argv[i], "--center") == 0 ) { main_window_props.center = True; } else if (strcmp(argv[i], "--topmost") == 0 ) { main_window_props.on_top = True; } else if (strcmp(argv[i], "--no-shape") == 0 ) { main_window_props.no_shape = True; } else if (!strcmp(argv[i], "--clipboard") || !strcmp(argv[i], "-C")) { compose_type = COMPOSE_XClipboard; } else if (!strcmp(argv[i], "--no-display") || !strcmp(argv[i], "-n")) { display = 0; } else if ((!strcmp(argv[i], "--root-window") || !strcmp(argv[i], "-r")) && i < argc + 1) { onroot = 1; } #endif /* X_DISPLAY_MISSING */ } destroy_asvisual( asv, False ); asv = NULL ; dpy = NULL ; #ifndef X_DISPLAY_MISSING if( display ) { LOCAL_DEBUG_OUT( "Opening display ...%s", ""); dpy = XOpenDisplay(NULL); LOCAL_DEBUG_OUT( "Done: %p", dpy); if( dpy ) { _XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False); screen = DefaultScreen(dpy); depth = DefaultDepth(dpy, screen); } } #endif if( dpy == NULL && doc_file == NULL && doc_str == default_doc_str ) doc_file = strdup("-"); /* Automagically determine the output type, if none was given. */ if (doc_save && !doc_save_type) { doc_save_type = strrchr(doc_save, '.'); if (doc_save_type) doc_save_type++; } LOCAL_DEBUG_OUT( "Creating visual ...%s", ""); asv = create_asvisual(dpy, screen, depth, NULL); LOCAL_DEBUG_OUT( "Done: %p", asv); /* Load the document from file, if one was given. */ if( compose_type == COMPOSE_Once ) { if (doc_file) { if( strcmp( doc_file, "-") == 0 ) doc_str = load_stdin(); else doc_str = load_file(doc_file); if (!doc_str) { show_error("Unable to load file [%s]: %s.\n", doc_file, strerror(errno)); exit(1); } } im = compose_asimage_xml(asv, NULL, NULL, doc_str, ASFLAGS_EVERYTHING, verbose, None, NULL); /* Save the result image if desired. */ if (doc_save && doc_save_type) { if(!save_asimage_to_file(doc_save, im, doc_save_type, doc_compress, NULL, 0, 1)) show_error("Save failed."); else show_progress("Save successful."); } /* Display the image if desired. */ if (display && dpy) { showimage(im, False, make_main_window(onroot, &main_window_props), &main_window_props); LOCAL_DEBUG_OUT( "Image %p displayed", im ); } /* Done with the image, finally. */ if( im ) { safe_asimage_destroy( im ); im = NULL ; } }else if( compose_type == COMPOSE_Interactive ) { FILE *fp = stdin ; int doc_str_len = 0; if (doc_file && strcmp( doc_file, "-") != 0 ) fp = fopen( doc_file, "rt" ); if( doc_str ) doc_str_len = strlen( doc_str ); if( fp != NULL || doc_str_len > 0 ) { ASImageManager *my_imman = create_generic_imageman(NULL); ASFontManager *my_fontman = create_generic_fontman(asv->dpy, NULL); int char_count = 0 ; ASXmlBuffer xb ; memset( &xb, 0x00, sizeof(xb)); if (display && dpy) main_window = make_main_window( onroot, &main_window_props ); do { reset_xml_buffer( &xb ); if( fp ) { int c ; show_progress("Please enter your xml text :" ); while( (c = fgetc(fp)) != EOF ) { char cc = c; while( xb.state >= 0 && spool_xml_tag( &xb, &cc, 1 ) <= 0) { LOCAL_DEBUG_OUT("[%c] : state=%d, tags_count=%d, level = %d, tag_type = %d", cc, xb.state, xb.tags_count, xb.level, xb.tag_type ); } LOCAL_DEBUG_OUT("[%c] : state=%d, tags_count=%d, level = %d, tag_type = %d", cc, xb.state, xb.tags_count, xb.level, xb.tag_type ); ++char_count ; if( ( xb.state == ASXML_Start && xb.tags_count > 0 && xb.level == 0) || xb.state < 0 ) break; } if( c == EOF && fp != stdin ) { if( endless_loop ) { fseek( fp, 0L, SEEK_SET ); char_count = 0 ; }else if( xb.tags_count == 0 ) break; if( xb.state == ASXML_Start && xb.tags_count == 0 ) continue; } }else { if( char_count >= doc_str_len ) { if( !endless_loop ) break; char_count = 0 ; } while( char_count < doc_str_len ) { char_count += spool_xml_tag( &xb, &doc_str[char_count], doc_str_len - char_count ); if( ( xb.state == ASXML_Start && xb.tags_count > 0 && xb.level == 0) || xb.state < 0 ) break; } } if( xb.state == ASXML_Start && xb.tags_count > 0 && xb.level == 0 ) { if( !display || dpy == NULL || !quiet ) printf("\n", xb.tags_count ); add_xml_buffer_chars( &xb, "", 1 ); LOCAL_DEBUG_OUT("buffer: [%s]", xb.buffer ); im = compose_asimage_xml(asv, my_imman, my_fontman, xb.buffer, ASFLAGS_EVERYTHING, verbose, None, NULL); if( im ) { /* Save the result image if desired. */ if (doc_save && doc_save_type) { if(!save_asimage_to_file(doc_save, im, doc_save_type, doc_compress, NULL, 0, 1)) show_error("Save failed."); else show_progress("Save successful."); } /* Display the image if desired. */ if (display && dpy) main_window = showimage(im, True, main_window, &main_window_props); safe_asimage_destroy(im); im = NULL ; } }else if( fp == stdin && xb.state == ASXML_Start && xb.tags_count == 0 && xb.level == 0 ) { if( !display || dpy == NULL || !quiet ) printf("\n", xb.tags_count ); break; }else { if( !display || dpy == NULL || !quiet ) { printf("