home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / fontutils-0.6-base.tgz / fontutils-0.6-base.tar / fsf / fontutils / gf / gf_input.c < prev    next >
C/C++ Source or Header  |  1992-06-13  |  28KB  |  977 lines

  1. /* gf_input.c: read objects from one GF file.
  2.  
  3. Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include "file-input.h"
  22. #include "gf.h"
  23. #include "scaled-num.h"
  24.  
  25. #include "gf_opcodes.h"
  26.  
  27.  
  28. /* If true, print out what we read.  */
  29. static boolean tracing_gf_input = false;
  30.  
  31.  
  32. /* These identify the file we're reading, for our own use.  */
  33. static string gf_input_filename;
  34. static FILE *gf_input_file;
  35.  
  36.  
  37. /* Low-level input.  These macros call the corresponding routines in
  38.    kbase, using the static variables for the input file and filename.  */
  39.  
  40. #define GF_FTELL() xftell (gf_input_file, gf_input_filename)
  41. #define GF_FSEEK(offset, from_where) \
  42.   xfseek (gf_input_file, offset, from_where, gf_input_filename)
  43. #define GF_GET_BYTE() get_byte (gf_input_file, gf_input_filename)
  44. #define GF_GET_PREVIOUS() get_previous_byte (gf_input_file, gf_input_filename)
  45. #define GF_GET_TWO() get_two (gf_input_file, gf_input_filename)
  46. #define GF_GET_FOUR() get_four (gf_input_file, gf_input_filename)
  47. #define GF_GET_SIGNED_FOUR() \
  48.   get_signed_four (gf_input_file, gf_input_filename)
  49. #define GF_GET_PREVIOUS_FOUR() \
  50.   get_previous_four (gf_input_file, gf_input_filename)
  51. #define GF_MATCH_BYTE(expected) \
  52.   match_byte (expected, gf_input_file, gf_input_filename)
  53.  
  54. static void get_specials (byte_count_type special_ptr);
  55. static string gf_get_string (unsigned string_length);
  56. static four_bytes gf_get_three (void);
  57.  
  58.  
  59. /* We have occasion to refer to the postamble when reading the characters,
  60.    so we keep a copy for ourselves.  */
  61. static gf_postamble_type *private_postamble;
  62.  
  63. /* This reads into `private_postamble'.  */
  64. static void get_postamble (void);
  65.  
  66. static void get_locators (void);
  67.  
  68.  
  69. /* Pointers to the characters we have read.  */
  70. static gf_char_type *char_list[MAX_CHARCODE + 1];
  71.  
  72.  
  73. /* Subroutines for reading a character.  */
  74. static void get_full_boc (gf_char_type *);
  75. static void get_abbreviated_boc (gf_char_type *);
  76. static void get_character_bitmap (gf_char_type *);
  77. static void get_postamble_info (gf_char_type *);
  78. static void deblank (gf_char_type *);
  79.  
  80. /* Subroutines for reading the bitmap.  */
  81. static void get_paint (coordinate_type *, boolean *, one_byte, gf_char_type *);
  82. static void get_skip (coordinate_type *, boolean *, one_byte, gf_char_type *);
  83. static void get_new_row
  84.   (coordinate_type *, boolean *, one_byte, gf_char_type *);
  85.  
  86. /* For handling raw characters.  */
  87. static void append_byte (raw_char_type *, one_byte);
  88. static void append_n_bytes (raw_char_type *, four_bytes, one_byte *);
  89. static raw_char_type new_raw_gf_char (gf_char_locator_type);
  90.  
  91. /* Start reading FILENAME.  Return false if it can't be opened.  */
  92.  
  93. boolean
  94. gf_open_input_file (string filename)
  95. {
  96.   if (gf_input_file != NULL)
  97.     FATAL2 ("gf_open_input_file: Attempt to open `%s', but `%s' is
  98. already open", filename, gf_input_filename);
  99.  
  100.   gf_input_filename = filename;
  101.   gf_input_file = fopen (filename, "r");
  102.  
  103.   return gf_input_file != NULL;
  104. }
  105.  
  106.  
  107. void
  108. gf_close_input_file ()
  109. {
  110.   unsigned code;
  111.   
  112.   assert (gf_input_file != NULL);
  113.  
  114.   xfclose (gf_input_file, gf_input_filename);
  115.  
  116.   gf_input_filename = NULL;
  117.   gf_input_file = NULL;
  118.   private_postamble = NULL;
  119.   
  120.   for (code = 0; code <= MAX_CHARCODE; code++)
  121.     char_list[code] = NULL;
  122. }
  123.  
  124. /* The only interesting thing in the preamble, either to the user or to
  125.    us, is the comment.
  126.  
  127.    It is wrong to save and restore the position in the gf file, since
  128.    this routine is primarily useful if the user intends to use
  129.    `gf_get_next_char', i.e., read the characters in the order they
  130.    appear.  In that case, the user has to read the preamble first.  */
  131.  
  132. string
  133. gf_get_preamble ()
  134. {
  135.   one_byte comment_length;
  136.   string answer;
  137.  
  138.   assert (gf_input_file != NULL);
  139.  
  140.   GF_MATCH_BYTE (PRE);
  141.   GF_MATCH_BYTE (GF_ID);
  142.  
  143.   comment_length = GF_GET_BYTE ();
  144.   answer = gf_get_string (comment_length);
  145.  
  146.   return answer;
  147. }
  148.  
  149. /* Reading the postamble.  This is the user-level call.  We make no
  150.    assumptions about the current position of the file pointer.  */
  151.  
  152. gf_postamble_type
  153. gf_get_postamble ()
  154. {
  155.   one_byte b;
  156.   byte_count_type old_pos, post_ptr;
  157.   unsigned this_char;
  158.  
  159.   assert (gf_input_file != NULL);
  160.  
  161.   if (private_postamble != NULL)   /* Previously read it?  */
  162.     return *private_postamble;
  163.  
  164.   old_pos = GF_FTELL ();
  165.   GF_FSEEK (0, SEEK_END);
  166.  
  167.   /* If the input file is empty, give a better message than `Invalid
  168.      argument' (because we are trying to seek before the beginning).  */
  169.   if (GF_FTELL () == 0)
  170.     FATAL1 ("%s: empty file", gf_input_filename);
  171.  
  172.   do
  173.     b = GF_GET_PREVIOUS ();
  174.   while (b == GF_SIGNATURE);
  175.  
  176.   if (b != GF_ID)
  177.     FATAL2 ("Expected GF id (%u), found %u", GF_ID, b);
  178.  
  179.   post_ptr = GF_GET_PREVIOUS_FOUR ();
  180.  
  181.   private_postamble = xmalloc (sizeof (gf_postamble_type));
  182.  
  183.   for (this_char = 0; this_char <= MAX_CHARCODE; this_char++)
  184.     {
  185.       GF_CHAR_LOC (*private_postamble, this_char).charcode
  186.         = this_char;
  187.       GF_CHAR_LOC (*private_postamble, this_char).char_pointer
  188.         = NULL_BYTE_PTR;
  189.     }
  190.  
  191.   GF_FSEEK (post_ptr, SEEK_SET);
  192.   get_postamble ();        /* Fills in `private_postamble'.  */
  193.  
  194.   GF_FSEEK (old_pos, SEEK_SET);
  195.   return *private_postamble;
  196. }
  197.  
  198.  
  199. /* Assume we are positioned at the beginning of the postamble.  Fill in
  200.    `private_postamble' with what we find.  */
  201.  
  202. static void
  203. get_postamble ()
  204. {
  205.   GF_MATCH_BYTE (POST);
  206.  
  207.   (void) GF_GET_FOUR ();        /* Ignore the special pointer.  */
  208.  
  209.   GF_DESIGN_SIZE (*private_postamble) = GF_GET_FOUR ();
  210.   GF_CHECKSUM (*private_postamble) = GF_GET_FOUR ();
  211.  
  212.   /* The resolution values are stored in the file as pixels per point,
  213.      scaled by 2^16.  */
  214.   GF_H_RESOLUTION (*private_postamble) = GF_GET_FOUR ();
  215.   GF_V_RESOLUTION (*private_postamble) = GF_GET_FOUR ();
  216.   
  217.   MIN_COL (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
  218.   MAX_COL (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
  219.   MIN_ROW (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
  220.   MAX_ROW (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
  221.  
  222.   get_locators ();
  223. }
  224.  
  225.  
  226. /* We do not know in advance how many character locators exist, but we do
  227.    place a maximum on it (contrary to what the GF format definition
  228.    says), namely, MAX_CHARCODE.  */
  229.  
  230. static void
  231. get_locators ()
  232. {
  233.   do
  234.     {
  235.       one_byte code;
  236.       one_byte b = GF_GET_BYTE ();
  237.  
  238.       if (b == POST_POST)
  239.     break;
  240.  
  241.       code = GF_GET_BYTE ();
  242.  
  243.       if (b == CHAR_LOC)
  244.     {
  245.       GF_CHAR_LOC (*private_postamble, code).h_escapement
  246.         = scaled_to_real (GF_GET_FOUR ()) + .5;
  247.       (void) GF_GET_FOUR ();  /* Ignore vertical escapement.  */
  248.     }
  249.       else if (b == CHAR_LOC0)
  250.         GF_CHAR_LOC (*private_postamble, code).h_escapement = GF_GET_BYTE ();
  251.       else
  252.         FATAL1 ("Expected a char_loc command, not %u", b);
  253.  
  254.       GF_CHAR_LOC (*private_postamble, code).tfm_width = GF_GET_FOUR ();
  255.       GF_CHAR_LOC (*private_postamble, code).char_pointer = GF_GET_FOUR ();
  256.     }
  257.   while (true);
  258. }
  259.  
  260. /* Unlike `gf_get_next_char' (which comes next), this routine will get any
  261.    character by its code.  It is meant to be called by the user.  We
  262.    save all the characters we read in the static `char_list', to avoid
  263.    going out to the file each time.  */
  264.  
  265. gf_char_type *
  266. gf_get_char (one_byte charcode)
  267. {
  268.   gf_char_locator_type char_locator;
  269.   byte_count_type char_pointer;
  270.  
  271.   if (char_list[charcode] != NULL)
  272.     return char_list[charcode];
  273.  
  274.   (void) gf_get_postamble ();
  275.   assert (private_postamble != NULL);
  276.  
  277.   char_locator = GF_CHAR_LOC (*private_postamble, charcode);
  278.   char_pointer = char_locator.char_pointer;
  279.  
  280.   if (char_pointer != NULL_BYTE_PTR)
  281.     {
  282.       boolean found;
  283.       byte_count_type old_pos = GF_FTELL ();
  284.       GF_FSEEK (char_pointer, SEEK_SET);
  285.  
  286.       char_list[charcode] = xmalloc (sizeof (gf_char_type));
  287.       *(char_list[charcode]) = gf_get_next_char (&found);
  288.       assert (found);
  289.  
  290.       GF_FSEEK (old_pos, SEEK_SET);
  291.     }
  292.  
  293.   return char_list[charcode];
  294. }
  295.  
  296.  
  297. /* This reads the character starting from the current position (but some
  298.    specials might come first).  */
  299.  
  300. gf_char_type
  301. gf_get_next_char (boolean *found)
  302. {
  303.   one_byte c;
  304.   gf_char_type gf_char;
  305.  
  306.   get_specials (GF_FTELL ());
  307.  
  308.   c = GF_GET_BYTE ();
  309.  
  310.   if (c == BOC)
  311.     get_full_boc (&gf_char);
  312.  
  313.   else if (c == BOC1)
  314.     get_abbreviated_boc (&gf_char);
  315.  
  316.   else if (c == POST)
  317.     {
  318.       *found = false;
  319.       return gf_char;        /* We are returning garbage, but that's OK.  */
  320.     }
  321.  
  322.   else
  323.     FATAL1 ("Expected a character (or the postamble), found %u", c);
  324.  
  325.   get_character_bitmap (&gf_char);
  326.   get_postamble_info (&gf_char);
  327.  
  328.   deblank (&gf_char);
  329.  
  330.   *found = true;
  331.   return gf_char;
  332. }
  333.  
  334.  
  335. /* If the back pointer actually points somewhere, this character is a
  336.    ``residue'', and the font is probably too big.  */
  337.  
  338. static void
  339. get_full_boc (gf_char_type *gf_char)
  340. {
  341.   signed_4_bytes back_pointer, charcode;
  342.  
  343.   charcode = GF_GET_SIGNED_FOUR ();
  344.   if (charcode < 0 || charcode > MAX_CHARCODE)
  345.     /* Someone is trying to use a font with character codes that are
  346.        out of our range.  */
  347.     FATAL1 ("Character code %d out of range 0..255 in GF file (sorry)",
  348.             charcode);
  349.  
  350.   GF_CHARCODE (*gf_char) = charcode;
  351.   
  352.   back_pointer = GF_GET_SIGNED_FOUR ();
  353.   if (back_pointer != -1)
  354.     WARNING2 ("Character %u has a non-null back pointer (to %d)", 
  355.               GF_CHARCODE (*gf_char), back_pointer);
  356.  
  357.   GF_CHAR_MIN_COL (*gf_char) = GF_GET_SIGNED_FOUR ();
  358.   GF_CHAR_MAX_COL (*gf_char) = GF_GET_SIGNED_FOUR ();
  359.   GF_CHAR_MIN_ROW (*gf_char) = GF_GET_SIGNED_FOUR ();
  360.   GF_CHAR_MAX_ROW (*gf_char) = GF_GET_SIGNED_FOUR ();
  361. }
  362.  
  363.  
  364. static void
  365. get_abbreviated_boc (gf_char_type *gf_char)
  366. {
  367.   one_byte col_delta, row_delta;
  368.  
  369.   GF_CHARCODE (*gf_char) = GF_GET_BYTE ();
  370.  
  371.   col_delta = GF_GET_BYTE ();
  372.   GF_CHAR_MAX_COL (*gf_char) = GF_GET_BYTE ();
  373.   GF_CHAR_MIN_COL (*gf_char) = GF_CHAR_MAX_COL (*gf_char) - col_delta;
  374.  
  375.   row_delta = GF_GET_BYTE ();
  376.   GF_CHAR_MAX_ROW (*gf_char) = GF_GET_BYTE ();
  377.   GF_CHAR_MIN_ROW (*gf_char) = GF_CHAR_MAX_ROW (*gf_char) - row_delta;
  378. }
  379.  
  380.  
  381. /* We also want to return the horizontal escapement (i.e., set width)
  382.    and the TFM width as part of the character, although this information is
  383.    not part of the boc..eoc, but rather the postamble.  */
  384.  
  385. static void
  386. get_postamble_info (gf_char_type *gf_char)
  387. {
  388.   gf_char_locator_type char_locator;
  389.  
  390.   (void) gf_get_postamble ();    /* Use `private_postamble'.  */
  391.   assert (private_postamble != NULL);
  392.  
  393.   char_locator = GF_CHAR_LOC (*private_postamble, GF_CHARCODE (*gf_char));
  394.  
  395.   GF_H_ESCAPEMENT (*gf_char) = char_locator.h_escapement;
  396.   GF_TFM_WIDTH (*gf_char) = char_locator.tfm_width;
  397. }
  398.  
  399.  
  400. /* The GF format does not guarantee that the bounding box is the
  401.    smallest possible, i.e., that the character bitmap does not have
  402.    blank rows or columns at an edge.  We want to remove such blanks.  */
  403.  
  404. static void
  405. deblank (gf_char_type *gf_char)
  406. {
  407.   boolean all_white;
  408.   bitmap_type gf_bitmap = GF_BITMAP (*gf_char);
  409.   unsigned width = BITMAP_WIDTH (gf_bitmap),
  410.            height = BITMAP_HEIGHT (gf_bitmap);
  411.   unsigned white_on_left = 0, white_on_right = 0,
  412.            white_on_top = 0, white_on_bottom = 0;
  413.   int this_col, this_row; /* int in case GF_CHAR is zero pixels wide.  */
  414.  
  415.   /* Let's start with blank columns at the left-hand side.  */
  416.   all_white = true;
  417.   for (this_col = 0; this_col < width && all_white; this_col++)
  418.     {
  419.       for (this_row = 0; this_row < height && all_white; this_row++)
  420.     {
  421.       if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != 0)
  422.             all_white = false;
  423.     }
  424.       if (all_white)
  425.         white_on_left++;
  426.     }
  427.  
  428.   /* Now let's check the right-hand side.  */
  429.   all_white = true;
  430.   for (this_col = width - 1; this_col >= 0 && all_white; this_col--)
  431.     {
  432.       for (this_row = 0; this_row < height && all_white; this_row++)
  433.     {
  434.       if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != WHITE)
  435.             all_white = false;
  436.     }
  437.       if (all_white)
  438.         white_on_right++;
  439.     }
  440.  
  441.   /* Check for all-white rows on top now.  */
  442.   all_white = true;
  443.   for (this_row = 0; this_row < height && all_white; this_row++)
  444.     {
  445.       for (this_col = 0; this_col < width && all_white; this_col++)
  446.         {
  447.           if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != WHITE)
  448.             all_white = false;
  449.         }
  450.       if (all_white)
  451.         white_on_top++;
  452.     }
  453.  
  454.   /* And, last, for all-white rows on the bottom.  */
  455.   all_white = true;
  456.   for (this_row = height - 1; this_row >= 0 && all_white; this_row--)
  457.     {
  458.       for (this_col = 0; this_col < width && all_white; this_col++)
  459.         {
  460.           if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != WHITE)
  461.             all_white = false;
  462.         }
  463.       if (all_white)
  464.         white_on_bottom++;
  465.     }
  466.  
  467.   /* If we have to remove columns at either the left or the right, we
  468.      have to reallocate the memory, since much code depends on the fact
  469.      that the bitmap is in contiguous memory.  If we have to remove
  470.      rows, we don't necessarily have to reallocate the memory, but we
  471.      might as well, to save space.  */
  472.   if (white_on_left > 0 || white_on_right > 0
  473.       || white_on_top > 0 || white_on_bottom > 0)
  474.     {
  475.       bitmap_type condensed;
  476.       
  477.       if (white_on_left + white_on_right > width)
  478.         { /* The character was entirely blank.  */
  479.           BITMAP_WIDTH (condensed) = BITMAP_HEIGHT (condensed) = 0;
  480.           GF_CHAR_MIN_COL (*gf_char) = GF_CHAR_MAX_COL (*gf_char)
  481.             = GF_CHAR_MIN_ROW (*gf_char) = GF_CHAR_MAX_ROW (*gf_char) = 0;
  482.           BITMAP_BITS (condensed) = NULL;
  483.         }
  484.       else
  485.         {
  486.           dimensions_type d;
  487.           DIMENSIONS_HEIGHT (d) = height - white_on_top - white_on_bottom;
  488.           DIMENSIONS_WIDTH (d) = width - white_on_left - white_on_right;
  489.           condensed = new_bitmap (d);
  490.  
  491.           for (this_row = 0; this_row < BITMAP_HEIGHT (condensed); this_row++)
  492.             for (this_col = 0; this_col < BITMAP_WIDTH (condensed); this_col++)
  493.               {
  494.             BITMAP_PIXEL (condensed, this_row, this_col)
  495.                   = BITMAP_PIXEL (gf_bitmap, this_row + white_on_top,
  496.                                              this_col + white_on_left);
  497.           }
  498.           GF_CHAR_MIN_ROW (*gf_char) += white_on_bottom;
  499.           GF_CHAR_MAX_ROW (*gf_char) -= white_on_top;
  500.           GF_CHAR_MIN_COL (*gf_char) += white_on_left;
  501.           GF_CHAR_MAX_COL (*gf_char) -= white_on_right;
  502.     }
  503.  
  504.       free_bitmap (&GF_BITMAP (*gf_char));
  505.       GF_BITMAP (*gf_char) = condensed;
  506.     }
  507. }
  508.  
  509.  
  510. /* The ``bitmap'' is a sequence of commands that describe it in terms of
  511.    run-length encoding.
  512.  
  513.    GF's row and column numbers are the lower left corner of a pixel. 
  514.    GF (0,0) is the Cartesian unit square: 0 <= x (col) <= 1,
  515.    0 <= y (row) <= 1.  Yes, it's <=, not <.  What does this mean for
  516.    the maxes and mins?  Let's take the height first:  if a character has
  517.    min_row = 0 and max_row = 10, we start the ``current'' y at 10,
  518.    (possibly) paint some pixels on that row, ..., and end up with it at
  519.    zero, (possibly) painting some pixels on that row.  Thus, there are
  520.    11 (10 - 0 + 1) rows in which we might paint pixels.  Now the width:
  521.    if a character has min_row = 0 and max_row = 4, the current x starts
  522.    at zero, we paint four pixels (let's say), and now the current x is
  523.    four (the max possible), so we cannot paint any more.  Thus there are
  524.    four (4 - 0) columns in which we might paint pixels. 
  525.    
  526.    Weird, huh?  */
  527.  
  528. static void
  529. get_character_bitmap (gf_char_type *gf_char)
  530. {
  531.   /* We expect these to be >= 0, but if the GF file is improper, they
  532.      might turn to be negative.  */
  533.   int height, width;
  534.   dimensions_type matrix_dimensions;
  535.   coordinate_type current;    /* This will be the GF position.  */
  536.   boolean painting_black = false;
  537.  
  538.   current.x = GF_CHAR_MIN_COL (*gf_char);
  539.   current.y = GF_CHAR_MAX_ROW (*gf_char);
  540.  
  541.   width = GF_CHAR_MAX_COL (*gf_char) - GF_CHAR_MIN_COL (*gf_char);
  542.   height = GF_CHAR_MAX_ROW (*gf_char) - GF_CHAR_MIN_ROW (*gf_char) + 1;
  543.  
  544.   /* If the character has zero or negative extent in either dimension,
  545.      it's not going to have a bitmap.  (If this happens, the GF file is
  546.      incorrect; but the discrepancy isn't serious, so we may as well not
  547.      bomb out when it happens, especially since PKtoGF has a bug that
  548.      produces such a bounding box when the character is all blank.)  */
  549.   if (width <= 0 || height <= 0)
  550.     {
  551.       one_byte b;
  552.       BITMAP_HEIGHT (GF_BITMAP (*gf_char))
  553.         = BITMAP_WIDTH (GF_BITMAP (*gf_char))
  554.         = 0;
  555.       BITMAP_BITS (GF_BITMAP (*gf_char)) = NULL;
  556.       
  557.       /* The next non-NO_OP byte should be EOC.  */
  558.       while ((b = GF_GET_BYTE ()) == NO_OP)
  559.         /* do nothing */ ;
  560.       if (b != EOC)
  561.         FATAL1 ("Expected eoc (for a blank character), found %u", b);
  562.  
  563.       return;
  564.     }
  565.   
  566.   DIMENSIONS_HEIGHT (matrix_dimensions) = height;
  567.   DIMENSIONS_WIDTH (matrix_dimensions) = width;
  568.   GF_BITMAP (*gf_char) = new_bitmap (matrix_dimensions);
  569.  
  570.   do
  571.     {
  572.       one_byte c = GF_GET_BYTE ();
  573.  
  574.       if (c == EOC)
  575.     break;
  576.  
  577.       /* No need to test if `PAINT_0 <= c'; it must be, since PAINT_0 is
  578.          zero and `c' is unsigned.  */
  579.       if (/* PAINT_0 <= c && */ c <= PAINT3)
  580.         get_paint (¤t, &painting_black, c, gf_char);
  581.  
  582.       else if (SKIP0 <= c && c <= SKIP3)
  583.         get_skip (¤t, &painting_black, c, gf_char);
  584.  
  585.       else if (NEW_ROW_0 <= c && c <= NEW_ROW_164)
  586.         get_new_row (¤t, &painting_black, c, gf_char);
  587.  
  588.       else if (c == NO_OP)
  589.         /* do nothing */ ;
  590.  
  591.       else if ((XXX1 <= c && c <= XXX4) || c == YYY)
  592.         get_specials (GF_FTELL ());
  593.  
  594.       else
  595.         FATAL1 ("Expected paint or skip or new_row, found %u", c);
  596.     }
  597.   while (true);
  598.  
  599.   if (tracing_gf_input)
  600.     puts ("");
  601. }
  602.  
  603.  
  604. /* The paint commands come in two varieties -- either with the length
  605.    implicitly part of the command, or where it is specified as a separate
  606.    parameter.  */
  607.  
  608. static void
  609. get_paint (coordinate_type *current, boolean *painting_black,
  610.            one_byte command, gf_char_type *gf_char)
  611. {
  612.   unsigned length;
  613.  
  614.   /* No need to test if `PAINT_0 <= command'; it must be, since PAINT_0 is
  615.      zero and `command' is unsigned.  */
  616.   if (/* PAINT_0 <= command && */ command <= PAINT_63)
  617.     length = command - PAINT_0;
  618.   else
  619.     {
  620.       switch (command)
  621.     {
  622.     case PAINT1:
  623.       length = GF_GET_BYTE ();
  624.       break;
  625.  
  626.     case PAINT2:
  627.       length = GF_GET_TWO ();
  628.       break;
  629.  
  630.     case PAINT3:
  631.       length = gf_get_three ();
  632.       break;
  633.  
  634.     default:
  635.       FATAL1 ("Expected a paint command, found %u", command);
  636.     }
  637.     }
  638.  
  639.   /* We have to translate from Cartesian to C coordinates.  That means the
  640.      x's are the same, but the y's are flipped.  */
  641.   if (*painting_black)
  642.     {
  643.       unsigned matrix_y = GF_CHAR_MAX_ROW (*gf_char) - current->y;
  644.  
  645.       if (tracing_gf_input)
  646.         printf ("%u", length);
  647.  
  648.       for (; length != 0; length--)
  649.     {
  650.       unsigned matrix_x = current->x - GF_CHAR_MIN_COL (*gf_char);
  651.  
  652.       BITMAP_PIXEL (GF_BITMAP (*gf_char), matrix_y, matrix_x) = 1;
  653.  
  654.       current->x++;
  655.     }
  656.     }
  657.   else
  658.     {
  659.       current->x += length;
  660.  
  661.       if (tracing_gf_input)
  662.         printf ("(%u)", length);
  663.     }
  664.   *painting_black = !*painting_black;
  665. }
  666.  
  667.  
  668. /* Skip commands move down in the GF character, leaving blank rows.  */
  669.  
  670. static void
  671. get_skip (coordinate_type * current, boolean * painting_black,
  672.           one_byte command, gf_char_type *gf_char)
  673. {
  674.   unsigned rows_to_skip;
  675.  
  676.   switch (command)
  677.     {
  678.     case SKIP0:
  679.       rows_to_skip = 0;
  680.       break;
  681.  
  682.     case SKIP1:
  683.       rows_to_skip = GF_GET_BYTE ();
  684.       break;
  685.  
  686.     case SKIP2:
  687.       rows_to_skip = GF_GET_TWO ();
  688.       break;
  689.  
  690.     case SKIP3:
  691.       rows_to_skip = gf_get_three ();
  692.       break;
  693.  
  694.     default:
  695.       FATAL1 ("Expected skip command, found %u", command);
  696.     }
  697.  
  698.   current->y -= rows_to_skip + 1;
  699.   current->x = GF_CHAR_MIN_COL (*gf_char);
  700.   *painting_black = false;
  701.  
  702.   if (tracing_gf_input)
  703.     printf ("\nskip %u (y now %d) ", rows_to_skip + 1, current->y);
  704. }
  705.  
  706.  
  707. /* `new_row' commands move to the next line down and then over.  */
  708.  
  709. static void
  710. get_new_row (coordinate_type *current, boolean *painting_black,
  711.          one_byte command, gf_char_type *gf_char)
  712. {
  713.   current->y--;
  714.   current->x = GF_CHAR_MIN_COL (*gf_char) + command - NEW_ROW_0;
  715.   *painting_black = true;
  716.  
  717.   if (tracing_gf_input)
  718.     printf ("\nnew_row %u (x,y now %d,%d) ", command - NEW_ROW_0,
  719.             current->x, current->y);
  720. }
  721.  
  722. /* Instead of building a bitmap, this routine just reads the bytes that
  723.    define the character CHARCODE.  If the character doesn't exist, we
  724.    return NULL.  */
  725.  
  726. /* Append the byte `b' to the buffer in `raw_char', followed by (if
  727.    WITH_SIZE_P is true) SIZE, followed SIZE bytes of the input.  */
  728. #define COMMON_APPEND(size, with_size_p)                \
  729.   do                                    \
  730.     {                                    \
  731.       append_byte (raw_char, b);                    \
  732.       if (with_size_p) append_byte (raw_char, size);            \
  733.       if (size > 0) append_n_bytes (raw_char, size, get_n_bytes (size,    \
  734.                                     gf_input_file, gf_input_filename));    \
  735.     }                                    \
  736.   while (0)
  737.  
  738. #define APPEND_BYTES(n) COMMON_APPEND (n, false)
  739. #define APPEND_VAR_BYTES(n) COMMON_APPEND (n, true)
  740.  
  741. raw_char_type *
  742. gf_get_raw_char (one_byte charcode)
  743. {
  744.   one_byte b; /* Command byte we've just read.  */
  745.   gf_char_locator_type char_locator;
  746.   byte_count_type char_pointer;
  747.   byte_count_type old_pos;
  748.   raw_char_type *raw_char;
  749.  
  750.   (void) gf_get_postamble ();
  751.   assert (private_postamble != NULL);
  752.   
  753.   char_locator = GF_CHAR_LOC (*private_postamble, charcode);
  754.   char_pointer = char_locator.char_pointer;
  755.  
  756.   /* If the character doesn't exist in the font, we're done.  */
  757.   if (char_pointer == NULL_BYTE_PTR)
  758.     return NULL;
  759.   
  760.   /* Save where we are in the file; we'll restore it when we're done.  */
  761.   old_pos = GF_FTELL ();
  762.   GF_FSEEK (char_pointer, SEEK_SET);
  763.   
  764.   raw_char = xmalloc (sizeof (raw_char_type));
  765.   *raw_char = new_raw_gf_char (char_locator);
  766.  
  767.   /* Unfortunately, the GF format doesn't tell us how many bytes long
  768.      the character description is.  So, we must decode it enough to
  769.      figure out how much to read.  */
  770.   
  771.   /* The first step is the boc: it might be either the one-byte or
  772.      four-byte variant.  */
  773.   b = GF_GET_BYTE ();
  774.   if (b == BOC)
  775.     /* The character code, the backpointer (which will probably be wrong
  776.        in the new file, if it exists, but we don't handle non-null
  777.        backpointers anyway), the bounding box.  */
  778.     APPEND_BYTES (24);
  779.   else /* b == BOC1 */
  780.     APPEND_BYTES (5);
  781.   
  782.   /* Read the character definition; exit when we get to EOC.  */
  783.   while ((b = GF_GET_BYTE ()) != EOC)
  784.     {
  785.       /* First test all the commands that have no parameters. No need to
  786.          test if `PAINT_0 <= b'; it must be, since PAINT_0 is zero and
  787.          `b' is unsigned.  */
  788.       if ((/* PAINT_0 <= b && */ b <= PAINT_63)
  789.           || b == SKIP0
  790.           || (NEW_ROW_0 <= b && b <= NEW_ROW_164))
  791.         APPEND_BYTES (0);
  792.       
  793.       /* Now the ones with a one-byte parameter.  */
  794.       else if (b == PAINT1 || b == SKIP1)
  795.         APPEND_BYTES (1);
  796.       
  797.       /* A two-byte parameter.  */
  798.       else if (b == PAINT2 || b == SKIP2)
  799.         APPEND_BYTES (2);
  800.       
  801.       /* Three-byte.  */
  802.       else if (b == PAINT3 || b == SKIP3)
  803.         APPEND_BYTES (3);
  804.       
  805.       /* Four.  */
  806.       else if (b == YYY)
  807.         APPEND_BYTES (4);
  808.       
  809.       /* Commands with a variable-size parameter.  */
  810.       else if (b == XXX1)
  811.         {
  812.           one_byte size = GF_GET_BYTE ();
  813.           APPEND_VAR_BYTES (size);
  814.         }
  815.       
  816.       else if (b == XXX2)
  817.         {
  818.           two_bytes size = GF_GET_TWO ();
  819.           APPEND_VAR_BYTES (size);
  820.         }
  821.       
  822.       else if (b == XXX3)
  823.         {
  824.           four_bytes size = gf_get_three ();
  825.           APPEND_VAR_BYTES (size);
  826.         }
  827.       
  828.       else if (b == XXX4)
  829.         {
  830.           four_bytes size = GF_GET_FOUR ();
  831.           APPEND_VAR_BYTES (size);
  832.         }
  833.   
  834.       else if (b == NO_OP)
  835.         /* do nothing */;
  836.       
  837.       else
  838.         FATAL1 ("gf_get_raw_char: Bad command byte %u", b);
  839.     }
  840.  
  841.   /* This appends the `eoc'---and now we're done.  */
  842.   APPEND_BYTES (0);
  843.  
  844.   GF_FSEEK (old_pos, SEEK_SET);
  845.   return raw_char;
  846. }
  847.  
  848.  
  849. /* This macro makes sure the raw character RGC has at least NEEDED
  850.    bytes free.  */
  851. #define ENSURE_AVAILABLE(rgc, needed)                    \
  852.   while (RAW_CHAR_ALLOCATED (rgc) - RAW_CHAR_USED (rgc) < needed)    \
  853.     {                                    \
  854.       RAW_CHAR_ALLOCATED (rgc) *= 2;                    \
  855.       RAW_CHAR_BYTES (rgc)                        \
  856.         = xrealloc (RAW_CHAR_BYTES (rgc), RAW_CHAR_ALLOCATED (rgc));    \
  857.     }
  858.  
  859.  
  860. /* Append the byte B to the end of the RAW_CHAR's buffer.  */
  861.  
  862. static void
  863. append_byte (raw_char_type *raw_char, one_byte b)
  864. {
  865.   ENSURE_AVAILABLE (*raw_char, 1);
  866.   RAW_CHAR_UNUSED_START (*raw_char) = b;
  867.   RAW_CHAR_USED (*raw_char)++;
  868. }
  869.  
  870.  
  871. /* Append the N bytes of data pointed to by DATA to the end of
  872.    RAW_CHAR's buffer.  Free DATA after copying.  */
  873.  
  874. static void
  875. append_n_bytes (raw_char_type *raw_char, four_bytes n, one_byte *data)
  876. {
  877.   ENSURE_AVAILABLE (*raw_char, n);
  878.   memcpy (&RAW_CHAR_UNUSED_START (*raw_char), data, n);
  879.   RAW_CHAR_USED (*raw_char) += n;
  880.   free (data);
  881. }
  882.  
  883.  
  884. /* Make a new raw character.  We have to start off the buffer with some
  885.    nonempty amount of memory, so that the reallocation will have
  886.    something to double.  */
  887.  
  888. static raw_char_type
  889. new_raw_gf_char (gf_char_locator_type locator)
  890. {
  891.   raw_char_type c;
  892.   
  893.   RAW_CHAR_ALLOCATED (c) = 1;
  894.   RAW_CHAR_BYTES (c) = xmalloc (RAW_CHAR_ALLOCATED (c));
  895.   RAW_CHAR_USED (c) = 0;
  896.   
  897.   GF_CHARCODE (c) = locator.charcode;
  898.   GF_H_ESCAPEMENT (c) = locator.h_escapement;
  899.   GF_TFM_WIDTH (c) = locator.tfm_width;
  900.   GF_CHAR_BB (c) = GF_FONT_BB (*private_postamble);
  901.   
  902.   /* Since we don't want to interpret the bounding box information in
  903.      the character, we just make our bounding box be the font bounding
  904.      box.  Since the only thing a raw character is good for is being
  905.      immediately written back out, this doesn't hurt.  (The actual
  906.      bounding box information in the character isn't lost.)  */
  907.   return c;
  908. }
  909.  
  910. /* Read all specials beginning from the given location, leaving the file
  911.    pointer at the first non-special.  We do not save the specials,
  912.    though.  */
  913.  
  914. static void
  915. get_specials (byte_count_type special_ptr)
  916. {
  917.   boolean found_special = true;
  918.  
  919.   GF_FSEEK (special_ptr, SEEK_SET);
  920.  
  921.   do
  922.     {
  923.       one_byte c = GF_GET_BYTE ();
  924.  
  925.       switch (c)
  926.     {
  927.     case XXX1:
  928.       (void) gf_get_string (GF_GET_BYTE ());
  929.       break;
  930.  
  931.     case XXX2:
  932.       (void) gf_get_string (GF_GET_TWO ());
  933.       break;
  934.  
  935.     case XXX3:
  936.       (void) gf_get_string (gf_get_three ());
  937.       break;
  938.  
  939.     case YYY:
  940.       (void) GF_GET_FOUR ();
  941.       break;
  942.  
  943.     default:
  944.       found_special = false;
  945.       GF_FSEEK (-1, SEEK_CUR);
  946.     }
  947.     }
  948.   while (found_special);
  949. }
  950.  
  951.  
  952. static string
  953. gf_get_string (unsigned length)
  954. {
  955.   string s;
  956.  
  957.   if (length == 0) return "";
  958.  
  959.   s = get_n_bytes (length, gf_input_file, gf_input_filename);
  960.   s = xrealloc (s, length + 1);
  961.   s[length] = 0;
  962.   return s;
  963. }
  964.  
  965.  
  966. /* C does not provide an obvious type for a 24-bit quantity, so we
  967.    return a 32-bit one.  */
  968.  
  969. static four_bytes
  970. gf_get_three ()
  971. {
  972.   four_bytes v = get_two (gf_input_file, gf_input_filename) << 8;
  973.   v |= get_byte (gf_input_file, gf_input_filename);
  974.  
  975.   return v;
  976. }
  977.