home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / groff-1.09-src.lha / src / amiga / groff-1.09 / libdriver / printer.cc < prev   
C/C++ Source or Header  |  1993-06-10  |  6KB  |  241 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.com)
  4.  
  5. This file is part of groff.
  6.  
  7. groff is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 2, or (at your option) any later
  10. version.
  11.  
  12. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with groff; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include "driver.h"
  22.  
  23. printer *pr = 0;
  24.  
  25. font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
  26. : p(f), next(fp)
  27. {
  28. }
  29.  
  30. printer::printer()
  31. : font_table(0), nfonts(0), font_list(0)
  32. {
  33. }
  34.  
  35. printer::~printer()
  36. {
  37.   a_delete font_table;
  38.   while (font_list) {
  39.     font_pointer_list *tem = font_list;
  40.     font_list = font_list->next;
  41.     delete tem->p;
  42.     delete tem;
  43.   }
  44.   if (ferror(stdout) || fflush(stdout) < 0)
  45.     fatal("output error");
  46. }
  47.  
  48. void printer::load_font(int n, const char *nm)
  49. {
  50.   assert(n >= 0);
  51.   if (n >= nfonts) {
  52.     if (nfonts == 0) {
  53.       nfonts = 10;
  54.       if (nfonts <= n)
  55.     nfonts = n + 1;
  56.       font_table = new font *[nfonts];
  57.       for (int i = 0; i < nfonts; i++)
  58.     font_table[i] = 0;
  59.     }
  60.     else {
  61.       font **old_font_table = font_table;
  62.       int old_nfonts = nfonts;
  63.       nfonts *= 2;
  64.       if (n >= nfonts)
  65.     nfonts = n + 1;
  66.       font_table = new font *[nfonts];
  67.       for (int i = 0; i < old_nfonts; i++)
  68.     font_table[i] = old_font_table[i];
  69.       for (i = old_nfonts; i < nfonts; i++)
  70.     font_table[i] = 0;
  71.       a_delete old_font_table;
  72.     }
  73.   }
  74.   font *f = find_font(nm);
  75.   font_table[n] = f;
  76. }
  77.  
  78. font *printer::find_font(const char *nm)
  79. {
  80.   for (font_pointer_list *p = font_list; p; p = p->next)
  81.     if (strcmp(p->p->get_name(), nm) == 0)
  82.       return p->p;
  83.   font *f = make_font(nm);
  84.   if (!f)
  85.     fatal("sorry, I can't continue");
  86.   font_list = new font_pointer_list(f, font_list);
  87.   return f;
  88. }
  89.  
  90. font *printer::make_font(const char *nm)
  91. {
  92.   return font::load_font(nm);
  93. }
  94.  
  95. void printer::end_of_line()
  96. {
  97. }
  98.  
  99. void printer::special(char *, const environment *)
  100. {
  101. }
  102.  
  103. void printer::draw(int, int *, int, const environment *)
  104. {
  105. }
  106.  
  107. void printer::set_ascii_char(unsigned char c, const environment *env, 
  108.                  int *widthp)
  109. {
  110.   char buf[2];
  111.   buf[0] = c;
  112.   buf[1] = '\0';
  113.   set_special_char(buf, env, widthp);
  114. }
  115.  
  116. void printer::set_special_char(const char *nm, const environment *env,
  117.                   int *widthp)
  118. {
  119.   int i = font::name_to_index(nm);
  120.   int fn = env->fontno;
  121.   if (fn < 0 || fn >= nfonts) {
  122.     error("bad font position `%1'", fn);
  123.     return;
  124.   }
  125.   font *f = font_table[fn];
  126.   if (f == 0) {
  127.     error("no font mounted at `%1'", fn);
  128.     return;
  129.   }
  130.   if (!f->contains(i)) {
  131.     if (nm[0] != '\0' && nm[1] == '\0')
  132.       error("font `%1' does not contain ascii character `%2'",
  133.         f->get_name(),
  134.         nm[0]);
  135.     else
  136.       error("font `%1' does not contain special character `%2'",
  137.         f->get_name(),
  138.         nm);
  139.     return;
  140.   }
  141.   int w = f->get_width(i, env->size);
  142.   if (widthp)
  143.     *widthp = w;
  144.   set_char(i, f, env, w);
  145. }
  146.  
  147. void printer::set_numbered_char(int num, const environment *env, int *widthp)
  148. {
  149.   int i = font::number_to_index(num);
  150.   int fn = env->fontno;
  151.   if (fn < 0 || fn >= nfonts) {
  152.     error("bad font position `%1'", fn);
  153.     return;
  154.   }
  155.   font *f = font_table[fn];
  156.   if (f == 0) {
  157.     error("no font mounted at `%1'", fn);
  158.     return;
  159.   }
  160.   if (!f->contains(i)) {
  161.     error("font `%1' does not contain numbered character %2",
  162.       f->get_name(),
  163.       num);
  164.     return;
  165.   }
  166.   int w = f->get_width(i, env->size);
  167.   if (widthp)
  168.     *widthp = w;
  169.   set_char(i, f, env, w);
  170. }
  171.  
  172. // This utility function adjusts the specified center of the
  173. // arc so that it is equidistant between the specified start
  174. // and end points. (p[0], p[1]) is a vector from the current
  175. // point to the center; (p[2], p[3]) is a vector from the 
  176. // center to the end point.  If the center can be adjusted,
  177. // a vector from the current point to the adjusted center is
  178. // stored in c[0], c[1] and 1 is returned.  Otherwise 0 is
  179. // returned.
  180.  
  181. #if 1
  182. int printer::adjust_arc_center(const int *p, double *c)
  183. {
  184.   // We move the center along a line parallel to the line between
  185.   // the specified start point and end point so that the center
  186.   // is equidistant between the start and end point.
  187.   // It can be proved (using Lagrange multipliers) that this will
  188.   // give the point nearest to the specified center that is equidistant
  189.   // between the start and end point.
  190.  
  191.   double x = p[0] + p[2];    // (x, y) is the end point
  192.   double y = p[1] + p[3];
  193.   double n = x*x + y*y;
  194.   if (n != 0) {
  195.     c[0]= double(p[0]);
  196.     c[1] = double(p[1]);
  197.     double k = .5 - (c[0]*x + c[1]*y)/n;
  198.     c[0] += k*x;
  199.     c[1] += k*y;
  200.     return 1;
  201.   }
  202.   else
  203.     return 0;
  204. }
  205. #else
  206. int printer::adjust_arc_center(const int *p, double *c)
  207. {
  208.   int x = p[0] + p[2];    // (x, y) is the end point
  209.   int y = p[1] + p[3];
  210.   // Start at the current point; go in the direction of the specified
  211.   // center point until we reach a point that is equidistant between
  212.   // the specified starting point and the specified end point. Place
  213.   // the center of the arc there.
  214.   double n = p[0]*double(x) + p[1]*double(y);
  215.   if (n > 0) {
  216.     double k = (double(x)*x + double(y)*y)/(2.0*n);
  217.     // (cx, cy) is our chosen center
  218.     c[0] = k*p[0];
  219.     c[1] = k*p[1];
  220.     return 1;
  221.   }
  222.   else {
  223.     // We would never reach such a point.  So instead start at the
  224.     // specified end point of the arc.  Go towards the specified
  225.     // center point until we reach a point that is equidistant between
  226.     // the specified start point and specified end point. Place
  227.     // the center of the arc there.
  228.     n = p[2]*double(x) + p[3]*double(y);
  229.     if (n > 0) {
  230.       double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
  231.       // (c[0], c[1]) is our chosen center
  232.       c[0] = p[0] + k*p[2];
  233.       c[1] = p[1] + k*p[3];
  234.       return 1;
  235.     }
  236.     else
  237.       return 0;
  238.   }
  239. }  
  240. #endif
  241.