---
name: "astext"
section: "3x"
platform: "linux"
package: "libafterimage-dev"
version: "2.2.12-18"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/astext"
---

# astext(3x)

demonstrates antialiased texturized text rendering libAfterImage/tutorials/ASText

## NAME

**astext** - demonstrates antialiased texturized text rendering libAfterImage/tutorials/ASText

## NAMEASText

## 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 ; }

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 cache 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() 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 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() 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 (remember - 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()
