home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / dtp / ghost / gs301src / atari / gdevvdi.c < prev    next >
C/C++ Source or Header  |  1994-09-11  |  28KB  |  1,161 lines

  1. /* Copyright (C) 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. /* gdevvdi.c */
  21.  
  22. /* Bitmapped screen device for the Atari ST. This driver contains
  23.  * portions of code originally written by Hauke Hess. It uses the
  24.  * vdi for all screen operations. It recognizes and supports 1, 2,
  25.  * 4, 8, 16, and 24 bit color. Tim Gallivan 5/94.
  26.  */
  27.  
  28. /* For monochrome, Ghostscript produces a bitmap in memory which
  29.  * is referenced directly by 'base'. For color images, GS produces
  30.  * a bitmap at 'base' with each pixel represented by several
  31.  * consecutive bits (packed or chunky pixel format). The routine
  32.  * 'pack_to_plane()' copies the GS "packed" image format into the
  33.  * appropriate number of color planes, referenced by 'cbase'. The
  34.  * image in 'cbase' is then copied back to 'base' with the vdi routine
  35.  * 'vr_trnfm()', and is then copied to the screen. This is rather
  36.  * convoluted, but is needed for portability.
  37.  */
  38.  
  39. #include "gdevvdi.h"
  40.  
  41. /* External Variables */
  42.  
  43. extern VWRK VWork;                /* from gp_atar1.c */
  44. extern PSTATE State;                /* from gp_atar1.c */
  45.  
  46. extern OBJECT menuobj[];            /* from gp_atar1.h */
  47.  
  48. extern WINDOW imagwin;                /* from gp_atar3.c */
  49.  
  50. extern WINLIST *WList, *WinListAdd(), *WinListDelete();
  51.  
  52. /* General screen driver variables. */
  53.  
  54. byte *cbase=0;        /* pointer to the color buffer */
  55. byte **lineptr;        /* pointer for each scan line in bitmap */
  56.  
  57. ushort *plane[16];    /* addresses of each color plane */
  58. ushort *tbase;        /* copy of base accessed by assembly routines */
  59.  
  60. uint csize;        /* size of the color buffer referenced by cbase */
  61. ulong mem_space;    /* amount of memory taken by the bitmap */
  62.  
  63. int words;
  64. int ByteWidth, WordWidth, Raster, CopyWidth, CopyHeight;
  65.  
  66. MFDB plane_image;
  67.  
  68. GRAPHIC Graphic = {
  69.     0,    /* PlotX */
  70.     0,    /* PlotY */
  71.     0,    /* XRes  */
  72.     0,    /* YRes  */
  73.     0,    /* Width */
  74.     0,    /* Height */
  75.     0,    /* StepX */
  76.     0,    /* StepY */
  77.     {0, 0, 0, 0, 0, 0},    /* image */
  78.     {0, 0, 0, 0, 0, 0}    /* screen */
  79. };
  80.  
  81. private dev_proc_open_device(stvdi_open);
  82. private dev_proc_close_device(stvdi_close);
  83. private dev_proc_output_page(stvdi_output_page);
  84. private dev_proc_print_page(stvdi_print_page);
  85. private dev_proc_map_rgb_color(stvdi_map_rgb_color);
  86. private dev_proc_map_color_rgb(stvdi_map_color_rgb);
  87.  
  88. private gx_device_procs stvdi_procs =
  89.   prn_color_procs(stvdi_open, stvdi_output_page, stvdi_close,
  90.     stvdi_map_rgb_color, stvdi_map_color_rgb);
  91.  
  92. gx_device_printer gs_stvdi_device =
  93.   prn_device(stvdi_procs, "stvdi",
  94.     WIDTH_10THS, HEIGHT_10THS,
  95.     X_DPI, Y_DPI,
  96.     0,0,0,0,            /* margins */
  97.     1, stvdi_print_page);        /* default to monochrome */
  98.  
  99. /* Open the stvdi device--get the resolution, allocate memory, etc. */
  100.  
  101. int
  102. stvdi_open(gx_device *pdev)
  103. {
  104.     byte *base=0;
  105.     char *left = 0;
  106.  
  107.     const gx_device_memory *mdev;
  108. /*    gx_device_procs *pprocs = pdev->procs; */
  109.  
  110.     static short AspectAdjusted=0;
  111.  
  112.     int ret;
  113.  
  114.     if (State.Gdebug) eprintf("stvdi_open ...");
  115.  
  116.     /* Adjust the image for the hardware's aspect ratio, but
  117.      * only once. If the device is initialized a second time,
  118.      * the aspect ratio will already be taken into account.
  119.      */
  120.  
  121.     if (!AspectAdjusted) {
  122.         pdev->y_pixels_per_inch = 
  123.         nint(VWork.AspectRatio * pdev->y_pixels_per_inch);
  124.  
  125.         pdev->height = nint(VWork.AspectRatio * pdev->height);
  126.  
  127.         AspectAdjusted = 1;
  128.     }
  129.  
  130.     /* Get an appropriate memory device. */
  131.  
  132.     if ((mdev = gdev_mem_device_for_bits(VWork.ColorBits)) == 0)
  133.         return_error(gs_error_rangecheck);
  134.  
  135.     Graphic.XRes = pmemdev->x_pixels_per_inch;    /* x dpi */
  136.     Graphic.YRes = pmemdev->y_pixels_per_inch;    /* y dpi */
  137.     Graphic.Width = pmemdev->width;            /* width in pixels */
  138.     Graphic.Height = pmemdev->height;        /* height in pixels */
  139.  
  140.     ByteWidth = (Graphic.Width + 7) >> 3;    /* pixel width / 8 */
  141.     WordWidth = (ByteWidth + 1) >> 1;    /* pixel width / 16 */
  142.  
  143.     /* Ensure that the width is a multiple of 16 pixels. */
  144.  
  145.     pmemdev->width = Graphic.Width = 16 * WordWidth;
  146.  
  147.     if (VWork.ColorBits > 1) {
  148.  
  149.         int MaxGray = (int)(pow(2, VWork.ColorBits) - .5);
  150.  
  151.         /* Fill the color_info structure. */
  152.  
  153.         ppdev->color_info.num_components = 3;
  154.         ppdev->color_info.depth       = mdev->color_info.depth;
  155.         ppdev->color_info.max_gray    = MaxGray;
  156.         ppdev->color_info.max_rgb     = VWork.MaxRGB;
  157.         ppdev->color_info.dither_gray = DITH_GRAY(VWork.ColorBits);
  158.         ppdev->color_info.dither_rgb  = DITH_RGB(VWork.ColorBits);
  159.  
  160.         if (State.Gdebug) {
  161.         eprintf1("Depth    = %ld\n", ppdev->color_info.depth);
  162.         eprintf1("Max Gray = %ld\n", ppdev->color_info.max_gray);
  163.         eprintf1("Max RGB  = %ld\n", ppdev->color_info.max_rgb);
  164.         eprintf1("Dither Gray = %ld\n", ppdev->color_info.dither_gray);
  165.         eprintf1("Dither RGB  = %ld\n", ppdev->color_info.dither_rgb);
  166.         }
  167.  
  168.     }
  169.  
  170.     /* Begin code included from gdevprn.c. */
  171.  
  172.     memset(ppdev->skip, 0, sizeof(ppdev->skip));
  173.     ppdev->orig_procs = pdev->std_procs;
  174.     ppdev->file = ppdev->ccfile = ppdev->cbfile = NULL;
  175.     mem_space = gdev_mem_bitmap_size(pmemdev);
  176.  
  177.     /* Base points to a buffer that GS uses to construct the image. */
  178.  
  179.     if ( mem_space >= ppdev->max_bitmap ||
  180.          mem_space != (uint)mem_space   ||    /* too big to allocate */
  181.          (base = (byte *)gs_malloc((uint)mem_space, 1,
  182.          "printer buffer(open)")) == 0  ||    /* can't allocate */
  183.          (PRN_MIN_MEMORY_LEFT != 0 &&
  184.          (left = gs_malloc(PRN_MIN_MEMORY_LEFT, 1,
  185.          "printer memory left")) == 0)    /* not enough left */
  186.        ) {
  187.         eprintf("stvdi_open: Malloc for printer buffer failed.\n");
  188.         return_error(gs_error_VMerror);
  189.     }
  190.  
  191.     /* End code included from gdevprn.c. */
  192.  
  193.     /* Cbase points to a buffer that holds the standard GEM
  194.      * color plane image.
  195.      */
  196.  
  197.     if ((VWork.ColorBits > 1) && !State.Chunky8 && !VWork.TrueColor) {
  198.  
  199.         csize = (uint)(2 * WordWidth * Graphic.Height * VWork.ColorBits);
  200.  
  201.         if ((cbase = (byte *)gs_malloc(csize, 1, "color buffer")) == 0) {
  202.         eprintf("stvdi_open: Malloc for color buffer failed.\n");
  203.         return_error(gs_error_VMerror);
  204.         }
  205.  
  206.     }
  207.  
  208.     /* Begin more code from gdevprn.c. */
  209.  
  210.        /* Render the image entirely in memory. */
  211.  
  212.     /* Release the leftover memory. */
  213.     gs_free(left, PRN_MIN_MEMORY_LEFT, 1, "printer memory left");
  214.  
  215.     ppdev->buffer_space = 0;
  216.     pmemdev->base = base;
  217.     ppdev->std_procs = mdev->std_procs;
  218.     ppdev->std_procs.get_page_device = gx_page_device_get_page_device;
  219.  
  220.     /* Synthesize the procedure vector. */
  221.     /* Rendering operations come from the memory or clist device, */
  222.     /* non-rendering come from the printer device. */
  223.  
  224. #define copy_proc(p) set_dev_proc(ppdev, p, ppdev->orig_procs.p)
  225.     copy_proc(get_initial_matrix);
  226.     copy_proc(output_page);
  227.     copy_proc(close_device);
  228.     copy_proc(map_rgb_color);
  229.     copy_proc(map_color_rgb);
  230.     copy_proc(get_params);
  231.     copy_proc(put_params);
  232.     copy_proc(map_cmyk_color);
  233.     copy_proc(get_xfont_procs);
  234.     copy_proc(get_xfont_device);
  235.     copy_proc(map_rgb_alpha_color);
  236.     copy_proc(get_page_device);
  237. #undef copy_proc
  238.  
  239.     /* End code included from gdevprn.c. */
  240.  
  241.     /* Open the memory device. */
  242.  
  243.     if ((ret = (*pdev->procs->open_device)(pdev)) != 0) {
  244.         return ret;
  245.     }
  246.  
  247.     Raster = pmemdev->raster;
  248.  
  249.     /* Set up the MFDBs for the GS image and the screen. */
  250.  
  251.     Graphic.screen.fd_addr   = (long)NULL;
  252.  
  253.     Graphic.image.fd_addr    = (long)base;
  254.     Graphic.image.fd_w       = (VWork.ColorBits > 1) ? 16 * WordWidth:
  255.                     8 * Raster;
  256.     Graphic.image.fd_h       = Graphic.Height;
  257.     Graphic.image.fd_wdwidth = Graphic.image.fd_w/16;
  258.     Graphic.image.fd_stand   = 0;
  259.     Graphic.image.fd_nplanes = VWork.ColorBits;
  260.  
  261.     if (VWork.ColorBits > 1 && cbase) {
  262.  
  263.         /* Set up the MFDB for the color image buffer. */
  264.  
  265.         plane_image.fd_addr    = (long)cbase;
  266.         plane_image.fd_w       = 16 * WordWidth;
  267.         plane_image.fd_h       = Graphic.Height;
  268.         plane_image.fd_wdwidth = Graphic.image.fd_w/16;
  269.         plane_image.fd_stand   = 1;
  270.         plane_image.fd_nplanes = VWork.ColorBits;
  271.  
  272.     }
  273.  
  274.     return 0;
  275. }
  276.  
  277. /* Close the stvdi device--free memory, close workstations, etc. */
  278.  
  279. int
  280. stvdi_close(gx_device *pdev)
  281. {
  282.     WINLIST *wl = WList;
  283.  
  284.     /* Close the image window. */
  285.  
  286.     if (imagwin.opened || imagwin.iconified) {
  287.     WinClose(&imagwin);
  288.     WinListDelete(wl, &imagwin);
  289.         WinListRedraw(wl, &State);
  290.     }
  291.  
  292.     /* Free the memory device bitmap. */
  293.  
  294.     gs_free((char *)pmemdev->base, (uint)gdev_mem_bitmap_size(pmemdev),
  295.     1, "printer buffer");
  296.  
  297.     /* Free the memory for the color image buffer. */
  298.  
  299.     if (VWork.ColorBits > 1 && cbase) {
  300.     gs_free((char *)cbase, csize, 1, "color buffer");
  301.     }
  302.  
  303.     pdev->std_procs = ppdev->orig_procs;
  304.  
  305.     return 0;
  306. }
  307.  
  308. int
  309. stvdi_output_page(gx_device *pdev, int num_copies, int flush)
  310. {
  311.     int code;
  312.  
  313.     ppdev->page_count++;
  314.  
  315.     /* Print the accumulated page description. */
  316.     code = (*ppdev->print_page)(ppdev, ppdev->file);
  317.  
  318.     /* Make palette entries available to the next page. */
  319.     State.PaletteCount = 1;
  320.  
  321.     if ( code < 0 ) return code;
  322.     return 0;
  323. }
  324.  
  325. /* Print the bitmap for the current page to the screen. */
  326.  
  327. private int
  328. stvdi_print_page(gx_device_printer *pdev, FILE *dummy)
  329. {
  330.     byte *base;
  331.  
  332.     int count, show_end, pad, length, top, empty;
  333.  
  334.     long ch;
  335.  
  336.     show_end = 0;
  337.  
  338.     /* Calculate the number of padding bits in the last byte
  339.      * of each scan line.
  340.      */
  341.  
  342.     pad = (8 * ByteWidth - Graphic.Width) * VWork.ColorBits;
  343.     length = ByteWidth * VWork.ColorBits;
  344.  
  345.     Graphic.PlotY = 0;
  346.  
  347.     lineptr = pmemdev->line_ptrs;
  348.     base = *lineptr;
  349.     tbase = (ushort *)base;    /* accessed from assembly routines */
  350.  
  351.     /* Find the first line containing nonzero bits. */
  352.  
  353.     while (Graphic.PlotY < Graphic.Height) {
  354.  
  355.         /* Search the scanline for a nonzero bit. */
  356.  
  357.         for (count=0; (count < length)
  358.                  && (base[count] == 0); ++count) ;
  359.  
  360.         if (count >= length) {    /* Empty line, continue. */
  361.         Graphic.PlotY++;
  362.         base = lineptr[Graphic.PlotY];
  363.         }
  364.         else if ((count==length-1) && (base[count]>>pad == 0)) {
  365.         Graphic.PlotY++;    /* nonzero bits in padding, continue */
  366.         base = lineptr[Graphic.PlotY];
  367.         }
  368.         else {        /* Nonzero bits found, break loop. */
  369.         if (--Graphic.PlotY < 0) {
  370.             Graphic.PlotY = 0;
  371.         }
  372.         break;
  373.         }
  374.     }
  375.  
  376.     /* Skip transformation and display of modes my hardware
  377.      * doesn't support.
  378.      */
  379.  
  380.     if (State.Debug8 || State.Debug16) {
  381.         dprintf1("%s\n", "Done!");
  382.         return 0;
  383.     }
  384.  
  385.     /* Convert the packed image to standard GEM color planes,
  386.      * then convert the plane image to the final platform-dependent
  387.      * screen format. If the platform-dependent format is chunky,
  388.      * then do nothing.
  389.      */
  390.  
  391.     if (VWork.TrueColor) {
  392.         ;
  393.     }
  394.     else if (VWork.ColorBits == 8 && State.Chunky8) {
  395.         ;
  396.     }
  397.     else {
  398.         stvdi_pack_to_plane();
  399.         vr_trnfm(VWork.VdiHandle, &plane_image, &Graphic.image);
  400.     }
  401.  
  402.     /* Open a window and display the image. */
  403.  
  404.     if (State.Windows) {
  405.  
  406.       graf_mouse(M_OFF, 0L );
  407.  
  408.       if (imagwin.opened) {    /* Already opened. */
  409.  
  410.         State.Event->Message[3] = imagwin.handle;
  411.         HandleRedraw(FULL_WIN, &State);
  412.         update_scroll(imagwin.handle);
  413.  
  414.       }
  415.       else {            /* Window closed or iconified. */
  416.  
  417.         if ((menuobj[NEXT].ob_state & DISABLED) &&
  418.         (menuobj[PREV].ob_state & DISABLED)) {
  419.           menu_ienable(menuobj, NEXT, 1);
  420.         }
  421.  
  422.         WinListAdd(WList, &imagwin);
  423.         BitWinOpen(&imagwin, &VWork, &State);
  424.  
  425.       }
  426.  
  427.       graf_mouse(BUSY_BEE, 0L);
  428.       graf_mouse(M_ON, 0L);
  429.  
  430.     }
  431.     else {
  432.  
  433.         /* Display the image with no windows. */
  434.  
  435.         CopyWidth  = MIN(VWork.XRes, Graphic.Width-1);    /* in pixels */
  436.         CopyHeight = MIN(VWork.YRes, Graphic.Height-1);    /* in pixels */
  437.         Graphic.StepX = .9 * CopyWidth;
  438.         Graphic.StepY = .9 * CopyHeight;
  439.  
  440.         if (Graphic.PlotY < 0)
  441.         Graphic.PlotY = 0;
  442.  
  443.         if (Graphic.PlotY >= Graphic.Height - CopyHeight)
  444.         Graphic.PlotY = (Graphic.Height - 1) - CopyHeight;
  445.  
  446.         v_exit_cur(VWork.VdiHandle);
  447.  
  448.     }
  449.  
  450.     while (!show_end && !State.Windows) {
  451.  
  452.         State.pxy[0] = Graphic.PlotX;
  453.         State.pxy[1] = Graphic.PlotY;
  454.         State.pxy[2] = State.pxy[0] + CopyWidth;
  455.         State.pxy[3] = State.pxy[1] + CopyHeight;
  456.         State.pxy[4] = 0;
  457.         State.pxy[5] = 0;
  458.         State.pxy[6] = State.pxy[4] + CopyWidth;
  459.         State.pxy[7] = State.pxy[5] + CopyHeight;
  460.  
  461.         graf_mouse(M_OFF, 0L );
  462.         vs_clip(VWork.VdiHandle, 1, &State.pxy[4]);
  463.         wind_update(BEG_UPDATE);    /* lock the screen */
  464.  
  465.         vro_cpyfm(VWork.VdiHandle, 3, State.pxy,
  466.             &Graphic.image, &Graphic.screen);
  467.  
  468.         wind_update(END_UPDATE);    /* release screen */
  469.         vs_clip(VWork.VdiHandle, 0, &State.pxy[4]);
  470.         graf_mouse(ARROW, 0L );
  471.         graf_mouse(M_ON, 0L );
  472.  
  473.         /* Accept keyboard commands to manipulate the screen image. */
  474.  
  475.         ch = (Bconin(2) >> 16) & 255;    /* Get key scancode */
  476.         
  477.         switch(ch) {
  478.  
  479.         case 16:            /* Q */
  480.         show_end = 1;
  481.         break;
  482.  
  483.         case 71:            /* Clr/Home */
  484.         Graphic.StepX /= 2; Graphic.StepY /= 2;
  485.         if (Graphic.StepX < 2) Graphic.StepX = 1;
  486.         if (Graphic.StepY < 2) Graphic.StepY = 1;
  487.         break;
  488.  
  489.         case 72:            /* Up cursor */
  490.         Graphic.PlotY = MAX(Graphic.PlotY - Graphic.StepY, 0);
  491.         break;
  492.  
  493.         case 75:            /* Left cursor */
  494.         Graphic.PlotX = MAX(Graphic.PlotX - Graphic.StepX, 0);
  495.         break;
  496.  
  497.         case 77:            /* Right cursor */
  498.         Graphic.PlotX = Graphic.PlotX + Graphic.StepX;
  499.         if (Graphic.PlotX >= Graphic.Width - CopyWidth)
  500.             Graphic.PlotX = (Graphic.Width - 1) - CopyWidth;
  501.         if (Graphic.PlotX < 0) Graphic.PlotX = 0;
  502.         break;
  503.  
  504.         case 80:            /* Down cursor */
  505.         Graphic.PlotY = Graphic.PlotY + Graphic.StepY;
  506.         if (Graphic.PlotY >= Graphic.Height - CopyHeight)
  507.             Graphic.PlotY = (Graphic.Height - 1) - CopyHeight;
  508.         if (Graphic.PlotY < 0) Graphic.PlotY = 0;
  509.         break;
  510.  
  511.         case 82:            /* Insert */
  512.         Graphic.StepX *= 2; Graphic.StepY *= 2;
  513.         if (Graphic.StepX > CopyWidth)  Graphic.StepX = CopyWidth;
  514.         if (Graphic.StepY > CopyHeight) Graphic.StepY = CopyHeight;
  515.         break;
  516.  
  517.         case 97:            /* Undo */
  518.         Graphic.PlotX = 0;
  519.         Graphic.PlotY = 0;
  520.         break;
  521.  
  522.         case 98:            /* Help */
  523.         stvdi_DisplayHelp();
  524.         Bconin(2);
  525.         stvdi_clear_screen(0);
  526.         break;
  527.             
  528.         }
  529.  
  530.     }
  531.  
  532.     if (!State.Windows) {
  533.         v_enter_cur(VWork.VdiHandle);
  534.     }
  535.  
  536.     return (0);
  537.  
  538. }
  539.  
  540. int stvdi_DisplayHelp()
  541. {
  542.     dprintf2("%c%c Help for GhostScript Screen Driver\n", 27, 'E');
  543.     dprintf(" Original Code by Hauke Hess.\n\n");
  544.     dprintf(" Q:            Quit this page (to next page or GS prompt).\n");
  545.     dprintf(" Cursor Keys:  Scroll screen in direction of cursor.\n");
  546.     dprintf(" Help:         Display help screen.\n");
  547.     dprintf(" Undo:         Move to upper-left corner of page.\n");
  548.     dprintf(" Insert:       Multiply scroll incrememt by 2.\n");
  549.     dprintf(" Clr/Home:     Divide scroll increment by 2.\n");
  550.     dprintf("\n Command line option -r<XDPI>x<YDPI> sets resolution.\n");
  551.  
  552. #if 0
  553.     dprintf("\n Helpseite des GhostScript Previewers no(c)\n");
  554.     dprintf(" Hauke Heß 1991\n");
  555.     dprintf(" Cursortasten: bewegen in entsprechender Richtung\n");
  556.     dprintf(" Undo:         Zurück nach links oben auf der Seite\n");
  557.     dprintf(" Insert:       Schrittweiter vergrößern\n");
  558.     dprintf(" Clr/Home:     Schrittweite verkleinern\n");
  559.     dprintf("\n Kommandozeilenparameter -r<XDPI>x<YDPI> setzt die Auflösung\n");
  560. #endif
  561.  
  562.     dprintf("\n >> Hit any key to continue. <<");
  563.  
  564.     return(0);
  565. }
  566.  
  567. int
  568. stvdi_clear_screen(int cursor)
  569. {
  570.     if (cursor) {
  571.         v_enter_cur(VWork.VdiHandle);
  572.     }
  573.     else {
  574.         v_exit_cur(VWork.VdiHandle);
  575.     }
  576. }
  577.  
  578.  
  579. /* Map a r-g-b color to a color index. */
  580.  
  581. /* Ghostscript asks this routine which color index should be associated
  582.  * with a given RGB triplet. The palette is set from the high end as GS
  583.  * requests colors. Black and white, however, always reside at color
  584.  * indices 1 and 0. When the palette is full and a new color is requested,
  585.  * the closest color in the palette is returned.
  586.  */
  587.  
  588. #define BK    0
  589. #define WT    3000
  590.  
  591. gx_color_index
  592. stvdi_map_rgb_color(gx_device *pdev, gx_color_value r, gx_color_value g,
  593.   gx_color_value b) {
  594.  
  595.     register int diff;
  596.     register int *pptr = VWork.Palette + VWork.PaletteSize;
  597.  
  598.     static int BlackSet=0, WhiteSet=0;
  599.  
  600.     gx_color_index Pixel;
  601.  
  602.     int *which, Index;
  603.     int rgb[3], red, grn, blu;
  604.     int best = 1000*3, psize = (VWork.PaletteSize/3 - 2);
  605.  
  606.     float max_value = (float)gx_max_color_value;
  607.  
  608.     if (VWork.ColorBits == 1) {        /* monochrome */
  609.     return ((r | g | b) > gx_max_color_value / 2 ?
  610.         (gx_color_index)0 : (gx_color_index)1);
  611.     }
  612.     else if (VWork.TrueColor) {
  613.     IndexToPixel(&Pixel, 1);
  614.     return Pixel;
  615.     }
  616.  
  617.     /* Change GS rgb values to ST vdi rgb values. */
  618.  
  619.     red = rgb[0] = 1000 * ((float)r / max_value);
  620.     grn = rgb[1] = 1000 * ((float)g / max_value);
  621.     blu = rgb[2] = 1000 * ((float)b / max_value);
  622.  
  623.     Index = State.PaletteCount;
  624.  
  625.     switch (red + grn + blu) {
  626.  
  627.     case WT:            /* white -- keep at vdi index 0 */
  628.     if (!WhiteSet) {
  629.         VWork.Palette[0] = rgb[0];
  630.         VWork.Palette[1] = rgb[1];
  631.         VWork.Palette[2] = rgb[2];
  632.         vs_color(VWork.VdiHandle, 0, rgb);
  633.         WhiteSet = 1;
  634.     }
  635.     return (gx_color_index)VWork.ColorReg[0];
  636.  
  637.     case BK:            /* black -- keep at vdi index 1 */
  638.     if (!BlackSet) {
  639.         VWork.Palette[3] = rgb[0];
  640.         VWork.Palette[4] = rgb[1];
  641.         VWork.Palette[5] = rgb[2];
  642.         vs_color(VWork.VdiHandle, 1, rgb);
  643.         BlackSet = 1;
  644.     }
  645.     return (gx_color_index)VWork.ColorReg[1];
  646.  
  647.     default:            /* Search for color from end of palette. */
  648.  
  649.     while ( Index-- > 1 ) {
  650.         pptr -= 3;
  651.  
  652.         diff = *pptr - red;
  653.         if ( diff < 0 ) diff = -diff;
  654.  
  655.         if ( diff < best ) {    /* quick rejection */
  656.         int dg = pptr[1] - grn;
  657.         if ( dg < 0 ) dg = -dg;
  658.  
  659.         if ( (diff += dg) < best ) {    /* quick rejection */
  660.             int db = pptr[2] - blu;
  661.             if ( db < 0 ) db = -db;
  662.  
  663.             if ( (diff += db) < best )
  664.             which = pptr, best = diff;
  665.  
  666.             if (best == 0) break;
  667.         }
  668.         }
  669.     }
  670.  
  671.     /* If the color is found or the palette is full, return
  672.      * the result of the palette search. Otherwise, set the
  673.      * next palette entry to the requested color.
  674.      */
  675.  
  676.     if (best == 0 || State.PaletteCount >= psize) {
  677.         Index = (which - VWork.Palette)/3;
  678.         return (gx_color_index)VWork.ColorReg[Index];
  679.     }
  680.     else {
  681.         int i = VWork.PaletteSize - 3 * State.PaletteCount;
  682.         
  683.         Index = i/3;
  684.  
  685.         VWork.Palette[i]   = rgb[0];
  686.         VWork.Palette[i+1] = rgb[1];
  687.         VWork.Palette[i+2] = rgb[2];
  688.  
  689.         vs_color(VWork.VdiHandle, Index, rgb);
  690.  
  691.         ++State.PaletteCount;
  692.  
  693.         return (gx_color_index)VWork.ColorReg[Index];
  694.     }
  695.  
  696.     break;
  697.  
  698.     }
  699. }
  700.  
  701. /* Map a color index to a r-g-b color. */
  702. int
  703. stvdi_map_color_rgb(gx_device *pdev, gx_color_index color,
  704.   gx_color_value prgb[3])
  705. {
  706.     int *pptr;
  707.     int max_value = gx_max_color_value;
  708.  
  709.     /* HACK ALERT! The manner for extracting RGB values for
  710.      * true color modes uses information which may be hardware
  711.      * dependent or may change in the future. This routine never
  712.      * seems to be called anyway, so it doesn't seem too critical.
  713.      */
  714.  
  715.     if (VWork.ColorBits == 1) {        /* monochrome */
  716.         return gdev_prn_map_color_rgb(pdev, color, prgb);
  717.     }
  718.     else if (VWork.TrueColor) {
  719.         if (VWork.ColorBits == 16) {
  720.         prgb[0] = (color & 0xf800) << (gx_color_value_bits - 16);
  721.         prgb[1] = (color & 0x07e0) << (gx_color_value_bits - 11);
  722.         prgb[2] = (color & 0x001f) << (gx_color_value_bits -  5);
  723.         }
  724.         else {
  725.         int shift = gx_color_value_bits - 24;
  726.  
  727.         if (shift >= 0) {
  728.             prgb[0] = (color & 0x00ff0000L) << shift;
  729.         }
  730.         else {
  731.             prgb[0] = (color & 0x00ff0000L) >> (-shift);
  732.         }
  733.  
  734.         prgb[1] = (color & 0x0000ff00L) << (gx_color_value_bits - 16);
  735.         prgb[2] = (color & 0x000000ffL) << (gx_color_value_bits -  8);
  736.         }
  737.  
  738.         return 0;
  739.     }
  740.  
  741.     pptr = VWork.Palette + (int)color * 3;
  742.  
  743.     prgb[0] = (pptr[0] * max_value) / 1000;
  744.     prgb[1] = (pptr[1] * max_value) / 1000;
  745.     prgb[2] = (pptr[2] * max_value) / 1000;
  746.  
  747.     return 0;
  748. }
  749.  
  750. /* Copy an image from Ghostscript's format to standard color planes. */
  751.  
  752. int
  753. stvdi_pack_to_plane(void)
  754. {
  755.     int i, plane_size;
  756.  
  757.     words = Graphic.Height * WordWidth - 1;        /* pixels/16 - 1 */
  758.     plane_size = 2 * WordWidth * Graphic.Height;
  759.  
  760.     /* Plane[i] holds the address of the ith color plane. */
  761.  
  762.     for (i=0; i<VWork.ColorBits; i++) {
  763.         plane[i] = (ushort *)(cbase + i * plane_size);
  764.     }
  765.  
  766.     /* Jump to the appropriate assembler image transformation. */
  767.  
  768.     switch (VWork.ColorBits) {
  769.  
  770.     case 2:        /* Two-bit color. */
  771.         trans_2();
  772.         break;
  773.  
  774.     case 4:        /* Four-bit color. */
  775.         trans_4();
  776.         break;
  777.  
  778.     case 8:        /* Eight-bit color. */
  779.         trans_8();
  780.         break;
  781.  
  782.     case 16:    /* 16-bit color. */
  783.         trans_16();
  784.         break;
  785.  
  786.     }
  787.  
  788.     return (0);
  789. }
  790.  
  791. /* This routine is necessary because the vdi color indices are not
  792.  * the same as the color register numbers used by the hardware.
  793.  * It figures out the color register number associated with each
  794.  * color index by writing each color index to the screen and then
  795.  * examining which color register was used.
  796.  */
  797.  
  798. int IndexToPixel(gx_color_index *index_array, int p_size)
  799. {
  800.     int i, index, xy_pos[2], LoWord, HiWord;
  801.  
  802.     /* Screen position to write pixel. */
  803.  
  804.     xy_pos[0] = 0;
  805.     xy_pos[1] = 0;
  806.  
  807.     vswr_mode(VWork.VdiHandle, 1);    /* overwrite mode    */
  808.     vsm_type(VWork.VdiHandle, 1);    /* marker type "dot" */
  809.  
  810.     for (index=0; p_size--; index++) {
  811.  
  812.     vsm_color(VWork.VdiHandle, index);      /* set pixel color */
  813.     v_pmarker(VWork.VdiHandle, 1, xy_pos);  /* write pixel to screen */
  814.  
  815.     /* get the pixel -- put in LoWord */
  816.  
  817.     v_get_pixel(VWork.VdiHandle, xy_pos[0], xy_pos[1], &LoWord, &HiWord);
  818.  
  819.     if (VWork.ColorBits <= 16) {
  820.         index_array[index] = (gx_color_index)LoWord;
  821.     }
  822.     else {
  823.         index_array[index] =  65536 * (gx_color_index)HiWord + LoWord;
  824.     }
  825.     }
  826. }
  827.  
  828. __asm__("
  829.  
  830. .globl    _trans_2, _trans_4, _trans_8, _trans_16
  831.  
  832. _trans_2:
  833.  
  834.     |    a0      address of plane 0
  835.     |    a1      address of plane 1
  836.     |    a4      address of source pixels
  837.     |    d7      #pixels/16 - 1
  838.  
  839.     moveml    a0-a5/d0-d7, sp@-    | save the registers
  840.  
  841.     movel    _plane,   a0
  842.     movel    _plane+4, a1
  843.     movel    _tbase,   a4
  844.     movel    _words,   d7
  845.  
  846.     next_block2:
  847.     moveq  #1, d6            | 2 words for 16 pixels
  848.  
  849.     next_word2:
  850.     movew    a4@+, d4        | get 8 pixels
  851.     moveq    #7,   d5        | 8 pixels/word
  852.  
  853.     next_pixel2:
  854.     addw    d4, d4            | scatter pixels to 2 planes
  855.     addxw    d0, d0
  856.     addw    d4, d4
  857.     addxw    d1, d1
  858.  
  859.     dbra    d5, next_pixel2
  860.  
  861.     dbra    d6, next_word2
  862.  
  863.     movew    d0, a1@+        | store 1 word of each bit plane
  864.     movew    d1, a0@+
  865.  
  866.     subql    #1, d7
  867.     bpl    next_block2
  868.  
  869.     moveml    sp@+, a0-a5/d0-d7    | restore the registers
  870.     rts    
  871.  
  872.  
  873. _trans_4:
  874.  
  875.     |    a0      address of plane 0
  876.     |    a1      address of plane 1
  877.     |    a2      address of plane 2
  878.     |    a3      address of plane 3
  879.     |    a4      address of source pixels
  880.     |    d7      #pixels/16 - 1
  881.  
  882.     moveml    d0-d7/a0-a5, sp@-    | save registers
  883.  
  884.     movel    _plane,    a0
  885.     movel    _plane+4,  a1
  886.     movel    _plane+8,  a2
  887.     movel    _plane+12, a3
  888.     movel    _tbase,    a4
  889.     movel    _words, d7
  890.  
  891.     next_block4:
  892.     moveq  #3,d6            | 4 words for 16 pixels
  893.  
  894.     next_word4:
  895.     movew  a4@+,d4            | get 4 pixels
  896.     moveq  #3,d5            | 4 pixels/word
  897.  
  898.     next_pixel4:
  899.     addw   d4,d4            | scatter pixels to four planes
  900.     addxw  d0,d0
  901.     addw   d4,d4
  902.     addxw  d1,d1
  903.     addw   d4,d4
  904.     addxw  d2,d2
  905.     addw   d4,d4
  906.     addxw  d3,d3
  907.  
  908.     dbra   d5,next_pixel4
  909.  
  910.     dbra   d6,next_word4
  911.  
  912.     movew  d0,a3@+            | store 1 word of each bit plane
  913.     movew  d1,a2@+
  914.     movew  d2,a1@+
  915.     movew  d3,a0@+
  916.  
  917.     subql  #1,d7
  918.     bpl    next_block4
  919.  
  920.     moveml    sp@+, d0-d7/a0-a5    | restore registers
  921.     rts
  922.  
  923. _trans_8:
  924.  
  925.     |    a0      address of planes 0 & 4
  926.     |    a1      address of planes 1 & 5
  927.     |    a2      address of planes 2 & 6
  928.     |    a3      address of planes 3 & 7
  929.     |    a4      address of source pixels
  930.     |    a5    pointer to array containing addresses of color planes
  931.     |    d7      #pixels/16 - 1
  932.  
  933.     moveml    d0-d7/a0-a5, sp@-    | save registers
  934.  
  935.     movel    _tbase,    a4
  936.     movel    #_plane,   a5
  937.     movel    _words, d7
  938.  
  939.     pass_one8:            | first pass through the image
  940.     moveml    a5@(16), a0-a3    | get addresses of second 4 planes
  941.  
  942.     next_block8:
  943.     moveq    #7, d6        | 8 words for 16 pixels
  944.  
  945.     next_word8:
  946.     movew    a4@+, d4    | get 2 pixels
  947.  
  948.      addw    d4, d4        | scatter to first 4 planes
  949.     addxw    d0, d0
  950.     addw    d4, d4
  951.     addxw    d1, d1
  952.     addw    d4, d4
  953.     addxw    d2, d2
  954.     addw    d4, d4
  955.     addxw    d3, d3
  956.     rolw    #4, d4
  957.     addw    d4, d4
  958.     addxw    d0, d0
  959.     addw    d4, d4
  960.     addxw    d1, d1
  961.     addw    d4, d4
  962.     addxw    d2, d2
  963.     addw    d4, d4
  964.     addxw    d3, d3
  965.  
  966.     dbra    d6, next_word8
  967.  
  968.     movew    d0, a3@+    | store 1 word of each bit plane
  969.     movew    d1, a2@+
  970.         movew    d2, a1@+
  971.         movew    d3, a0@+
  972.  
  973.     subql    #1, d7
  974.     bpl    next_block8
  975.  
  976.     pass_two8:            | second pass through the image
  977.     moveml    a5@, a0-a3    | get addresses of first 4 planes
  978.     movel    _words, d7    | get #pixels/16 - 1
  979.     movel    _tbase, a4    | get address of source pixels
  980.  
  981.     next_block8_2:
  982.     moveq    #7, d6        | 8 words for 16 pixels
  983.  
  984.     next_word8_2:
  985.     movew    a4@+, d4    | get 2 pixels
  986.     rolw    #4, d4
  987.  
  988.      addw    d4, d4        | scatter to last 4 planes
  989.     addxw    d0, d0
  990.     addw    d4, d4
  991.     addxw    d1, d1
  992.     addw    d4, d4
  993.     addxw    d2, d2
  994.     addw    d4, d4
  995.     addxw    d3, d3
  996.     rolw    #4, d4
  997.     addw    d4, d4
  998.     addxw    d0, d0
  999.     addw    d4, d4
  1000.     addxw    d1, d1
  1001.     addw    d4, d4
  1002.     addxw    d2, d2
  1003.     addw    d4, d4
  1004.     addxw    d3, d3
  1005.  
  1006.     dbra    d6, next_word8_2
  1007.  
  1008.         movew    d0, a3@+    | store 1 word of each bit plane
  1009.         movew    d1, a2@+
  1010.         movew    d2, a1@+
  1011.         movew    d3, a0@+
  1012.  
  1013.     subql  #1,d7
  1014.     bpl    next_block8_2
  1015.  
  1016.     moveml    sp@+, d0-d7/a0-a5    | restore registers
  1017.     rts
  1018.  
  1019.  
  1020. _trans_16:
  1021.  
  1022.     |    a0      address of planes 0, 4,  8, & 12
  1023.     |    a1      address of planes 1, 5,  9, & 13
  1024.     |    a2      address of planes 2, 6, 10, & 14
  1025.     |    a3      address of planes 3, 7, 11, & 15
  1026.     |    a4      address of source pixels
  1027.     |    a5    pointer to array containing addresses of color planes
  1028.     |    d7      #pixels/16 - 1
  1029.  
  1030.     moveml    d0-d7/a0-a5, sp@-    | save registers
  1031.  
  1032.     movel    _tbase,    a4
  1033.     movel    #_plane,   a5
  1034.     movel    _words, d7
  1035.  
  1036.     pass_one16:            | first pass through the image
  1037.     moveml    a5@(48), a0-a3    | get addresses of last 4 planes
  1038.  
  1039.     next_block16:
  1040.     moveq    #15, d6        | 16 words for 16 pixels
  1041.  
  1042.     next_word16:
  1043.     movew    a4@+, d4    | get 1 pixel
  1044.  
  1045.      addw    d4, d4        | scatter to first 4 planes
  1046.     addxw    d0, d0
  1047.     addw    d4, d4
  1048.     addxw    d1, d1
  1049.     addw    d4, d4
  1050.     addxw    d2, d2
  1051.     addw    d4, d4
  1052.     addxw    d3, d3
  1053.  
  1054.     dbra    d6, next_word16
  1055.  
  1056.         movew    d0, a3@+    | store 1 word of each bit plane
  1057.     movew    d1, a2@+
  1058.     movew    d2, a1@+
  1059.     movew    d3, a0@+
  1060.  
  1061.     subql    #1, d7
  1062.     bpl    next_block16
  1063.  
  1064.     pass_two16:            | second pass through the image
  1065.     moveml    a5@(32), a0-a3    | get addresses of next 4 planes
  1066.     movel    _words, d7    | get #pixels/16 - 1
  1067.     movel    _tbase, a4    | get address of source pixels
  1068.  
  1069.     next_block16_2:
  1070.     moveq    #15, d6        | 16 words for 16 pixels
  1071.  
  1072.     next_word16_2:
  1073.     movew    a4@+, d4    | get 1 pixel
  1074.     rolw    #4, d4
  1075.  
  1076.      addw    d4, d4        | scatter to last 4 planes
  1077.     addxw    d0, d0
  1078.     addw    d4, d4
  1079.     addxw    d1, d1
  1080.     addw    d4, d4
  1081.     addxw    d2, d2
  1082.     addw    d4, d4
  1083.     addxw    d3, d3
  1084.  
  1085.     dbra    d6, next_word16_2
  1086.  
  1087.         movew    d0, a3@+    | store 1 word of each bit plane
  1088.     movew    d1, a2@+
  1089.     movew    d2, a1@+
  1090.     movew    d3, a0@+
  1091.  
  1092.     subql  #1,d7
  1093.     bpl    next_block16_2
  1094.  
  1095.     pass_three16:            | third pass through the image
  1096.     moveml    a5@(16), a0-a3    | get addresses of next 4 planes
  1097.     movel    _words, d7    | get #pixels/16 - 1
  1098.     movel    _tbase, a4    | get address of source pixels
  1099.  
  1100.     next_block16_3:
  1101.     moveq    #15, d6        | 16 words for 16 pixels
  1102.  
  1103.     next_word16_3:
  1104.     movew    a4@+, d4    | get 1 pixel
  1105.     rolw    #8, d4
  1106.  
  1107.      addw    d4, d4        | scatter to last 4 planes
  1108.     addxw    d0, d0
  1109.     addw    d4, d4
  1110.     addxw    d1, d1
  1111.     addw    d4, d4
  1112.     addxw    d2, d2
  1113.     addw    d4, d4
  1114.     addxw    d3, d3
  1115.  
  1116.     dbra    d6, next_word16_3
  1117.  
  1118.     movew    d0, a3@+    | store 1 word of each bit plane
  1119.     movew    d1, a2@+
  1120.     movew    d2, a1@+
  1121.     movew    d3, a0@+
  1122.  
  1123.     subql  #1,d7
  1124.     bpl    next_block16_3
  1125.  
  1126.     pass_four16:        | fourth pass through the image
  1127.     moveml    a5@, a0-a3    | get addresses of first 4 planes
  1128.     movel    _words, d7    | get #pixels/16 - 1
  1129.     movel    _tbase, a4    | get address of source pixels
  1130.  
  1131.     next_block16_4:
  1132.     moveq    #15, d6        | 16 words for 16 pixels
  1133.  
  1134.     next_word16_4:
  1135.     movew    a4@+, d4    | get 1 pixel
  1136.     rorw    #4, d4
  1137.  
  1138.      addw    d4, d4        | scatter to last 4 planes
  1139.     addxw    d0, d0
  1140.     addw    d4, d4
  1141.     addxw    d1, d1
  1142.     addw    d4, d4
  1143.     addxw    d2, d2
  1144.     addw    d4, d4
  1145.     addxw    d3, d3
  1146.  
  1147.     dbra    d6, next_word16_4
  1148.  
  1149.     movew    d0, a3@+    | store 1 word of each bit plane
  1150.     movew    d1, a2@+
  1151.     movew    d2, a1@+
  1152.     movew    d3, a0@+
  1153.  
  1154.     subql  #1,d7
  1155.     bpl    next_block16_4
  1156.  
  1157.     moveml    sp@+, d0-d7/a0-a5    | restore registers
  1158.     rts
  1159.  
  1160. ");
  1161.