Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.     convert.c: converts text bitmaps into binary bitmaps.
  3.     This has been written with an aim to detect any errors that
  4.     might have crept in while generating a text bitmap for a font.
  5.  
  6.     Copyright 2011 dunkaist <dunkaist@gmail.com>
  7.     Copyright 2014 ashmew2 <ashmew2@gmail.com>
  8.     Distributed under the terms of the GNU General Public License v3.
  9.     See http://www.gnu.org/licenses/gpl.txt for the full license text.
  10. */
  11.  
  12. /*
  13.     For TRANSLATION, only the hard coded strings such as in usage[] need to
  14.     rewritten in the desired language. The translation selection should be
  15.     inside an #if LANG == RUS {} #else {} block. All messsages are printed
  16.     using msg_printx() and the translations need to be done for all such
  17.     calls.
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <stdarg.h>
  25. #include <stdbool.h>
  26.  
  27. #define FONT_HEIGHT         9   /* The height of each symbol in input file */
  28. #define FONT_WIDTH_MONO     5   /* Fixed width for mono fonts */
  29. #define FONT_WIDTH_VAR      7   /* Max symbol width */
  30. #define LINE_BUFFER_SIZE   12   /* For FONT_WIDTH_VAR and delimiters */
  31. #define NUM_SYMBOLS       256   /* Number of symbols in input file */
  32.  
  33. enum error_code {
  34.   ERROR_PARSING_ARGS = 1,
  35.   ERROR_OPENING_FILE,
  36.   ERROR_INVALID_INPUT_FILE
  37. };
  38.  
  39. void msg_printx(int errnum, char *message, ...)
  40. {
  41.   va_list args;
  42.  
  43.   va_start(args, message);
  44.   vfprintf(stderr, message, args);
  45.   va_end(args);
  46.  
  47.   exit(errnum);
  48. }
  49.  
  50. void usage_printx(char *prog_name)
  51. {
  52.   char usage[] = "Usage: \n"
  53.                  "\t%s <INPUTFILE> <OUTPUTFILE> <-m>\n\n"
  54.                  "Converts font bitmaps from text to binary format.\n\n"
  55.                  "\tINPUTFILE\t The input file containing text bitmap.\n"
  56.                  "\tOUTPUTFILE\t The output file for writing binary bitmap.\n"
  57.                  "\t-m\t         Mono flag. -0 for mono. -1 otherwise.\n\n"
  58.                  "Examples: \n"
  59.                  "\t%s char.txt CHAR.MT -0\n"
  60.                  "\t%s char2.txt CHAR2.MT -1\n\n"
  61.                  "Exit status: \n"
  62.                  "\t 0: Successful conversion.\n"
  63.                  "\t 1: Incorrect arguments supplied to the command.\n"
  64.                  "\t 2: Files could not be opened for read/write.\n"
  65.                  "\t 3: Error(s) reading data from file.\n\n"
  66.                  "This is a part of the font_conv program in KolibriOS.\n";
  67.  
  68.   msg_printx(ERROR_PARSING_ARGS, usage, prog_name, prog_name, prog_name);
  69. }
  70.  
  71. char* get_row(bool use_mono)
  72. {
  73.   static int line_number = 1; /* Initialize to 1 for first line being read */
  74.   static size_t len_line;
  75.   static char line[LINE_BUFFER_SIZE];
  76.  
  77.   size_t len;
  78.   char *current_line;
  79.   int i;
  80.  
  81.   current_line = fgets(line, LINE_BUFFER_SIZE - 1, stdin);
  82.  
  83.   if(!current_line)
  84.     msg_printx(ERROR_INVALID_INPUT_FILE, "Error: could not read line from input file.\n");
  85.  
  86.   len = strlen(current_line);
  87.  
  88.   if(len > 2)
  89.     {
  90.       if(line[len - 1] == '\n' && line[len - 2] == '\r')
  91.         len -= 2;
  92.       else if(line[len - 1] == '\n')
  93.         --len;
  94.       else if(line_number != ((FONT_HEIGHT + 1) * NUM_SYMBOLS)) /* if last line of input */
  95.         msg_printx(ERROR_INVALID_INPUT_FILE, "Error: line %d: no newline character found in first %d bytes.\n", 12 - 1, line_number);
  96.  
  97.       line[--len] = '\0';
  98.     }
  99.   else
  100.     msg_printx(ERROR_INVALID_INPUT_FILE, "Error: line %d: line too short.\n", line_number);
  101.  
  102.   if(line_number == 1) /* Processing first line in input */
  103.     {
  104.       if(len > FONT_WIDTH_VAR)
  105.         msg_printx(ERROR_INVALID_INPUT_FILE, "Error: line %d: length of line is larger than %d (maximum allowed width).\n", line_number, FONT_WIDTH_VAR);
  106.  
  107.       if((use_mono) && (len != FONT_WIDTH_MONO))
  108.         msg_printx(ERROR_INVALID_INPUT_FILE, "Error: line %d: length of line is not equal to %d (mono font width).\n", line_number, FONT_WIDTH_MONO);
  109.  
  110.       len_line = len;
  111.     }
  112.   else
  113.     {
  114.       if(len != len_line)
  115.         msg_printx(ERROR_INVALID_INPUT_FILE, "Error: line %d: length of line does not match length of first line in file.\n", line_number);
  116.  
  117.       /*validate Row*/
  118.       for(i = 0; line[i]; i++)
  119.         if(!isprint(line[i]))
  120.           msg_printx(ERROR_INVALID_INPUT_FILE, "Error: line %d: non printable characters found on line.\n", line_number);      
  121.     }
  122.  
  123.   ++line_number;
  124.  
  125.   return line;
  126. }
  127.  
  128. int do_symbol(short int font_width)
  129. {
  130.   short int row, col;
  131.   int data;
  132.  
  133.   for(row = FONT_HEIGHT; row; row--)
  134.     {
  135.       char *line = get_row(font_width == FONT_WIDTH_MONO);
  136.  
  137.       data = 0; /* Create empty byte for storing line */
  138.  
  139.       for(col = 0; col < font_width; col++)
  140.         {
  141.           if(line[col] != ' ')
  142.             data |= 1<<col; /* Get corresponding bit for non-space character */
  143.         }
  144.  
  145.       putchar(data);
  146.     }
  147.   return 0;
  148. }
  149.  
  150. int main(int argc, char *argv[])
  151. {
  152.   char *input_file = NULL;
  153.   char *output_file = NULL;
  154.   short int char_num;
  155.   bool use_mono;
  156.  
  157.   if(argc != 4) /* Required argc is 4, for three mandatory arguments. */
  158.     usage_printx(argv[0]);
  159.   else
  160.     {
  161.       if(!strcmp(argv[3],"-0"))
  162.         use_mono = true;
  163.       else if(!strcmp(argv[3],"-1"))
  164.         use_mono = false;
  165.       else
  166.         usage_printx(argv[0]);
  167.     }
  168.  
  169.   input_file = argv[1];
  170.   output_file = argv[2];
  171.  
  172.   if(!freopen(input_file, "rt", stdin))
  173.     msg_printx(ERROR_OPENING_FILE, "Error: unable to open %s for reading.\n", input_file);  
  174.  
  175.   if(!freopen(output_file, "wb", stdout))
  176.     msg_printx(ERROR_OPENING_FILE, "Error: unable to open %s for writing.\n", output_file);  
  177.  
  178.   for(char_num = NUM_SYMBOLS; char_num; char_num--)
  179.     {
  180.       char *line = get_row(use_mono);
  181.  
  182.       if(use_mono)
  183.         {
  184.           do_symbol(FONT_WIDTH_MONO);
  185.         }
  186.       else
  187.         {
  188.           size_t len = strlen(line);
  189.  
  190.           int p = line[len - 1];
  191.  
  192.           putchar(p == ' '? 0x08 : p-47); /* Put a backspace character or a decimal digit */
  193.           do_symbol(FONT_WIDTH_VAR);
  194.         }
  195.     }
  196.  
  197.   return 0;
  198. }
  199.