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 / bzrto / char.c < prev    next >
C/C++ Source or Header  |  1992-10-19  |  7KB  |  252 lines

  1. /* char.c: manipulate a TFM and BZR character simultaneously.
  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 "bzr.h"
  22. #include "spline.h"
  23. #include "tfm.h"
  24.  
  25. #include "char.h"
  26.  
  27. #include "ccc.h"
  28.  
  29.  
  30. /* Angle from the vertical by which to slant the shapes, in radians.
  31.    (-oblique-angle)  */
  32. real oblique_angle = 0.0;
  33.  
  34.  
  35. static void scale_splines (spline_list_array_type *shape, real scale_factor);
  36. static real_coordinate_type scale_point (real_coordinate_type, real);
  37. static real_coordinate_type slant_point (real_coordinate_type);
  38. static unsigned update_subrs
  39.   (char_type *[], charcode_type, ccc_type *[], bzr_char_type *[]);
  40.  
  41. /* Scale the information in C by SCALE_FACTOR.  */
  42.  
  43. void
  44. scale_char (bzr_char_type *c, real scale_factor)
  45. {
  46.   if (scale_factor == 1)
  47.     return;
  48.  
  49.   CHAR_SET_WIDTH (*c) *= scale_factor;
  50.   CHAR_MIN_COL(*c) *= scale_factor;
  51.   CHAR_MAX_COL(*c) *= scale_factor;
  52.   CHAR_MIN_ROW(*c) *= scale_factor;
  53.   CHAR_MAX_ROW(*c) *= scale_factor;
  54.  
  55.   scale_splines (&BZR_SHAPE (*c), scale_factor);
  56. }
  57.  
  58.  
  59. /* Scale all the coordinates in each spline in the list.  */
  60.  
  61. static void
  62. scale_splines (spline_list_array_type *shape, real scale_factor)
  63. {
  64.   unsigned this_list;
  65.  
  66.   for (this_list = 0; this_list < SPLINE_LIST_ARRAY_LENGTH (*shape);
  67.        this_list++)
  68.     {
  69.       unsigned this_spline;
  70.       spline_list_type list = SPLINE_LIST_ARRAY_ELT (*shape, this_list);
  71.  
  72.       for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH (list);
  73.            this_spline++)
  74.         {
  75.           spline_type s = SPLINE_LIST_ELT (list, this_spline);
  76.  
  77.           START_POINT (s) = scale_point (START_POINT (s), scale_factor);
  78.           END_POINT (s) = scale_point (END_POINT (s), scale_factor);
  79.           
  80.           if (SPLINE_DEGREE (s) == CUBIC)
  81.             {
  82.               CONTROL1 (s) = scale_point (CONTROL1 (s), scale_factor);
  83.               CONTROL2 (s) = scale_point (CONTROL2 (s), scale_factor);
  84.             }
  85.     
  86.       SPLINE_LIST_ELT (list, this_spline) = s;
  87.         }
  88.     }
  89. }
  90.  
  91.  
  92. /* Scale the single point P.  */
  93.  
  94. static real_coordinate_type
  95. scale_point (real_coordinate_type p, real scale_factor)
  96. {
  97.   real_coordinate_type scaled_p;
  98.   
  99.   scaled_p.y = p.y * scale_factor;
  100.   scaled_p.x = p.x * scale_factor;
  101.   
  102.   return scaled_p;
  103. }
  104.  
  105. /* Merge CCC_CHARS and BZR_CHARS between STARTING_CHAR and ENDING_CHAR,
  106.    with the latter taking precedence.  For each element in CCC_CHARS we use
  107.    also incorporate any other characters it needs.  Return the resulting
  108.    array of structures, and the number of subroutines found in SUBR_COUNT.  */
  109.    
  110. char_type **
  111. subr_chars (bzr_char_type *bzr_chars[], ccc_type *ccc_chars[],
  112.             charcode_type starting_char, charcode_type ending_char,
  113.             unsigned *subr_count)
  114. {
  115.   unsigned code;
  116.   char_type **subrs = XTALLOC (MAX_CHARCODE + 1, char_type *);
  117.   
  118.   *subr_count = 0;
  119.   for (code = 0; code <= MAX_CHARCODE; code++)
  120.     subrs[code] = NULL;
  121.  
  122.   for (code = starting_char; code <= ending_char; code++)
  123.     {
  124.       if (ccc_chars[code])
  125.         *subr_count += update_subrs (subrs, code, ccc_chars, bzr_chars);
  126.     }
  127.  
  128.   return subrs;
  129. }
  130.  
  131.  
  132. /* Update in SUBRS all the characters in CCC_CHARS and BZR_CHARS that
  133.    are used as subroutines in CCC_CHARS[CODE].  Prefer entries in
  134.    BZR_CHARS to ones in CCC_CHARS, if both exist.  We assume
  135.    CCC_CHARS[CODE] is not null.  */
  136.  
  137. static unsigned
  138. update_subrs (char_type *subrs[], charcode_type code,
  139.               ccc_type *ccc_chars[], bzr_char_type *bzr_chars[])
  140. {
  141.   unsigned this_cmd;
  142.   ccc_type c = *ccc_chars[code];
  143.   unsigned subr_count = 0;
  144.  
  145.   for (this_cmd = 0; this_cmd < LIST_SIZE (c); this_cmd++)
  146.     { 
  147.       ccc_cmd_type cmd = *(ccc_cmd_type *) LIST_ELT (c, this_cmd);
  148.       
  149.       switch (CCC_OPCODE (cmd))
  150.         {
  151.         case TR_SETCHAR:
  152.         case TR_SETCHARBB:
  153.           {
  154.             char_type *new_char = XTALLOC1 (char_type);
  155.             charcode_type subr_code = CCC_CHARCODE (cmd);
  156.             
  157.             /* If we already needed this character, keep going.  */
  158.             if (subrs[subr_code])
  159.               continue;
  160.             
  161.             /* Prefer the BZR definition to the CCC if we have both.  */
  162.             if (bzr_chars[subr_code])
  163.               {
  164.                 CHAR_CLASS (*new_char) = bzr_char_class;
  165.                 CHAR_BZR (*new_char) = bzr_chars[subr_code];
  166.                 subrs[subr_code] = new_char;
  167.                 subr_count++;
  168.               }
  169.             else if (ccc_chars[subr_code])
  170.               {
  171.                 CHAR_CLASS (*new_char) = ccc_char_class;
  172.                 CHAR_CCC (*new_char) = ccc_chars[subr_code];
  173.                 subrs[subr_code] = new_char;
  174.                 subr_count++;
  175.                 
  176.                 /* This CCC char might need more subroutines, so recurse.  */
  177.                 subr_count
  178.                   += update_subrs (subrs, subr_code, ccc_chars, bzr_chars);
  179.               }
  180.             else
  181.               WARNING2 ("Char %d used by CCC char %d, but undefined",
  182.                         subr_code, code);
  183.           }
  184.           break;
  185.  
  186.         case TR_HMOVE:
  187.         case TR_VMOVE:
  188.           break;
  189.  
  190.         default:
  191.           FATAL2 ("Bad CCC command %d in char %d", CCC_OPCODE (cmd), code);
  192.     }
  193.     }
  194.   
  195.   return subr_count;
  196. }
  197.  
  198. /* Transform all the coordinates in each spline in the list.  */
  199.  
  200. spline_list_array_type
  201. oblique_splines (spline_list_array_type shape)
  202. {
  203.   unsigned this_list;
  204.   spline_list_array_type answer = new_spline_list_array ();
  205.  
  206.   if (oblique_angle == 0.0) return shape;
  207.   
  208.   for (this_list = 0; this_list < SPLINE_LIST_ARRAY_LENGTH (shape);
  209.        this_list++)
  210.     {
  211.       unsigned this_spline;
  212.       spline_list_type list = SPLINE_LIST_ARRAY_ELT (shape, this_list);
  213.       spline_list_type *new = new_spline_list ();
  214.  
  215.       for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH (list);
  216.            this_spline++)
  217.         {
  218.           spline_type s = SPLINE_LIST_ELT (list, this_spline);
  219.  
  220.           START_POINT (s) = slant_point (START_POINT (s));
  221.           END_POINT (s) = slant_point (END_POINT (s));
  222.           
  223.           if (SPLINE_DEGREE (s) == CUBIC)
  224.             {
  225.               CONTROL1 (s) = slant_point (CONTROL1 (s));
  226.               CONTROL2 (s) = slant_point (CONTROL2 (s));
  227.             }
  228.  
  229.           append_spline (new, s);
  230.         }
  231.       
  232.       append_spline_list (&answer, *new);
  233.     }
  234.   free_spline_list_array (&shape);
  235.  
  236.   return answer;
  237. }
  238.  
  239.  
  240. /* Slant the single point P.  This is just trigonometry.  */
  241.  
  242. static real_coordinate_type
  243. slant_point (real_coordinate_type p)
  244. {
  245.   real_coordinate_type slanted_p;
  246.   
  247.   slanted_p.y = p.y;
  248.   slanted_p.x = p.x + tan (oblique_angle) * p.y;
  249.   
  250.   return slanted_p;
  251. }
  252.