text: #include "config.h"
  
  #include <string.h>
  #include <stdlib.h>
  
  /****h* libAfterImage/tutorials/ASText
   * NAME
   * ASText
   * SYNOPSIS
   * libAfterImage application for rendering texturized text.
   * DESCRIPTION
   * In this tutorial we will attempt to render arbitrary text in window,
   * with optional texturized background and foreground. We shall also
   * surround rendered text with beveled frame, creating an illusion of a
   * button.
   *
   * New steps described in this tutorial are :
   * ASText.1. Opening and closing fonts.
   * ASText.2. Approximating rendered text size.
   * ASText.3. Rendering texturized text.
   * ASText.4. Merging foreground and background with bevel.
   * 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.
   * Tutorial 5: ASGrad  - drawing multipoint linear gradients.
   * Tutorial 6: ASFlip  - image rotation.
   * SOURCE
   */
  
  #include "../afterbase.h"
  #include "../afterimage.h"
  #include "common.h"
  
  /* Usage:  astext [-f font] [-s size] [-t text] [-S 3D_style]
                    [-c text_color] [-b background_color]
                    [-T foreground_texture] [-B background_image]
  				  [-r foreground_resize_type] [-R background_resize_type]
   */
  
  #define BEVEL_HI_WIDTH 20
  #define BEVEL_LO_WIDTH 30
  #define BEVEL_ADDON    (BEVEL_HI_WIDTH+BEVEL_LO_WIDTH)
  
  void usage()
  {
  	printf( "  Usage:   astext [-h] [-f font] [-s size] [-t text] "
  			"[-S 3D_style] \n");
  	printf( "                  [-c text_color] [-b background_color]\n");
  	printf( "                  [-T foreground_texture] "
  			"[-B background_image]\n");
  	printf( "      			   [-r foreground_resize_type] "
  			"[-R background_resize_type]\n");
  	printf( "      			   [-m ]\n");
  	printf( "  Where: font - TrueType font's filename or X font spec or "
  			"alias;\n");
  	printf( "         size - size in points for TrueType fonts;\n");
  	printf( "         text - text to be drawn;\n");
  	printf( "         3D_style - 3D style of text. "
  			"One of the following:\n");
  	printf( "             0 - plain 2D tetx, 1 - embossed, 2 - sunken, "
  			"3 - shade above,\n");
  	printf( "             4 - shade below, 5 - embossed thick, "
  			"6 - sunken thick.\n");
  	printf( "             7 - ouline above, 8 - ouline below, "
  			"9 - full ouline.\n");
  	printf( "         resize_type - tells how texture/image should be "
  			"transformed to fit\n");
  	printf( "         the text size. Could be: scale or tile." 
  			"Default is tile\n");
  	printf( "         -m make font monospaced. \n");
  
  
  }
  
  int main(int argc, char* argv[])
  {
  	Display *dpy = NULL;
  	ASVisual *asv = NULL ;
  	int screen = 0, depth = 0;
  	char *font_name = "test.ttf";
  	int size = 32 ;
  #if 0
  	char *text = "　　还没有";  /* chinese */ 
  #else
   	char *text = "Smart Brown Dog jumps\nOver The Lazy Fox,\n"
  				 "and falls into the ditch.";
  #endif
  	ARGB32 text_color = ARGB32_White, back_color = ARGB32_Black;
  	char *text_color_name = "#FFFFFFFF", *back_color_name = "#FF000000";
  	char *fore_image_file = "fore.xpm" ;
  	char *back_image_file = "back.xpm" ;
  	Bool scale_fore_image = False, scale_back_image = False ;
  	ASImage *fore_im = NULL, *back_im = NULL;
  	ASImage *text_im = NULL ;
  	struct ASFontManager *fontman = NULL;
  	struct ASFont  *font = NULL;
  	unsigned int width, height ;
  	int i ;
  	int text_margin = size/2 ;
  	Bool monospaced = False ;
  	char * font_path = NULL;
  	ASTextAttributes attr = {ASTA_VERSION_1, ASTA_UseTabStops, 
  							 AST_ShadeBelow, ASCT_UTF8, 8, 0, 
  							 NULL, 0, ARGB32_White };
  	
  	/* see ASView.1 : */
  	set_application_name( argv[0] );
  #if (HAVE_AFTERBASE_FLAG==1)
  	set_output_threshold(OUTPUT_LEVEL_DEBUG);
  #endif
  
  	if( argc == 1 )
  		usage();
  	else for( i = 1 ; i < argc ; i++ )
  	{
  		if( strncmp( argv[i], "-h", 2 ) == 0 )
  		{
  			usage();
  			return 0;
  		}
  		if( strncmp( argv[i], "-m", 2 ) == 0 )
  		{
  	   		monospaced = True ;
  		}else if( i+1 < argc )
  		{
  			if( strncmp( argv[i], "-f", 2 ) == 0 )
  				font_name = argv[i+1] ;
  			else if( strncmp( argv[i], "-s", 2 ) == 0 )
  			{
  				size = atoi(argv[i+1]);
  				text_margin = size/2 ;
  			}else if( strncmp( argv[i], "-t", 2 ) == 0 )
  				text = argv[i+1] ;
  			else if( strncmp( argv[i], "-S", 2 ) == 0 )
  			{
  				attr.type = atoi(argv[i+1]);
  				if( attr.type >= AST_3DTypes )
  				{
  					show_error( "3D type is wrong. "
  								"Using 2D Plain instead.");
  					attr.type = AST_Plain ;
  				}
  
  			}else if( strncmp( argv[i], "-c", 2 ) == 0 )
  				text_color_name = argv[i+1] ;
  			else if( strncmp( argv[i], "-b", 2 ) == 0 )
  				back_color_name = argv[i+1] ;
  			else if( strncmp( argv[i], "-T", 2 ) == 0 )
  				fore_image_file = argv[i+1] ;
  			else if( strncmp( argv[i], "-B", 2 ) == 0 )
  				back_image_file = argv[i+1] ;
  			else if( strncmp( argv[i], "-r", 2 ) == 0 )
  				scale_fore_image = (strcmp( argv[i+1], "scale") == 0);
  			else if( strncmp( argv[i], "-R", 2 ) == 0 )
  				scale_back_image = (strcmp( argv[i+1], "scale") == 0);
  		}
  	}
  
  
  #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
  
  	/* see ASText.1 : */
  	if( getenv("FONT_PATH") != NULL ) 
  	{
  		font_path = safemalloc( strlen(getenv("FONT_PATH"))+1+2+1);
  		sprintf( font_path, "%s:./", getenv("FONT_PATH") );
  		
  	}	 
  	if( (fontman = create_font_manager( dpy, font_path, NULL )) != NULL )
  		font = get_asfont( fontman, font_name, 0, size, 
  						   ASF_GuessWho|(monospaced?ASF_Monospaced:0) );
  
  	if( font == NULL )
  	{
  		show_error( "unable to load requested font \"%s\". "
  					"Falling back to \"fixed\".", font_name );
  		font = get_asfont( fontman, "fixed", 0, size, ASF_GuessWho );
  		if( font == NULL )
  		{
  			show_error("font \"fixed\" is not available either. Aborting.");
  			return 1;
  		}
  	}
  
  	/*for( i = 0 ; i < 128 ; ++i ) 
  		print_asglyph( stderr, font, i); */
  
  	parse_argb_color( text_color_name, &text_color );
  	parse_argb_color( back_color_name, &back_color );
  
  	attr.fore_color = text_color ;
  	if( attr.type >= AST_OutlineAbove ) 
  		fore_image_file = NULL ;
  
  	/* see ASView.3 : */
  	asv = create_asvisual( dpy, screen, depth, NULL );
  
  	/* see ASText.2 : */
  	/*set_asfont_glyph_spacing( font, 10, 40 );*/
      /*Simple way:get_text_size( text, font, attr.type, &width, &height ); */
  	/*Fancy way : */
  	get_fancy_text_size( text, font, &attr, &width, &height, 0, NULL );
  /* show_progress( "extimated text size = %dx%d", width, height ); */
  	
  	if( fore_image_file )
  	{
  		ASImage *tmp = file2ASImage( fore_image_file, 0xFFFFFFFF,
  		               		         SCREEN_GAMMA, 0, getenv("IMAGE_PATH"), NULL );
  		if( tmp )
  		{
  			if( tmp->width != width || tmp->height != height )
  			{   /* see ASScale.2 : */
  				if( scale_fore_image )
  					fore_im = scale_asimage( asv, tmp, width, height,
    					                         ASA_ASImage, 0, 
  											 ASIMAGE_QUALITY_DEFAULT );
  				else
  					fore_im = tile_asimage( asv, tmp, 0, 0, 
  											width, height, 0,
    					                        ASA_ASImage, 0, 
  											ASIMAGE_QUALITY_DEFAULT );
  				destroy_asimage( &tmp );
  			}else
  				fore_im = tmp ;
  		}else
  			fore_im = NULL ;
  	}
  	width  += text_margin*2 + BEVEL_ADDON;
  	height += text_margin*2 + BEVEL_ADDON;
  	if( back_image_file )
  	{ /* see ASView.2 : */
  		ASImage *tmp = file2ASImage( back_image_file, 0xFFFFFFFF,
  			                        SCREEN_GAMMA, 0, getenv("IMAGE_PATH"), NULL );
  		if( tmp )
  		{
  			if( scale_back_image && 
  				(tmp->width != width || tmp->height != height) )
  			{   /* see ASScale.2 : */
  				back_im = scale_asimage( asv, tmp, width, height,
  				                         ASA_ASImage, 0, 
  										 ASIMAGE_QUALITY_DEFAULT );
  				destroy_asimage( &tmp );
  			}else
  				back_im = tmp ;
  		}else
  			back_im = NULL ;
  	}
  
  	/* see ASText.3 : */
      /* simple way : text_im = draw_text( text, font, attr.type, 0 ); */
  	text_im = draw_fancy_text( text, font, &attr, 0, 0 );
  	if( fore_im )
  	{
  		move_asimage_channel( fore_im, IC_ALPHA, text_im, IC_ALPHA );
  		destroy_asimage( &text_im );
  	}else
  		fore_im = text_im ;
  
  	/* see ASText.1 : */
  	release_font( font );
  	destroy_font_manager( fontman, False );
  
  	if( fore_im )
  	{
  		ASImage *rendered_im ;
  		ASImageLayer layers[2] ;
  		ASImageBevel bevel = {0/*BEVEL_SOLID_INLINE*/, 0xFFDDDDDD, 
  							  0xFF555555, 0xFFFFFFFF, 
  							  0xFF777777, 0xFF222222,
  		                      BEVEL_HI_WIDTH, BEVEL_HI_WIDTH,
  							  BEVEL_LO_WIDTH, BEVEL_LO_WIDTH,
  							  BEVEL_HI_WIDTH, BEVEL_HI_WIDTH,
  							  BEVEL_LO_WIDTH, BEVEL_LO_WIDTH } ;
  
  		/* see ASText.4 : */
  		init_image_layers( &(layers[0]), 2 );
  		if( back_im )
  			back_im->back_color = back_color ;
  		if( fore_im ) 
  			fore_im->back_color = text_color ;
  		layers[0].im = back_im ;
  		layers[0].dst_x = 0 ;
  		layers[0].dst_y = 0 ;
  		layers[0].clip_width = width ;
  		layers[0].clip_height = height ;
  		layers[0].bevel = &bevel ;
  		layers[1].im = fore_im ;
  		layers[1].dst_x = text_margin+BEVEL_HI_WIDTH*2 ;
  		layers[1].dst_y = text_margin+
  							MIN( (int)text_margin,
  								((int)font->max_height-
  								 (int)font->max_ascend))/2+
  								 BEVEL_HI_WIDTH*2;
  		if( fore_im ) 
  		{	
  			layers[1].clip_width = fore_im->width ;
  			layers[1].clip_height = fore_im->height ;
  		}
  		rendered_im = merge_layers( asv, &(layers[0]), 2,
  									width+BEVEL_ADDON, height+BEVEL_ADDON,
  #ifndef X_DISPLAY_MISSING
  									ASA_XImage,
  #else
  									ASA_ASImage,
  #endif
  									0, ASIMAGE_QUALITY_DEFAULT);
  		destroy_asimage( &fore_im );
  		destroy_asimage( &back_im );
  
  		if( rendered_im )
  		{
  #ifndef X_DISPLAY_MISSING
  			Window w;
  			/* see ASView.4 : */
  			w = create_top_level_window( asv, DefaultRootWindow(dpy), 
  										 32, 32,
  			      		                 width+BEVEL_ADDON, 
  										 height+BEVEL_ADDON,
  										 1, 0, NULL,
  										 "ASText", text );
  			if( w != None )
  			{
  				Pixmap p ;
  
  			  	XMapRaised   (dpy, w);
  
  				/* see ASView.5 : */
  				p = asimage2pixmap( asv, DefaultRootWindow(dpy), 
  									rendered_im, NULL, True );
  				destroy_asimage( &rendered_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);
  			dpy = NULL;
  #else
  			/* writing result into the file */
  			ASImage2file( rendered_im, NULL, "astext.jpg", ASIT_Jpeg, 
  						  NULL );
  			destroy_asimage( &rendered_im );
  #endif
  		}
  	}
      return 0 ;
  }
  /**************/
  /****f* libAfterImage/tutorials/ASText.1 [7.1]
   * SYNOPSIS
   * Step 1. Opening and closing fonts.
   * DESCRIPTION
   * Before any text can be rendered using libAfterImage - desired font
   * has to be opened for use. Font opening process is two-step. At first
   * we need to create font manager ( ASFontManager ). That is done once,
   * and same font manager can be used throughout entire application. It
   * contains information about used external libraries, hash of opened
   * fonts, and some other info.
   *
   * When ASFontManager is created it could be used to obtain actuall fonts.
   * get_asfont() call is used to query cahce of the ASFontManager, to see
   * if the font has been loaded already, and if not - then it will load
   * the font and prepare it for drawing.
   *
   * EXAMPLE
   *     if( (fontman = create_font_manager( dpy, NULL, NULL )) != NULL )
   *         font = get_asfont( fontman, font_name, 0, size, ASF_GuessWho);
   *     if( font == NULL )
   *     {
   *         font = get_asfont( fontman, "fixed", 0, size, ASF_GuessWho );
   *         if( font == NULL )
   *         {
   *             show_error( "font \"fixed\" is not available either. 
   * 							Aborting.");
   *             return 1;
   *         }
   *     }
   *     ...
   *     destroy_font( font );
   *     destroy_font_manager( fontman, False );
   * SEE ALSO
   * create_font_manager(), get_asfont(), destroy_font(),
   * destroy_font_manager()
   ********/
  /****f* libAfterImage/tutorials/ASText.2 [7.2]
   * SYNOPSIS
   * Step 2. Approximating rendered text size.
   * DESCRIPTION
   * Prior to actually drawing the text it is useful to estimate the size
   * of the image, that rendered text will occupy, So that window can be
   * created of appropriate size, and othe interface elements laid out
   * accordingly. get_text_size() could be used to obtain rendered text
   * size without actually drawing it.
   * EXAMPLE
   *     get_text_size( text, font, type_3d, &width, &height );
   *     if( fore_image_file )
   *     {
   *         ASImage *tmp = file2ASImage( fore_image_file, 0xFFFFFFFF,
   *                                      SCREEN_GAMMA, 0, NULL );
   *         if( tmp )
   *         {
   *             if( tmp->width != width || tmp->height != height )
   *             {
   *                 if( scale_fore_image )
   *                     fore_im = scale_asimage( asv, tmp, width, height,
   *                                              ASA_ASImage, 0,
   *                                              ASIMAGE_QUALITY_DEFAULT );
   *                 else
   *                     fore_im = tile_asimage( asv, tmp, 0, 0,
   *                                             width, height, 0,
   *                                             ASA_ASImage, 0,
   *                                             ASIMAGE_QUALITY_DEFAULT );
   *                 destroy_asimage( &tmp );
   *             }else
   *                 fore_im = tmp ;
   *         }
   *     }
   * NOTES
   * In this particular example we either tile or scale foreground texture
   * to fit the text. In order to texturize the text  - we need to use
   * rendered text as an alpha channel on texture image. That can easily
   * be done only if both images are the same size.
   * SEE ALSO
   * get_text_size(), scale_asimage(), tile_asimage(), ASText.3
   ********/
  /****f* libAfterImage/tutorials/ASText.3 [7.3]
   * SYNOPSIS
   * Step 3. Rendering texturized text.
   * DESCRIPTION
   * The most effective text texturization technique provided by
   * libAfterImage consists of substitution of the alpha channel of the
   * texture, with rendered text. That is possible since all the text is
   * rendered into alpha channel only. move_asimage_channel() call is used
   * to accomplish this operation. This call actually removes channel
   * data from the original image and stores it in destination image. If
   * there was something in destination image's channel  already - it will
   * be destroyed.
   * All kinds of nifty things could be done using this call, actually.
   * Like, for example, rendered text can be moved into green channel of
   * the texture, creating funky effect.
   * EXAMPLE
   *     text_im = draw_text( text, font, 0 );
   *     if( fore_im )
   *     {
   *         move_asimage_channel( fore_im, IC_ALPHA, text_im, IC_ALPHA );
   *         destroy_asimage( &text_im );
   *     }else
   *         fore_im = text_im ;
   * NOTES
   * move_asimage_channel() will only work if both images have exactly the
   * same size. It will do nothing otherwise.
   * SEE ALSO
   * draw_text(), move_asimage_channel()
   ********/
  /****f* libAfterImage/tutorials/ASText.4 [7.4]
   * SYNOPSIS
   * Step 4. Merging foreground and background with bevel.
   * DESCRIPTION
   * On this step we have 2 images ready for us - background and texturized
   * text. At this point we need to merge them together by alpha-blending
   * text over background (remeber - text is alpha-channel of foreground
   * texture). At the same time we would like to add some nice bevel border
   * around entire image. To accomplish that task all we have to do is setup
   * ASImageLayer structure for both background and foreground, and apply
   * merge_layers on them. When it is done - we no longer need original
   * images and we destroy them to free up some memory.
   * EXAMPLE
   *     ASImageLayer layers[2] ;
   *     ASImageBevel bevel = {0, 0xFFDDDDDD, 0xFF555555,
   *                              0xFFFFFFFF, 0xFF777777, 0xFF444444,
   *                           BEVEL_HI_WIDTH, BEVEL_HI_WIDTH,
   *                           BEVEL_LO_WIDTH, BEVEL_LO_WIDTH,
   *                           BEVEL_HI_WIDTH, BEVEL_HI_WIDTH,
   *                           BEVEL_LO_WIDTH, BEVEL_LO_WIDTH } ;
   *     memset( &(layers[0]), 0x00, sizeof(layers) );
   *     layers[0].im = back_im ;
   *     layers[0].clip_width = width ;
   *     layers[0].clip_height = height ;
   *     layers[0].merge_scanlines = alphablend_scanlines ;
   *     layers[0].bevel = &bevel ;
   *     layers[1].im = fore_im ;
   *     layers[1].dst_x = TEXT_MARGIN ;
   *     layers[1].dst_y = TEXT_MARGIN ;
   *     layers[1].clip_width = fore_im->width ;
   *     layers[1].clip_height = fore_im->height ;
   *     layers[1].back_color = text_color ;
   *     layers[1].merge_scanlines = alphablend_scanlines ;
   *     rendered_im = merge_layers( asv, &(layers[0]), 2,
   *                                 width+BEVEL_ADDON, height+BEVEL_ADDON,
   *                                 ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
   *     destroy_asimage( &fore_im );
   *     destroy_asimage( &back_im );
   * NOTES
   * We have to remember that outside bevel border will addup to the image
   * size, hence we have to use width+BEVEL_ADDON , height+BEVEL_ADDON as
   * desired image size.
   * SEE ALSO
   * ASImageLayer, ASImageBevel, merge_layers()
   ********/
  
  