home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / printing / ghostscrip / source / specific / c / gdevbgi < prev    next >
Encoding:
Text File  |  1991-10-25  |  11.4 KB  |  411 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gdevbgi.c */
  21. /* Ghostscript driver for Borland Graphics Interface (BGI) */
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <conio.h>
  25. #include <graphics.h>
  26. #include "gx.h"
  27. #include "gsmatrix.h"            /* for gxdevice.h */
  28. #include "gxbitmap.h"
  29. #include "gxdevice.h"
  30.  
  31. /*
  32.  * BGI supports these video cards:
  33.  *   Hercules, CGA, MCGA, EGA, VGA, AT&T 400, IBM 8514, PC3270.
  34.  * Highest resolution mode is used with all these video cards.
  35.  * EGA and VGA display 16 colors, the rest are black-and-white only.
  36.  * In addition, the environment variable BGIUSER may be used
  37.  * to define a user-supplied Super VGA driver: see the use.doc file
  38.  * for details.
  39.  */
  40. #define SUPER_VGA 999            /* bogus # for user-defined driver */
  41.  
  42. /* See gxdevice.h for the definitions of the procedures. */
  43.  
  44. dev_proc_open_device(bgi_open);
  45. dev_proc_close_device(bgi_close);
  46. dev_proc_map_rgb_color(bgi_map_rgb_color);
  47. dev_proc_map_color_rgb(bgi_map_color_rgb);
  48. dev_proc_fill_rectangle(bgi_fill_rectangle);
  49. dev_proc_tile_rectangle(bgi_tile_rectangle);
  50. dev_proc_copy_mono(bgi_copy_mono);
  51. dev_proc_copy_color(bgi_copy_color);
  52. dev_proc_draw_line(bgi_draw_line);
  53. dev_proc_fill_trapezoid(bgi_fill_trapezoid);
  54.  
  55. /* The device descriptor */
  56. typedef struct gx_device_bgi_s gx_device_bgi;
  57. struct gx_device_bgi_s {
  58.     gx_device_common;
  59.     int display_mode;
  60.     struct text_info text_mode;
  61. };
  62. #define bgi_dev ((gx_device_bgi *)dev)
  63. static gx_device_procs bgi_procs = {
  64.     bgi_open,
  65.     gx_default_get_initial_matrix,
  66.     gx_default_sync_output,
  67.     gx_default_output_page,
  68.     bgi_close,
  69.     bgi_map_rgb_color,
  70.     bgi_map_color_rgb,
  71.     bgi_fill_rectangle,
  72.     bgi_tile_rectangle,
  73.     bgi_copy_mono,
  74.     bgi_copy_color,
  75.     bgi_draw_line,
  76.     bgi_fill_trapezoid,
  77.     gx_default_tile_trapezoid
  78. };
  79. gx_device_bgi gs_bgi_device = {
  80.     sizeof(gx_device_bgi),
  81.     &bgi_procs,
  82.     "bgi",
  83.     0, 0,        /* width and height are set in bgi_open */
  84.     0, 0,        /* density is set in bgi_open */
  85.     no_margins,
  86.     0,        /* has_color, set for monochrome device */
  87.     1,              /* max_rgb_value, set for monochrome */
  88.     1,        /* bits per color pixel, set for monochrome */
  89.     0        /* not open yet */
  90. };
  91.  
  92. /* Detection procedure for user-defined driver. */
  93. private int huge
  94. detectVGA()
  95. {    return gs_bgi_device.display_mode;
  96. }
  97.  
  98. /* Open the BGI driver for graphics mode */
  99. int
  100. bgi_open(gx_device *dev)
  101. {    int driver, mode;
  102.     char *bgi_user = getenv("BGIUSER");
  103.     char *bgi_path = getenv("BGIPATH");
  104.  
  105.     gettextinfo(&bgi_dev->text_mode);
  106.  
  107.     if ( bgi_path == NULL )
  108.         bgi_path = "";
  109.     if ( bgi_user != NULL )
  110.        {    /* A user-supplied driver is specified as "mode.dname", */
  111.         /* where mode is a hex number and dname is the name */
  112.         /* of the driver file. */
  113.         char dname[40];
  114.         if ( strlen(bgi_user) > sizeof(dname) ||
  115.              sscanf(bgi_user, "%x.%s", &mode, dname) != 2
  116.            )
  117.            {    eprintf("BGIUSER not in form nn.dname.\n");
  118.             exit(1);
  119.            }
  120.         gs_bgi_device.display_mode = mode;    /* sigh.... */
  121.         installuserdriver(dname, detectVGA);
  122.         driver = DETECT;
  123.         initgraph(&driver, &mode, bgi_path);
  124.         driver = SUPER_VGA;
  125.        }
  126.     else                /* not user-defined driver */
  127.        {    /* We include the EGA/VGA driver in the Ghostscript */
  128.         /* executable, so end-users don't have to have */
  129.         /* the BGI files. */
  130.         if ( registerbgidriver(EGAVGA_driver) < 0 )
  131.            {    eprintf("BGI: Can't register EGA/VGA driver!\n");
  132.             exit(1);
  133.            }
  134.  
  135.         detectgraph(&driver, &mode);
  136.         if ( driver < 0 )
  137.            {    eprintf("BGI: No graphics hardware detected!\n");
  138.             exit(1);
  139.            }
  140.  
  141.         if ( driver == EGA64 )
  142.            {    /* Select 16 color video mode if video card is EGA with 64 Kb of memory */
  143.             mode = EGA64LO;
  144.            }
  145.  
  146.         /* Initialize graphics mode. */
  147.  
  148.         /* Following patch for AT&T 6300 is courtesy of */
  149.         /* Allan Wax, Xerox Corp. */
  150.         if ( driver == CGA )
  151.            {    /* The actual hardware might be an AT&T 6300. */
  152.             /* Try initializing it that way. */
  153.             int save_mode = mode;
  154.             driver = ATT400, mode = ATT400HI;
  155.             initgraph(&driver, &mode, bgi_path);
  156.             if ( graphresult() != grOk )
  157.                {    /* Nope, it was a real CGA. */
  158.                 closegraph();
  159.                 driver = CGA, mode = save_mode;
  160.                 initgraph(&driver, &mode, bgi_path);
  161.                }
  162.            }
  163.         else
  164.             initgraph(&driver, &mode, "");
  165.        }
  166.  
  167.        {    int code = graphresult();
  168.         if ( code != grOk )
  169.            {    eprintf1("Error initializing BGI driver: %s\n",
  170.                  grapherrormsg(code));
  171.             exit(1);
  172.            }
  173.        }
  174.  
  175.     /* Set parameters that were unknown before opening device */
  176.  
  177.     /* Size and nominal density of screen. */
  178.     /* The following algorithm maps an appropriate fraction of */
  179.     /* the display screen to an 8.5" x 11" coordinate space. */
  180.     /* This may or may not be what is desired! */
  181.     dev->width = getmaxx() + 1;
  182.     dev->height = getmaxy() + 1;
  183.     dev->y_pixels_per_inch = dev->height / 11.0;
  184.        {    /* Make an educated guess about the aspect ratio. */
  185.         float aspect_ratio;
  186.         switch ( dev->height )
  187.            {
  188.         case 200: case 400:
  189.             aspect_ratio = 25.0 / 11.0;
  190.             break;
  191.         case 350:
  192.             aspect_ratio = 48.0 / 35.0;
  193.             break;
  194.         default:        /* assume square pixels */
  195.             aspect_ratio = 1;
  196.            }
  197.         if ( dev->width / dev->height >= 2 )
  198.             aspect_ratio *= 2;
  199.         dev->x_pixels_per_inch = dev->height * aspect_ratio / 11.0;
  200.        }
  201.  
  202.     /* Find out if the device supports color */
  203.     /* (default initialization is BLACK and WHITE) */
  204.     switch ( driver )
  205.        {
  206.     case EGA:
  207.     case EGA64:
  208.     case VGA:
  209.     case SUPER_VGA:
  210.         dev->has_color = 1;
  211.         dev->bits_per_color_pixel = 4;
  212.         dev->max_rgb_value = 2;
  213.        }
  214.     return 0;
  215. }
  216.  
  217.  
  218. /* Close the BGI driver */
  219. int
  220. bgi_close(gx_device *dev)
  221. {    closegraph();
  222.     textmode(bgi_dev->text_mode.currmode);
  223.     return 0;
  224. }
  225.  
  226.  
  227. /* Map a r-g-b color to the 16 colors available with an EGA/VGA video card. */
  228. /* r, g, b are between 0 and 2. */
  229. static char rgb_color[3][3][3] =
  230.   { { { BLACK, BLUE, LIGHTBLUE },
  231.       { GREEN, CYAN, LIGHTCYAN },
  232.       { LIGHTGREEN, LIGHTCYAN, LIGHTCYAN } },
  233.     { { RED, MAGENTA, LIGHTMAGENTA },
  234.       { BROWN, LIGHTGRAY, LIGHTBLUE },
  235.       { YELLOW, YELLOW, WHITE } },
  236.     { { LIGHTRED, LIGHTMAGENTA, LIGHTMAGENTA },
  237.       { YELLOW, YELLOW, LIGHTMAGENTA },
  238.       { YELLOW, YELLOW, WHITE } }
  239.   };
  240.  
  241. gx_color_index
  242. bgi_map_rgb_color(gx_device *dev, ushort r, ushort g, ushort b)
  243. {    if ( dev->has_color )
  244.        {    return (gx_color_index)rgb_color[r][g][b];
  245.        }
  246.     else
  247.        {    if ( r > 0 || g > 0 || b > 0 )
  248.             return (gx_color_index)WHITE;
  249.         else
  250.             return (gx_color_index)BLACK;
  251.        }
  252. }
  253.  
  254.  
  255. /* Map a color code to r-g-b.  Surprisingly enough, this is algorithmic. */
  256. int
  257. bgi_map_color_rgb(gx_device *dev, gx_color_index color, ushort prgb[3])
  258. {    int on = (color & 8 ? 2 : 1);
  259.     prgb[0] = (color & 4 ? on : 0);
  260.     prgb[1] = (color & 2 ? on : 0);
  261.     prgb[2] = (color & 1 ? on : 0);
  262.     return 0;
  263. }
  264.  
  265.  
  266. /* Copy a monochrome bitmap.  The colors are given explicitly. */
  267. /* Color = gx_no_color_index means transparent (no effect on the image). */
  268. int
  269. bgi_copy_mono(gx_device *dev, byte *base, int sourcex, int raster,
  270.   int x, int y, int w, int h,
  271.   gx_color_index zero, gx_color_index one)
  272. {    byte *ptr_line = base + (sourcex >> 3);
  273.     int left_bit = 0x80 >> (sourcex & 7);
  274.     int dest_y = y, end_x = x + w;
  275.     int invert = 0;
  276.     int color;
  277.  
  278.     if ( zero == gx_no_color_index )
  279.        {    if ( one == gx_no_color_index ) return 0;
  280.         color = (int)one;
  281.        }
  282.     else
  283.        {    if ( one == gx_no_color_index )
  284.            {    color = (int)zero;
  285.             invert = -1;
  286.            }
  287.         else
  288.            {    /* Pre-clear the rectangle to zero */
  289.             setfillstyle(SOLID_FILL, (int)zero);
  290.             bar(x, y, x + w - 1, y + h - 1);
  291.             color = (int)one;
  292.            }
  293.        }
  294.  
  295.     while ( h-- )              /* for each line */
  296.        {    byte *ptr_source = ptr_line;
  297.         register int dest_x = x;
  298.         register int bit = left_bit;
  299.         while ( dest_x < end_x )     /* for each bit in the line */
  300.            {    if ( (*ptr_source ^ invert) & bit )
  301.                 putpixel(dest_x, dest_y, color);
  302.             dest_x++;
  303.             if ( (bit >>= 1) == 0 )
  304.                 bit = 0x80, ptr_source++;
  305.            }
  306.         dest_y++;
  307.         ptr_line += raster;
  308.        }
  309.     return 0;
  310. }
  311.  
  312.  
  313. /* Copy a color pixel map.  This is just like a bitmap, except that */
  314. /* each pixel takes 4 bits instead of 1 when device driver has color. */
  315. int
  316. bgi_copy_color(gx_device *dev, byte *base, int sourcex, int raster,
  317.   int x, int y, int w, int h)
  318. {    if ( dev->has_color )
  319.        {    /* color device, four bits per pixel */
  320.         byte *line = base + (sourcex >> 1);
  321.         int dest_y = y, end_x = x + w;
  322.  
  323.         if ( w <= 0 ) return 0;
  324.         while ( h-- )              /* for each line */
  325.            {    byte *source = line;
  326.             register int dest_x = x;
  327.             if ( sourcex & 1 )    /* odd nibble first */
  328.                {    int color =  *source++ & 0xf;
  329.                 putpixel(dest_x, dest_y, color);
  330.                 dest_x++;
  331.                }
  332.             /* Now do full bytes */
  333.             while ( dest_x < end_x )
  334.                {    int color = *source >> 4;
  335.                 putpixel(dest_x, dest_y, color);
  336.                 dest_x++;
  337.                 if ( dest_x < end_x )
  338.                    {    color =  *source++ & 0xf;
  339.                     putpixel(dest_x, dest_y, color);
  340.                     dest_x++;
  341.                    }
  342.                }
  343.             dest_y++;
  344.             line += raster;
  345.            }
  346.        }
  347.     else /* monochrome device: one bit per pixel */
  348.        {    /* bitmap is the same as bgi_copy_mono: one bit per pixel */
  349.         bgi_copy_mono(dev, base, sourcex, raster, x, y, w, h,
  350.             (gx_color_index)BLACK, (gx_color_index)WHITE);
  351.        }
  352.     return 0;
  353. }
  354.  
  355.  
  356. /* Fill a rectangle. */
  357. int
  358. bgi_fill_rectangle(gx_device *dev, int x, int y, int w, int h,
  359.   gx_color_index color)
  360. {    setfillstyle(SOLID_FILL, (int)color);
  361.     bar(x, y, x + w - 1, y + h - 1);
  362.     return 0;
  363. }
  364.  
  365.  
  366. /* Tile a rectangle.  If neither color is transparent, */
  367. /* pre-clear the rectangle to color0 and just tile with color1. */
  368. /* This is faster because of how bgi_copy_mono is implemented. */
  369. /* Note that this also does the right thing for colored tiles. */
  370. int
  371. bgi_tile_rectangle(gx_device *dev, gx_bitmap *tile,
  372.   int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
  373.   int px, int py)
  374. {    if ( czero != gx_no_color_index && cone != gx_no_color_index )
  375.        {    bgi_fill_rectangle(dev, x, y, w, h, czero);
  376.         czero = gx_no_color_index;
  377.        }
  378.     return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py);
  379. }
  380.  
  381.  
  382. /* Draw a line */
  383. int
  384. bgi_draw_line(gx_device *dev, int x0, int y0, int x1, int y1,
  385.   gx_color_index color)
  386. {    setcolor((int)color);
  387.     setlinestyle(SOLID_LINE, 0, NORM_WIDTH);  /* solid, one pixel wide */
  388.     line(x0, y0, x1, y1);
  389.     return 0;
  390. }
  391.  
  392.  
  393. /* Fill a trapezoid */
  394. int
  395. bgi_fill_trapezoid(gx_device *dev, int x0, int y0, int width0,
  396.   int x1, int y1, int width1, gx_color_index color)
  397. {    struct pointtype pts[4];
  398.     setcolor((int)color);
  399.     /* We'd like to suppress the border, but */
  400.     /* there is no way to do it (aaargh!). */
  401.     setlinestyle(SOLID_LINE, 0, NORM_WIDTH);  /* border solid, one pixel wide */
  402.     setfillstyle(SOLID_FILL, color);
  403.     --y1, --width0, --width1;    /* BGI uses closed intervals */
  404.     pts[0].x = x0;          pts[0].y = y0;
  405.     pts[1].x = x1;          pts[1].y = y1;
  406.     pts[2].x = x1 + width1; pts[2].y = y1;
  407.     pts[3].x = x0 + width0; pts[3].y = y0;
  408.     fillpoly(4, (int *)pts);
  409.     return 0;
  410. }
  411.