IFontBDF.c
资源名称:ilib [点击查看]
上传用户:changbiao
上传日期:2007-01-13
资源大小:141k
文件大小:12k
源码类别:

图片显示

开发平台:

C/C++

  1. /*
  2. ** Routines for reading in a BDF (font) file.
  3. ** BDF files can be obtained as part of the X Windows System
  4. ** at ftp://ftp.x.org/
  5. **
  6. ** Copyright 1999 Craig Knudsen
  7. **
  8. ** 12-Apr-1999 Craig Knudsen cknudsen@radix.net
  9. ** Added support for high ascii characters.
  10. ** (This has disabled usage of the escape sequences like
  11. ** "33agrave".)
  12. ** 17-May-1996 Craig Knudsen   cknudsen@radix.net
  13. ** Created
  14. */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <fcntl.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include "Ilib.h"
  23. #include "IlibP.h"
  24. #include "IFontBDF.h"
  25. #ifndef FALSE
  26. #define FALSE 0
  27. #endif
  28. #ifndef TRUE
  29. #define TRUE 1
  30. #endif
  31. /*
  32. ** Define the BDF translations into standard ASCII.
  33. ** Note we will still handle non-ASCII characters.
  34. ** Use "33agrave;" to get the agrave symbol.
  35. */
  36. typedef struct {
  37.   char *name;
  38.   unsigned char value;
  39. } char_translation;
  40. char_translation translation[] = {
  41.   { "space", ' ' },
  42.   { "exclam", '!' },
  43.   { "quotedbl", '"' },
  44.   { "numbersign", '#' },
  45.   { "dollar", '$' },
  46.   { "percent", '%' },
  47.   { "ampersand", '&' },
  48.   { "quoteright", ''' },
  49.   { "parenleft", '(' },
  50.   { "parenright", ')' },
  51.   { "asterisk", '*' },
  52.   { "plus", '+' },
  53.   { "comma", ',' },
  54.   { "minus", '-' },
  55.   { "period", '.' },
  56.   { "slash", '/' },
  57.   { "zero", '0' },
  58.   { "one", '1' },
  59.   { "two", '2' },
  60.   { "three", '3' },
  61.   { "four", '4' },
  62.   { "five", '5' },
  63.   { "six", '6' },
  64.   { "seven", '7' },
  65.   { "eight", '8' },
  66.   { "nine", '9' },
  67.   { "colon", ':' },
  68.   { "semicolon", ';' },
  69.   { "less", '<' },
  70.   { "equal", '=' },
  71.   { "greater", '>' },
  72.   { "question", '?' },
  73.   { "at", '@' },
  74.   { "bracketleft", '[' },
  75.   { "backslash", '\' },
  76.   { "bracketright", ']' },
  77.   { "asciicircum", '^' },
  78.   { "underscore", '_' },
  79.   { "quoteleft", '`' },
  80.   { "braceleft", '{' },
  81.   { "bar", '|' },
  82.   { "braceright", '}' },
  83.   { "asciitilde", '~' },
  84.   { NULL, '' },
  85. };
  86. static char *trans_table[256];
  87. typedef struct {
  88.   char *name; /* translated name ("A", "B", "33agrave;") */
  89.   unsigned int *data; /* character definition */
  90.   unsigned int width; /* character width */
  91.   unsigned int height; /* height (size of lines array) */
  92.   unsigned int actual_width; /* width with padding on left and right */
  93.   int xoffset; /* pixels to move to the right before drawing */
  94.   int yoffset; /* pixels to move to up before drawing */
  95. } Char;
  96. typedef struct {
  97.   char *name; /* font name */
  98.   char *family; /* font family ("Times") */
  99.   char *face_name; /* face name ("Times Roman") */
  100.   char *width_name; /* face name ("Normal") */
  101.   char *weight; /* font weight ("R") */
  102.   int proportional; /* yes or no? (fixed/proportional font) */
  103.   int pixel_size;
  104.   int font_ascent;
  105.   int font_descent;
  106.   Char *chars[256]; /* list of chars */
  107.   Char **other_chars; /* non ASCII chars */
  108.   unsigned int num_other_chars; /* size of above array */
  109. } Font;
  110. static Font **fonts = NULL;
  111. static int num_fonts = 0;
  112. IError IFontBDFReadFile ( name, path )
  113. char *name;
  114. char *path;
  115. {
  116.   struct stat buf;
  117.   FILE *fp;
  118.   char text[256];
  119.   IError ret;
  120.   char **lines;
  121.   int num_lines = 0, loop;
  122.   if ( stat ( path, &buf ) == 0 ) {
  123.     fp = fopen ( path, "r" );
  124.     if ( !fp )
  125.       return ( INoSuchFile );
  126.     lines = malloc ( 1 );
  127.     while ( fgets ( text, 256, fp ) ) {
  128.       lines = realloc ( lines, ( num_lines + 1 ) * sizeof ( char * ) );
  129.       if ( text[strlen(text)-1] == '12' )
  130.         text[strlen(text)-1] = '';
  131.       if ( text[strlen(text)-1] == '15' )
  132.         text[strlen(text)-1] = '';
  133.       lines[num_lines] = (char *) malloc ( strlen ( text ) + 1 );
  134.       strcpy ( lines[num_lines++], text );
  135.     }
  136.     fclose ( fp );
  137.     lines = realloc ( lines, ( num_lines + 1 ) * sizeof ( char * ) );
  138.     lines[num_lines++] = NULL;
  139.     ret = IFontBDFReadData ( name, lines );
  140.     for ( loop = 0; lines[loop]; loop++ )
  141.       free ( lines[loop] );
  142.     free ( lines );
  143.     return ( ret );
  144.   }
  145.   else {
  146.    fprintf ( stderr, "Cannot find font file: %sn", path );
  147.    return ( INoSuchFile );
  148.   }
  149. }
  150. IError IFontBDFReadData ( name, lines )
  151. char *name;
  152. char **lines;
  153. {
  154.   char ch[256], *text;
  155.   int temp;
  156.   int in_bitmap = 0, hexval;
  157.   int loop, which_char, which_bit;
  158.   int num_ret;
  159.   char c;
  160.   Font *font;
  161.   Char *character;
  162.   int xpos, ypos;
  163.   static int first = 1;
  164.   int line_no = 0;
  165.   /* Initialize a few things the first time this is called */
  166.   if ( first ) {
  167.     first = 0;
  168.     memset ( trans_table, '', sizeof ( trans_table ) );
  169.     for ( loop = 0; translation[loop].name; loop++ ) {
  170.       trans_table[translation[loop].value] = translation[loop].name;
  171.     }
  172.   }
  173.   font = (Font *) malloc ( sizeof ( Font ) );
  174.   memset ( font, '', sizeof ( Font ) );
  175.   font->name = (char *) malloc ( strlen ( name ) + 1 );
  176.   strcpy ( font->name, name );
  177.   memset ( font->chars, '', sizeof ( font->chars ) );
  178.   font->other_chars = malloc ( 4 );
  179.   while ( lines[line_no] ) {
  180.     text = lines[line_no];
  181.     if ( strncmp ( text, "STARTCHAR", 9 ) == 0 ) {
  182.       strcpy ( ch, text + 10 );
  183.       for ( loop = 0; translation[loop].name; loop++ ) {
  184.         if ( strcmp ( translation[loop].name, ch ) == 0 ) {
  185.           ch[0] = translation[loop].value;
  186.           ch[1] = '';
  187.           break;
  188.         }
  189.       }
  190.       in_bitmap = 0;
  191.       character = (Char *) malloc ( sizeof ( Char ) );
  192.       memset ( character, '', sizeof ( Char ) );
  193.       num_ret = 1;
  194.       character->name = (char *) malloc ( strlen ( ch ) + 1 );
  195.       strcpy ( character->name, ch );
  196.     }
  197.     else if ( strncmp ( text, "ENCODING", 8 ) == 0 ) {
  198.       temp = atoi ( text + 9 );
  199.       if ( temp > 0 && temp < 256 && character != NULL ) {
  200.         sprintf ( ch, "%c", temp );
  201.         strcpy ( character->name, ch );
  202.       }
  203.     }
  204.     else if ( strncmp ( text, "PIXEL_SIZE", 10 ) == 0 ) {
  205.       font->pixel_size = atoi ( text + 11 );
  206.     }
  207.     else if ( strncmp ( text, "FONT_ASCENT", 11 ) == 0 ) {
  208.       font->font_ascent = atoi ( text + 12 );
  209.     }
  210.     else if ( strncmp ( text, "FONT_DESCENT", 12 ) == 0 ) {
  211.       font->font_descent = atoi ( text + 13 );
  212.     }
  213.     else if ( strncmp ( text, "SPACING", 7 ) == 0 ) {
  214.       if ( strncmp ( text + 8, ""P"", 3 ) == 0 )
  215.         font->proportional = TRUE;
  216.       else
  217.         font->proportional = FALSE;
  218.     }
  219.     else if ( strncmp ( text, "FACE_NAME", 9 ) == 0 ) {
  220.       font->face_name = (char *) malloc ( strlen ( text + 10 ) + 1 );
  221.       strcpy ( font->face_name, text + 10 );
  222.     }
  223.     else if ( strncmp ( text, "SETWIDTH_NAME", 13 ) == 0 ) {
  224.       font->width_name = (char *) malloc ( strlen ( text + 14 ) + 1 );
  225.       strcpy ( font->width_name, text + 14 );
  226.     }
  227.     else if ( strncmp ( text, "BBX", 3 ) == 0 ) {
  228.       sscanf ( text, "BBX %d %d %d %d", &character->width, &character->height,
  229.         &character->xoffset, &character->yoffset );
  230.       /* use the width and height to allocate space for the data */
  231.       character->data = (unsigned int *) calloc ( character->height * character->width,
  232.         sizeof ( int ) );
  233.     }
  234.     else if ( strncmp ( text, "DWIDTH", 6 ) == 0 ) {
  235.       sscanf ( text, "DWIDTH %d %d", &character->actual_width, &temp );
  236.     }
  237.     else if ( strcmp ( text, "BITMAP" ) == 0 ) {
  238. /*
  239.       if ( character->width <= 0 || character->height <= 0 ) {
  240.         fprintf ( stderr, "BBX line not found. (line %d)n", line_no + 1 );
  241.         return ( IFontError );
  242.       }
  243. */
  244.       in_bitmap = 1;
  245.       xpos = ypos = 0;
  246.     } else if ( strcmp ( text, "ENDCHAR" ) == 0 ) {
  247.       if ( in_bitmap ) {
  248.         in_bitmap = 0;
  249.         if ( ! character ) {
  250.           return ( IFontError );
  251.         }
  252.         if ( strlen ( character->name ) == 1 )
  253.           font->chars[(unsigned char)character->name[0]] = character;
  254.         else {
  255.           font->other_chars = (Char **) realloc ( font->other_chars,
  256.             ( font->num_other_chars + 1 ) * sizeof ( Char * ) );
  257.           font->other_chars[font->num_other_chars++] = character;
  258.         }
  259.       }
  260. /*
  261.       for ( loop = 0; loop < character->width * character->height; loop++ ) {
  262.         if ( character->data[loop] )
  263.           printf ( "+" );
  264.         else
  265.           printf ( "-" );
  266.       }
  267.       printf ( "n-------------------n" );
  268. */
  269.     } else if ( in_bitmap ) {
  270.       xpos = 0;
  271.       for ( loop = 0; loop < character->width; loop++ ) {
  272.         which_char = loop / 4;
  273.         c = text[which_char];
  274.         if ( isdigit ( c ) )
  275.           hexval = (int) ( c - '0' );
  276.         else
  277.           hexval = (int) ( c - 'A' ) + 10;
  278.         which_bit = 3 - ( loop % 4 );
  279.         if ( hexval & ( 1 << which_bit ) ) {
  280.           character->data[ypos * character->width + xpos] = 1;
  281.           /*printf ( "X" );*/
  282.         }
  283.         else {
  284.           character->data[ypos * character->width + xpos] = 0;
  285.           /*printf ( " " );*/
  286.         }
  287.         xpos++;
  288.       }
  289.       ypos++;
  290.       /*printf ( "n" );*/
  291.     }
  292.     line_no++;
  293.   }
  294.   /* Now add this font to the tree of loaded fonts */
  295.   if ( ! fonts )
  296.      fonts = (Font **) malloc ( sizeof ( Font * ) );
  297.   else
  298.     fonts = (Font **) realloc ( fonts, 
  299.     ( num_fonts + 1 ) * sizeof ( Font * ) );
  300.   fonts[num_fonts++] = font;
  301.   /* return success */
  302.   return ( INoError );
  303. }
  304. Font *_IGetFont ( name )
  305. char *name;
  306. {
  307.   int loop;
  308.   if ( num_fonts ) {
  309.     for ( loop = 0; loop < num_fonts; loop++ ) {
  310.       if ( fonts[loop] ) {
  311.         if ( strcmp ( fonts[loop]->name, name ) == 0 )
  312.           return ( (Font *)fonts[loop] );
  313.       }
  314.     }
  315.   }
  316.   return ( NULL );
  317. }
  318. static void free_character ( ch )
  319. Char *ch;
  320. {
  321.   free ( ch->name );
  322.   free ( ch->data );
  323.   free ( ch );
  324. }
  325. IError IFontBDFFree ( name )
  326. char *name;
  327. {
  328.   Font *font;
  329.   unsigned int loop;
  330.   font = _IGetFont ( name );
  331.   if ( ! font )
  332.     return ( INoSuchFont );
  333.   for ( loop = 0; loop < 256; loop++ ) {
  334.     if ( font->chars[loop] )
  335.       free_character ( font->chars[loop] );
  336.   }
  337.   for ( loop = 0; loop < font->num_other_chars; loop++ ) {
  338.     free_character ( font->other_chars[loop] );
  339.   }
  340.   free ( font->other_chars );
  341.   if ( font->name )
  342.     free ( font->name );
  343.   if ( font->family )
  344.     free ( font->family );
  345.   if ( font->face_name )
  346.     free ( font->face_name );
  347.   if ( font->width_name )
  348.     free ( font->width_name );
  349.   if ( font->weight )
  350.     free ( font->weight );
  351.   free ( font );
  352.   return ( INoError );
  353. }
  354. IError _IFontBDFGetSize ( name, height_return )
  355. char *name;
  356. unsigned int *height_return;
  357. {
  358.   Font *font;
  359.   font = _IGetFont ( name );
  360.   if ( ! font )
  361.     return ( INoSuchFont );
  362.   *height_return = font->pixel_size;
  363.   return ( INoError );
  364. }
  365. IError IFontBDFGetChar ( name, ch, bitdata, width, height,
  366.   actual_width, size, xoffset, yoffset )
  367. char *name;
  368. char *ch;
  369. unsigned int **bitdata;
  370. unsigned int *height;
  371. unsigned int *width;
  372. unsigned int *actual_width;
  373. unsigned int *size;
  374. int *xoffset;
  375. int *yoffset;
  376. {
  377.   Font *font;
  378.   Char *character = NULL;
  379.   unsigned int loop;
  380.   static char *last_name = NULL;
  381.   static Font *last_font = NULL;
  382.   if ( ! ch || ! strlen ( ch ) )
  383.     return ( IInvalidArgument );
  384.   if ( last_name == name ) {
  385.     font = last_font;
  386.   }
  387.   else {
  388.     font = _IGetFont ( name );
  389.     if ( ! font )
  390.       return ( INoSuchFont );
  391.     last_name = name;
  392.     last_font = font;
  393.   }
  394.   /* we got the font.  now get the character */
  395.   if ( strlen ( ch ) == 1 ) {
  396.     character = font->chars[(unsigned char)ch[0]];
  397.   }
  398.   /* if more than a single char, must not be in the ascii list */
  399.   else {
  400.     for ( loop = 0, character = NULL; loop < font->num_other_chars; loop++ ) {
  401.       if ( strcmp ( ch, font->other_chars[loop]->name ) == 0 ) {
  402.         character = font->other_chars[loop];
  403.         break;
  404.       }
  405.     }
  406.     if ( ! character )
  407.       character = font->chars[' '];
  408.   }
  409.   /* if still not there, use space */
  410.   if ( ! character ) {
  411.     /* This should not happen if font is defined correctly */
  412.     return ( IFontError );
  413.   }
  414.   
  415.   *height = character->height;
  416.   *width = character->width;
  417.   *actual_width = character->actual_width;
  418.   *size = font->pixel_size;
  419.   *xoffset = character->xoffset;
  420.   *yoffset = character->yoffset;
  421.   *bitdata = character->data;
  422.   return ( INoError );
  423. }