home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pbm / pbmtext.c < prev    next >
C/C++ Source or Header  |  1993-10-27  |  6KB  |  271 lines

  1. /* pbmtext.c - render text into a bitmap
  2. **
  3. ** Copyright (C) 1991 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pbm.h"
  14. #include "pbmfont.h"
  15.  
  16. static void fix_control_chars ARGS(( char* buf ));
  17. static void fill_rect ARGS(( bit** bits, int row0, int col0, int height, int width, bit color ));
  18. static void copy_rect ARGS(( bit** fbits, int frow0, int fcol0, int height, int width, bit** tbits, int trow0, int tcol0 ));
  19.  
  20. int
  21. main( argc, argv )
  22.     int argc;
  23.     char* argv[];
  24.     {
  25.     bit** bits;
  26.     int argn, rows, cols, row, col;
  27.     struct font* fn;
  28.     char* fontname;
  29.     int frows, fcols;
  30.     FILE* ifp;
  31.     int dump;
  32.     int char_width, char_height, char_awidth, char_aheight, vmargin, hmargin;
  33.     int char_row0[95];
  34.     int char_col0[95];
  35.     char buf[5000];
  36.     char** lp;
  37.     struct glyph* glyph;
  38.     int lines, maxlines, line;
  39.     int maxwidth, maxleftb;
  40.     char* cp;
  41.     char* usage = "[-font <fontfile>] [-builtin <fontname>] [text]";
  42.  
  43.     pbm_init( &argc, argv );
  44.  
  45.     /* Set up default parameters. */
  46.     argn = 1;
  47.     fn = 0;
  48.     fontname = "bdf";
  49.     dump = 0;
  50.  
  51.     /* Check for flags. */
  52.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  53.     {
  54.     if ( pm_keymatch( argv[argn], "-font", 2 ) )
  55.         {
  56.         ++argn;
  57.         if ( argn == argc )
  58.         pm_usage( usage );
  59.         
  60.         fn = pbm_loadfont( argv[argn] );
  61.         }
  62.     else if ( pm_keymatch( argv[argn], "-builtin", 2 ) )
  63.         {
  64.         ++argn;
  65.         if ( argn == argc )
  66.         pm_usage( usage );
  67.         fontname = argv[argn];
  68.         }
  69.     else if ( pm_keymatch( argv[argn], "-dump", 2 ) )
  70.         /* Undocumented dump flag for installing a new built-in font. */
  71.         dump = 1;
  72.     else
  73.         pm_usage( usage );
  74.     ++argn;
  75.     }
  76.  
  77.     if (fn == 0)
  78.     fn = pbm_defaultfont( fontname );
  79.  
  80.     if ( dump )
  81.     {
  82.     pbm_dumpfont( fn );
  83.     exit( 0 );
  84.     }
  85.     
  86.     maxlines = 50;
  87.     lp = (char**) malloc( maxlines * sizeof(char*) );
  88.     if ( lp == (char**) 0 )
  89.     pm_error( "out of memory" );
  90.  
  91.     if ( argn < argc )
  92.     { /* Get text from the command line. */
  93.     (void) strcpy( buf, argv[argn] );
  94.     ++argn;
  95.     while ( argn < argc )
  96.         {
  97.         (void) strcat( buf, " " );
  98.         (void) strcat( buf, argv[argn] );
  99.         ++argn;
  100.         }
  101.     fix_control_chars( buf );
  102.     lp[0] = buf;
  103.     lines = 1;
  104.     }
  105.     else
  106.     { /* Read text from stdin. */
  107.     lines = 0;
  108.     while ( gets( buf ) != NULL )
  109.         {
  110.         int l;
  111.  
  112.         fix_control_chars( buf );
  113.         l = strlen( buf );
  114.         if ( lines >= maxlines )
  115.         {
  116.         maxlines *= 2;
  117.         lp = (char**) realloc( (char*) lp, maxlines * sizeof(char*) );
  118.         if ( lp == (char**) 0 )
  119.             pm_error( "out of memory" );
  120.         }
  121.         lp[lines] = (char*) malloc( l + 1 );
  122.         if ( lp[lines] == 0 )
  123.         pm_error( "out of memory" );
  124.         (void) strcpy( lp[lines], buf );
  125.         ++lines;
  126.         }
  127.     }
  128.  
  129.     if ( lines == 1 )
  130.     {
  131.     vmargin = fn->maxheight / 2;
  132.     hmargin = fn->maxwidth;
  133.     }
  134.     else
  135.     {
  136.     vmargin = fn->maxheight;
  137.     hmargin = 2 * fn->maxwidth;
  138.     }
  139.     
  140.     /* The total height is easy to figure out */
  141.     rows = 2 * vmargin + lines * fn->maxheight;
  142.  
  143.     /* The total width is not so easy */
  144.     maxwidth = 0;
  145.     maxleftb = 0;
  146.     for ( line = 0; line < lines; ++line ) {
  147.     int isfirst = 1;
  148.     int x = 0;
  149.     int bwid = 0;
  150.     char lastch;
  151.  
  152.     for ( cp = lp[line]; *cp != '\0'; ++cp ) {
  153.         if (!fn->glyph[*cp])
  154.         continue;
  155.         if (isfirst) {
  156.         isfirst = 0;
  157.         if (fn->glyph[*cp]->x < 0)
  158.             x = -fn->glyph[*cp]->x;
  159.             else
  160.             bwid += fn->glyph[*cp]->x;
  161.  
  162.             bwid += x;
  163.         }
  164.         bwid += fn->glyph[*cp]->xadd;
  165.         lastch = *cp;
  166.     }
  167.     if (!isfirst) {
  168.         bwid -= fn->glyph[lastch]->xadd;
  169.         bwid += fn->glyph[lastch]->width + fn->glyph[lastch]->x;
  170.     }
  171.  
  172.     if (bwid > maxwidth)
  173.         maxwidth = bwid;
  174.     if (x > maxleftb)
  175.         maxleftb = x;
  176.     }
  177.  
  178.     cols = 2 * hmargin + maxwidth + maxleftb;
  179.     bits = pbm_allocarray( cols, rows );
  180.  
  181.     /* Fill background with white */
  182.     fill_rect( bits, 0, 0, rows, cols, PBM_WHITE );
  183.     
  184.     /* Render characters. */
  185.     for ( line = 0; line < lines; ++line ) {
  186.     row = vmargin + line * fn->maxheight;
  187.     col = hmargin + maxleftb;
  188.  
  189.     for ( cp = lp[line]; *cp != '\0'; ++cp )
  190.         {
  191.         int h, w, y;
  192.  
  193.         if (!(glyph = fn->glyph[*cp]))
  194.         continue;
  195.  
  196.         y = row + fn->maxheight + fn->y - glyph->height - glyph->y;
  197.  
  198.         for (h = 0; h < glyph->height; h++) {
  199.         for (w = 0; w < glyph->width; w++) {
  200.             if (glyph->bmap[h * glyph->width + w])
  201.             bits[y][w + col + glyph->x] = PBM_BLACK;
  202.         }
  203.         y++;
  204.         }
  205.         col += glyph->xadd;
  206.     }
  207.     }
  208.  
  209.     /* All done. */
  210.     pbm_writepbm( stdout, bits, cols, rows, 0 );
  211.     pm_close( stdout );
  212.  
  213.     exit( 0 );
  214.     }
  215.  
  216. static void
  217. fix_control_chars( buf )
  218.     char* buf;
  219.     {
  220.     int i, j, n, l;
  221.  
  222.     for ( i = 0; buf[i] != '\0'; ++i )
  223.     {
  224.     if ( buf[i] == '\t' )
  225.         { /* Turn tabs into the right number of spaces. */
  226.         n = ( i + 8 ) / 8 * 8;
  227.         l = strlen( buf );
  228.         for ( j = l; j > i; --j )
  229.         buf[j + n - i - 1] = buf[j];
  230.         for ( ; i < n; ++i )
  231.         buf[i] = ' ';
  232.         --i;
  233.         }
  234.     else if ( buf[i] < ' ' || buf[i] > '~' )
  235.         /* Turn other control chars into a single space. */
  236.         buf[i] = ' ';
  237.     }
  238.     }
  239.  
  240. #if __STDC__
  241. static void
  242. fill_rect( bit** bits, int row0, int col0, int height, int width, bit color )
  243. #else /*__STDC__*/
  244. static void
  245. fill_rect( bits, row0, col0, height, width, color )
  246.     bit** bits;
  247.     int row0, col0, height, width;
  248.     bit color;
  249. #endif /*__STDC__*/
  250.     {
  251.     int row, col;
  252.  
  253.     for ( row = row0; row < row0 + height; ++row )
  254.     for ( col = col0; col < col0 + width; ++col )
  255.         bits[row][col] = color;
  256.     }
  257.  
  258. static void
  259. copy_rect( fbits, frow0, fcol0, height, width, tbits, trow0, tcol0 )
  260.     bit** fbits;
  261.     int frow0, fcol0, height, width;
  262.     bit** tbits;
  263.     int trow0, tcol0;
  264.     {
  265.     int row, col;
  266.  
  267.     for ( row = 0; row < height; ++row )
  268.     for ( col = 0; col < width; ++col )
  269.         tbits[trow0 + row][tcol0 + col] = fbits[frow0 + row][fcol0 + col];
  270.     }
  271.