home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / GSPMSRC / SRC / GDEVPM.C < prev    next >
C/C++ Source or Header  |  1993-12-20  |  29KB  |  932 lines

  1. /*  gdevpm.c                                                    */
  2. /*  Ghostscript driver for OS2 2.x Presentation Manager.        */
  3. /*    Version 2.6a by Jim Yang, 1992, 1993.                     */
  4.  
  5. #define INCL_PM
  6. #define INCL_DOS
  7. #define INCL_WIN
  8. #define INCL_GPI
  9.  
  10. #include <stdlib.h>
  11. #include "gx.h"
  12. #include "memory_.h"
  13. #include "gserrors.h"
  14. #include "gsprops.h"
  15. #include "gsutil.h"
  16. #include "gxdevice.h"
  17. #include "gsos2.h"
  18. #include "gxdevmem.h"
  19. #include <os2.h>
  20.  
  21. #define TILE_CACHE_WIDTH        160
  22. #define TILE_CACHE_HEIGHT       32
  23.  
  24. #define MAX_PALETTE_COLORS      224
  25. #define COLORS_STATIC           64
  26.  
  27. #define DEFAULT_WIDTH   442
  28. #define DEFAULT_HEIGHT  572
  29. #define DEFAULT_XDPI    52.0
  30. #define DEFAULT_YDPI    52.0
  31.  
  32. #define DRV_PALETTE_MANAGER     0x02
  33.  
  34. /*-------------------------------------------------------------------------*/
  35. /*  Variables and procedures shared with gsos2b.exe.                       */
  36. HPAL    hpal;
  37. HWND    hwndClient;
  38. ULONG   DrawingMode;
  39. LONG    CXImage, CYImage;
  40. HEV     hevWaitClient;
  41. float   Xdpi, Ydpi;
  42. int     repaint_window (int x0, int y0, int x1, int y1,
  43.                         int x2, int y2, int x3, int y3);
  44. /*-------------------------------------------------------------------------*/
  45.  
  46. extern HAB      habGS;              /*  declared in gp_os2.c  */
  47. extern int      pm_draw_line_called;      /*  declared in gxdraw.c  */
  48.  
  49. /*  See gxdevice.h for the definitions of the procedures.  */
  50.  
  51. dev_proc_open_device (pm_open);
  52. dev_proc_get_initial_matrix (pm_get_initial_matrix);
  53. dev_proc_output_page (pm_output_page);
  54. dev_proc_close_device (pm_close);
  55. dev_proc_fill_rectangle (pm_fill_rectangle);
  56. dev_proc_tile_rectangle (pm_tile_rectangle);
  57. dev_proc_copy_mono (pm_copy_mono);
  58. dev_proc_copy_color (pm_copy_color);
  59. dev_proc_draw_line (pm_draw_line);
  60. dev_proc_map_rgb_color (pm_map_rgb_color);
  61. dev_proc_map_color_rgb (pm_map_color_rgb);
  62. dev_proc_sync_output (pm_sync_output);
  63.  
  64. int alloc_backing_bitmap (gx_device *dev);
  65. VOID APIENTRY close_pm_driver ();
  66.  
  67. /*  The device descriptor  */
  68. typedef struct gx_device_pm_s gx_device_pm;
  69. struct gx_device_pm_s
  70. {
  71.     gx_device_common;
  72.     HWND hwndClient;
  73.     HPS  hpsWin;
  74.     HDC  hdcTile;
  75.     HPS  hpsTile;
  76.     HBITMAP  hbmTile;
  77.     BITMAPINFOHEADER2  bmpTile;
  78.     BITMAPINFO2  *pbmiTile;
  79.     BYTE *TileCache;
  80.     gx_bitmap_id  last_bitmap_id;
  81.     HDC  hdcBackingBitmap;
  82.     HPS  hpsBackingBitmap;
  83.     HBITMAP  hbmBackingBitmap;
  84.     BITMAPINFOHEADER2  bmpBackingBitmap;
  85.     BITMAPINFO2  *pbmiBackingBitmap;
  86.     ULONG  DriverCaps;
  87.     ULONG  HighestColorIndex;
  88.     HPAL  hpal;
  89.     ULONG  aulColorTable [MAX_PALETTE_COLORS];
  90.     gx_device_memory  mdev;
  91.     BYTE  *BackingBitmapPtr;
  92.     ULONG  DrawBitsflOptions;
  93. };
  94.  
  95. #define pmdev ((gx_device_pm *)dev)
  96. #define pmmdev ((gx_device *) &pmdev->mdev)
  97. #define pmmproc(proc) (*pmdev->mdev.procs->proc)
  98.  
  99. private gx_device_procs pm_procs =
  100. {
  101.     pm_open,
  102.     pm_get_initial_matrix,
  103.     pm_sync_output,
  104.     pm_output_page,
  105.     pm_close,
  106.     pm_map_rgb_color,
  107.     pm_map_color_rgb,
  108.     pm_fill_rectangle,
  109.     pm_tile_rectangle,
  110.     pm_copy_mono,
  111.     pm_copy_color,
  112.     pm_draw_line,
  113.     gx_default_get_bits,
  114.     gx_default_get_props,
  115.     gx_default_put_props,
  116.     gx_default_map_cmyk_color,
  117.     NULL        /*  No support for external fonts  */
  118. };
  119.  
  120. gx_device_pm gs_os2pm_device =
  121. {
  122.     sizeof(gx_device_pm),
  123.     &pm_procs,
  124.     "os2pm",
  125.     DEFAULT_WIDTH, DEFAULT_HEIGHT,
  126.     DEFAULT_XDPI, DEFAULT_YDPI,
  127.     no_margins,
  128.     {1, 2, 3, 0, 4, 0},         /*  4 shades of gray                      */
  129.     0                           /*  not opened yet                        */
  130. };
  131.  
  132. gx_device_pm  *CurrentDev;
  133.  
  134.  
  135. /*  Create a color palette and realize it.  */
  136. MakeColorPalette (gx_device *dev)
  137. {
  138.     static const gx_device_color_info  info_256 = dci_color (8, 63, 4);
  139.     ULONG  *pulTable, aulTable [256], r, g, b, i, clr;
  140.     HPAL  hpalOld;
  141.     BITMAPINFO2  *pbmiBackingBitmap;
  142.  
  143.     pbmiBackingBitmap = pmdev->pbmiBackingBitmap;
  144.  
  145.     pmdev->DrawBitsflOptions = BBO_IGNORE | BBO_PAL_COLORS;
  146.     dev->color_info = info_256;
  147.  
  148.     for (i = 0; i < 256; i++)
  149.     {
  150.         pbmiBackingBitmap->argbColor[i].bBlue  = i;
  151.         pbmiBackingBitmap->argbColor[i].bGreen = 0;
  152.         pbmiBackingBitmap->argbColor[i].bRed   = 0;
  153.         pbmiBackingBitmap->argbColor[i].fcOptions = 0;
  154.     }
  155.  
  156.     pulTable = pmdev->aulColorTable;
  157.  
  158.     for (i = 0, r = 0; r < 256; r += 85)
  159.         for (g = 0; g < 256; g += 85)
  160.             for (b = 0; b < 256; b += 85, i++, pulTable++)
  161.             {
  162.                 *pulTable = (r << 16) + (g << 8) + b;
  163.                 aulTable [i] = *pulTable;
  164.             }
  165.  
  166.     for (; i < MAX_PALETTE_COLORS; i++)
  167.         aulTable [i] = PC_RESERVED << 24;
  168.  
  169.     hpal = GpiCreatePalette (habGS, LCOL_PURECOLOR, LCOLF_CONSECRGB,
  170.                              MAX_PALETTE_COLORS, aulTable);
  171.  
  172.     if (hpal == GPI_ERROR)
  173.     {
  174.         fprintf (stdout, "Error creating palette!\n");
  175.         return (0);
  176.     }
  177.  
  178.     pmdev->hpal = hpal;
  179.  
  180.     hpalOld = GpiSelectPalette (pmdev->hpsWin, hpal);
  181.     if (hpalOld == PAL_ERROR)
  182.         fprintf (stdout, "Error setting palette of drawing window!\n");
  183.  
  184.     WinRealizePalette (hwndClient, pmdev->hpsWin, &clr);
  185.  
  186.     pmdev->HighestColorIndex = COLORS_STATIC;
  187.  
  188.     DosSleep (250L);    /*  Sleep for 1/4 second for PM to change palette.  */
  189.  
  190.     return (0);
  191. }
  192.  
  193.  
  194. /*  Create a logical color table with 16 or 4 gray scales.  */
  195. MakeGrayTable (gx_device *dev, int GrayScales)
  196. {
  197.     static const gx_device_color_info  info_16 = {1, 4, 15, 0, 16, 0};
  198.     static const gx_device_color_info  info_4 = {1, 2, 3, 0, 4, 0};
  199.     static const gx_device_color_info  info_2 = dci_black_and_white;
  200.     LONG  alTable [16], i;
  201.     BITMAPINFO2  *pbmiBackingBitmap;
  202.  
  203.     pbmiBackingBitmap = pmdev->pbmiBackingBitmap;
  204.     pmdev->DrawBitsflOptions = BBO_IGNORE;
  205.  
  206.     if (GrayScales == 16)
  207.     {
  208.         dev->color_info = info_16;
  209.         for (i = 0; i < 16; i++)
  210.         {
  211.             alTable [i] = 0x111111 * i;
  212.             pbmiBackingBitmap->argbColor[i].bBlue  = 0x11 * i;
  213.             pbmiBackingBitmap->argbColor[i].bGreen = 0x11 * i;
  214.             pbmiBackingBitmap->argbColor[i].bRed   = 0x11 * i;
  215.             pbmiBackingBitmap->argbColor[i].fcOptions = 0;
  216.         }
  217.         GpiCreateLogColorTable (pmdev->hpsWin, LCOL_PURECOLOR, LCOLF_CONSECRGB,
  218.                                 0L, 16L, alTable);
  219.     }
  220.     else if (GrayScales == 4)
  221.     {
  222.         dev->color_info = info_4;
  223.         for (i = 0; i < 4; i++)
  224.         {
  225.             alTable [i] = 0x555555 * i;
  226.             pbmiBackingBitmap->argbColor[i].bBlue  = 0x55 * i;
  227.             pbmiBackingBitmap->argbColor[i].bGreen = 0x55 * i;
  228.             pbmiBackingBitmap->argbColor[i].bRed   = 0x55 * i;
  229.             pbmiBackingBitmap->argbColor[i].fcOptions = 0;
  230.         }
  231.         GpiCreateLogColorTable (pmdev->hpsWin, LCOL_PURECOLOR, LCOLF_CONSECRGB,
  232.                                 0L, 4L, alTable);
  233.         if (pmdev->pbmiBackingBitmap->cBitCount == 4)
  234.         {
  235.             GpiCreateLogColorTable (pmdev->hpsBackingBitmap, LCOL_PURECOLOR,
  236.                                     LCOLF_CONSECRGB, 0L, 4L, alTable);
  237.         }
  238.     }
  239.     else            /*  Black and white  */
  240.     {
  241.         dev->color_info = info_2;
  242.         for (i = 0; i < 2; i++)
  243.         {
  244.             alTable [i] = 0xffffff * i;
  245.             pbmiBackingBitmap->argbColor[i].bBlue  = 0xff * i;
  246.             pbmiBackingBitmap->argbColor[i].bGreen = 0xff * i;
  247.             pbmiBackingBitmap->argbColor[i].bRed   = 0xff * i;
  248.             pbmiBackingBitmap->argbColor[i].fcOptions = 0;
  249.         }
  250.         GpiCreateLogColorTable (pmdev->hpsWin, LCOL_PURECOLOR, LCOLF_CONSECRGB,
  251.                                 0L, 2L, alTable);
  252.         if (pmdev->pbmiBackingBitmap->cBitCount == 4)
  253.         {
  254.             GpiCreateLogColorTable (pmdev->hpsBackingBitmap, LCOL_PURECOLOR,
  255.                                     LCOLF_CONSECRGB, 0L, 2L, alTable);
  256.         }
  257.     }
  258.  
  259.     return (0);
  260. }
  261.  
  262.  
  263. /*  Open the PM driver.  */
  264. int pm_open (register gx_device *dev)
  265. {
  266.     LONG alBmpFormats [2], lCaps;
  267.     BOOL  fSuccess;
  268.     SIZEL  sizl;
  269.     BITMAPINFO2  *pbmiBackingBitmap, *pbmiTile;
  270.     HDC  hdcWin;
  271.     static DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL};
  272.     static LONG  TimesOpened;
  273.     ULONG  ulMode, ulPostCt;
  274.  
  275.     CurrentDev = pmdev;
  276.  
  277.     pmdev->hwndClient = hwndClient;
  278.     pmdev->hpsWin = WinGetPS (hwndClient);
  279.  
  280.     /*  Bring the drawing window to the top and activate it so that it has  */
  281.     /*    the input focus - having input focus is necessary in order to     */
  282.     /*    realize the palette absolutely.  Use the event semaphore          */
  283.     /*    hevWaitClient to wait until the drawing window has been moved to  */
  284.     /*    the top before continuing.                                        */
  285.     DosResetEventSem (hevWaitClient, &ulPostCt);
  286.     WinPostMsg (hwndClient, WM_USER, (MPARAM) WM_USER_WINTOTOP, 0L);
  287.     DosWaitEventSem (hevWaitClient, SEM_INDEFINITE_WAIT);
  288.  
  289.     /*  Tell the window's client procedure to call WinShowWindow and  */
  290.     /*    make the window visible.                                    */
  291.     DosResetEventSem (hevWaitClient, &ulPostCt);
  292.     WinPostMsg (hwndClient, WM_USER, (MPARAM) WM_USER_SHOWWIN, 0L);
  293.     DosWaitEventSem (hevWaitClient, SEM_INDEFINITE_WAIT);
  294.  
  295.     dev->width = CXImage;
  296.     dev->height = CYImage;
  297.     dev->x_pixels_per_inch = Xdpi;
  298.     dev->y_pixels_per_inch = Ydpi;
  299.  
  300.     hdcWin = GpiQueryDevice (pmdev->hpsWin);
  301.  
  302.     if (hdcWin == NULLHANDLE || hdcWin == HDC_ERROR)
  303.         fprintf (stdout, "Error getting hdcWin!\n");
  304.  
  305.     fSuccess = DevQueryCaps (hdcWin, CAPS_ADDITIONAL_GRAPHICS, 1L, &lCaps);
  306.     if (!fSuccess)
  307.         fprintf (stdout, "DevQueryCaps failed: CAPS_ADDITIONAL_GRAPHICS.\n");
  308.  
  309.     pmdev->DriverCaps = 0;
  310.  
  311.     if (lCaps & CAPS_PALETTE_MANAGER)
  312.         pmdev->DriverCaps |= DRV_PALETTE_MANAGER;
  313.  
  314.     sizl.cx = sizl.cy = 0;
  315.  
  316.     pmdev->hdcTile = DevOpenDC (habGS, OD_MEMORY, "*", 5L, (PDEVOPENDATA) &dop,
  317.                                 NULLHANDLE);
  318.  
  319.     pmdev->hpsTile = GpiCreatePS (habGS, pmdev->hdcTile, &sizl, PU_PELS |
  320.                                   GPIA_ASSOC | GPIT_MICRO | GPIF_DEFAULT);
  321.  
  322.     pmdev->TileCache = (BYTE *) calloc ((TILE_CACHE_WIDTH / (sizeof(ULONG) * 8))
  323.                                          * TILE_CACHE_HEIGHT, sizeof (ULONG));
  324.     if (pmdev->TileCache == NULL)
  325.         fprintf (stdout, "Error allocating memory for TileCache!\n");
  326.  
  327.     pbmiTile = malloc (sizeof (BITMAPINFO2) + sizeof (RGB2));
  328.     if (pbmiTile == NULL)
  329.         fprintf (stdout, "Error allocating memory for BITMAPINFO2 for Tile!\n");
  330.     pmdev->pbmiTile = pbmiTile;
  331.  
  332.     memset (pbmiTile, 0, sizeof (BITMAPINFOHEADER2));
  333.     memset (&(pmdev->bmpTile), 0, sizeof (BITMAPINFOHEADER2));
  334.     pbmiTile->cbFix = pmdev->bmpTile.cbFix = sizeof (BITMAPINFOHEADER2);
  335.     pbmiTile->cPlanes = pmdev->bmpTile.cPlanes = 1;
  336.     pbmiTile->cBitCount = pmdev->bmpTile.cBitCount = 1;
  337.  
  338.     pbmiTile->argbColor[0].bBlue  = 0;
  339.     pbmiTile->argbColor[0].bGreen = 0;
  340.     pbmiTile->argbColor[0].bRed   = 0;
  341.     pbmiTile->argbColor[0].fcOptions = 0;
  342.  
  343.     pbmiTile->argbColor[1].bBlue  = 0xff;
  344.     pbmiTile->argbColor[1].bGreen = 0xff;
  345.     pbmiTile->argbColor[1].bRed   = 0xff;
  346.     pbmiTile->argbColor[1].fcOptions = 0;
  347.  
  348.     pbmiTile->cx = pmdev->bmpTile.cx = TILE_CACHE_WIDTH;
  349.     pbmiTile->cy = pmdev->bmpTile.cy = TILE_CACHE_HEIGHT;
  350.  
  351.     pmdev->hbmTile = GpiCreateBitmap (pmdev->hpsTile, &(pmdev->bmpTile),
  352.                                          0L, NULL, NULL);
  353.  
  354.     GpiSetBitmap (pmdev->hpsTile, pmdev->hbmTile);
  355.  
  356.     GpiQueryDeviceBitmapFormats (pmdev->hpsWin, 2L, alBmpFormats);
  357.  
  358.     pbmiBackingBitmap = malloc (sizeof (BITMAPINFO2) + 256 * sizeof (RGB2));
  359.     if (pbmiBackingBitmap == NULL)
  360.         fprintf (stdout, "Error allocating memory for BITMAPINFO2 for Mono!\n");
  361.     pmdev->pbmiBackingBitmap = pbmiBackingBitmap;
  362.  
  363.     memset (pbmiBackingBitmap, 0, sizeof (BITMAPINFOHEADER2));
  364.     pbmiBackingBitmap->cbFix = sizeof (BITMAPINFOHEADER2);
  365.     pbmiBackingBitmap->cPlanes = 1;
  366.     pbmiBackingBitmap->cBitCount = (USHORT) alBmpFormats [1];
  367.     pbmiBackingBitmap->cx = dev->width;
  368.     pbmiBackingBitmap->cy = dev->height;
  369.  
  370.     if ((DrawingMode & MODE_256_COLOR) && !(pmdev->DriverCaps & DRV_PALETTE_MANAGER))
  371.     {
  372.         fprintf (stdout, "You cannot use the 256 color mode because your"
  373.                          " display driver is not capable of palette"
  374.                          " management!\n");
  375.         return_error (gs_error_rangecheck);
  376.     }
  377.  
  378.     if (pbmiBackingBitmap->cBitCount < 8 && ((DrawingMode & MODE_256_COLOR) ||
  379.         (DrawingMode & MODE_16_GRAY)))
  380.     {
  381.         fprintf (stdout, "You cannot use the 256 color mode or the 16 gray mode"
  382.                          " because you are using a 16 color display!\n");
  383.         return_error (gs_error_rangecheck);
  384.     }
  385.  
  386.     if (pbmiBackingBitmap->cBitCount > 8)
  387.         pbmiBackingBitmap->cBitCount = 8;
  388.  
  389.     if (DrawingMode & MODE_2_GRAY)
  390.        pbmiBackingBitmap->cBitCount = 1;
  391.  
  392.     if (pbmiBackingBitmap->cBitCount == 4)
  393.     {
  394.         pmdev->hdcBackingBitmap = DevOpenDC (habGS, OD_MEMORY, "*", 5L, (PDEVOPENDATA) &dop,
  395.                                     NULLHANDLE);
  396.  
  397.         pmdev->hpsBackingBitmap = GpiCreatePS (habGS, pmdev->hdcBackingBitmap, &sizl, PU_PELS |
  398.                                                GPIA_ASSOC | GPIT_MICRO | GPIF_DEFAULT);
  399.  
  400.         pmdev->bmpBackingBitmap.cbFix = sizeof (BITMAPINFOHEADER2);
  401.         pmdev->bmpBackingBitmap.cPlanes = 1;
  402.         pmdev->bmpBackingBitmap.cBitCount = 4;
  403.  
  404.         pmdev->bmpBackingBitmap.cx = dev->width;
  405.         pmdev->bmpBackingBitmap.cy = dev->height;
  406.  
  407.         pmdev->hbmBackingBitmap = GpiCreateBitmap (pmdev->hpsBackingBitmap, &(pmdev->bmpBackingBitmap),
  408.                                                    0L, NULL, NULL);
  409.  
  410.         GpiSetBitmap (pmdev->hpsBackingBitmap, pmdev->hbmBackingBitmap);
  411.     }
  412.  
  413.     if  (DrawingMode & MODE_256_COLOR)
  414.         MakeColorPalette (dev);
  415.     else if (DrawingMode & MODE_16_GRAY)
  416.         MakeGrayTable (dev, 16);
  417.     else if (DrawingMode & MODE_4_GRAY)
  418.         MakeGrayTable (dev, 4);
  419.     else
  420.         MakeGrayTable (dev, 2);
  421.  
  422.     pmdev->last_bitmap_id = gx_no_bitmap_id;
  423.  
  424.     alloc_backing_bitmap (dev);
  425.  
  426.     /*  Add the cleanup routines for the PM driver to the exit list.  */
  427.     DosExitList (EXLST_ADD | 0x0000, close_pm_driver);
  428.  
  429.     return (0);
  430. }
  431.  
  432.  
  433. /*  Synchronize the device.  If any output to the device has been buffered,  */
  434. /*    send / write it now.                                                   */
  435. int pm_sync_output (gx_device *dev)
  436. {
  437.     POINTL  *paptl;
  438.     ULONG  ulPostCt;
  439.  
  440.     if (DrawingMode & MODE_DRAW_BITMAP_ONLY)
  441.     {
  442.         DosResetEventSem (hevWaitClient, &ulPostCt);
  443.         WinPostMsg (hwndClient, WM_USER, (MPARAM) WM_USER_SYNCOUTPUT, 0L);
  444.         DosWaitEventSem (hevWaitClient, SEM_INDEFINITE_WAIT);
  445.     }
  446.  
  447.     return (0);
  448. }
  449.  
  450.  
  451. /*  Output a fully composed page to the device.  */
  452. int pm_output_page (gx_device *dev, int num_copies, int flush)
  453. {
  454.     ULONG  ulPostCt;
  455.  
  456.     pm_sync_output (dev);
  457.  
  458.     if (DrawingMode & MODE_256_COLOR)
  459.         pmdev->HighestColorIndex = COLORS_STATIC;
  460.  
  461.     DosResetEventSem (hevWaitClient, &ulPostCt);
  462.     WinPostMsg (hwndClient, WM_USER, (MPARAM) WM_USER_SHOWPAGE, 0L);
  463.     DosWaitEventSem (hevWaitClient, SEM_INDEFINITE_WAIT);
  464.     return (0);
  465. }
  466.  
  467.  
  468. /*  Close the PM driver.  */
  469. int pm_close (register gx_device *dev)
  470. {
  471.     if (DrawingMode & MODE_256_COLOR)
  472.     {
  473.         GpiSelectPalette (pmdev->hpsWin, NULLHANDLE);
  474.         GpiDeletePalette (pmdev->hpal);
  475.     }
  476.  
  477.     WinReleasePS (pmdev->hpsWin);
  478.  
  479.     free (pmdev->pbmiTile);
  480.     free (pmdev->TileCache);
  481.     free (pmdev->pbmiBackingBitmap);
  482.     free (pmdev->BackingBitmapPtr);
  483.  
  484.     GpiSetBitmap (pmdev->hpsTile, NULLHANDLE);
  485.     GpiDeleteBitmap (pmdev->hbmTile);
  486.     GpiDestroyPS (pmdev->hpsTile);
  487.     DevCloseDC (pmdev->hdcTile);
  488.  
  489.     CurrentDev = NULL;
  490.  
  491.     return (0);
  492. }
  493.  
  494.  
  495. /*  Construct the initial transformation matrix mapping user coordinates  */
  496. /*    (nominally 1/72" per unit) to device coordinates.                   */
  497. void pm_get_initial_matrix (gx_device *dev, register gs_matrix *pmat)
  498. {
  499.     pmat->xx = dev->x_pixels_per_inch / 72.0;
  500.     pmat->xy = 0;
  501.     pmat->yx = 0;
  502.     pmat->yy = dev->y_pixels_per_inch / 72.0;
  503.     pmat->tx = 0;
  504.     pmat->ty = 0;
  505. }
  506.  
  507.  
  508. #define MAP64(z) ((((z) >> (gx_color_value_bits - 6)) << 2) +\
  509.      ((z) >> (gx_color_value_bits - 2)))
  510. /*  Map a RGB color to a device color.  */
  511. gx_color_index pm_map_rgb_color (gx_device *dev,
  512.                                   gx_color_value red,
  513.                                   gx_color_value green,
  514.                                   gx_color_value blue)
  515. {
  516.     gx_color_index radius;
  517.     ULONG r, g, b, i, index, ulTable, *pulTable, rgb;
  518.  
  519.     if (DrawingMode & MODE_256_COLOR)
  520.     {
  521.         r = MAP64 (red);        /*  Map r to 0->255 in 64 steps.  */
  522.         g = MAP64 (green);
  523.         b = MAP64 (blue);
  524.  
  525.         pulTable = pmdev->aulColorTable;
  526.         index = pmdev->HighestColorIndex;
  527.         rgb = (r << 16) + (g << 8) + b;
  528.  
  529.         for (i = 0; i < index; i++, pulTable++)
  530.             if (*pulTable == rgb)
  531.                 return (i);
  532.  
  533.         if (index < MAX_PALETTE_COLORS)
  534.         {
  535.             ulTable = (PC_RESERVED << 24) + rgb;
  536.             *pulTable = rgb;
  537.             GpiAnimatePalette (pmdev->hpal, LCOLF_CONSECRGB, index, 1, &ulTable);
  538.             pmdev->HighestColorIndex += 1;
  539.             return (index);
  540.         }
  541.         else
  542.             return (gx_no_color_index);
  543.     }
  544.     else if (DrawingMode & MODE_16_GRAY)
  545.     {
  546.         radius = (gx_color_index) max (red, max (green, blue));
  547.         return (min ((radius * 16) / gx_max_color_value, 15));
  548.     }
  549.     else if (DrawingMode & MODE_4_GRAY)
  550.     {
  551.         radius = (gx_color_index) max (red, max (green, blue));
  552.         return (min ((radius * 4) / gx_max_color_value, 3));
  553.     }
  554.     else
  555.     {
  556.         radius = (gx_color_index) max (red, max (green, blue));
  557.         return (min ((radius * 2) / gx_max_color_value, 1));
  558.     }
  559. }
  560.  
  561.  
  562. /*  Map a device color code to RGB values.  */
  563. int pm_map_color_rgb (gx_device *dev, gx_color_index color,
  564.                        gx_color_value rgb[3])
  565. {
  566.     gx_color_value  clr;
  567.     ULONG  *pulTable;
  568.  
  569.     if (DrawingMode & MODE_256_COLOR)
  570.     {
  571.         pulTable = pmdev->aulColorTable + color;
  572.         rgb [2] = (*pulTable >> 16) * (gx_max_color_value / 255);
  573.         rgb [1] = ((*pulTable >> 8) & 0xff) * (gx_max_color_value / 255);
  574.         rgb [0] = (*pulTable & 0xff) * (gx_max_color_value / 255);
  575.     }
  576.     else if (DrawingMode & MODE_16_GRAY)
  577.     {
  578.         clr = (gx_max_color_value / 15) * color;
  579.         rgb[2] = rgb[1] = rgb[0] = clr;
  580.     }
  581.     else if (DrawingMode & MODE_4_GRAY)
  582.     {
  583.         clr = (gx_max_color_value / 3) * color;
  584.         rgb[2] = rgb[1] = rgb[0] = clr;
  585.     }
  586.     else
  587.     {
  588.         clr = gx_max_color_value * color;
  589.         rgb[2] = rgb[1] = rgb[0] = clr;
  590.     }
  591.  
  592.     return (0);
  593. }
  594.  
  595.  
  596. /*  Fill a rectangle with a color.  */
  597. int pm_fill_rectangle (gx_device *dev, int x, int y, int width, int height,
  598.                         gx_color_index color)
  599. {
  600.     POINTL *paptl;
  601.     RECTL  rcl;
  602.  
  603.     if (width <= 0 || height <= 0)
  604.         return (0);
  605.  
  606.     rcl.xLeft = x;
  607.     rcl.yBottom = y;
  608.     rcl.xRight = x + width;
  609.     rcl.yTop = y + height;
  610.  
  611.     pmmproc (fill_rectangle) (pmmdev, x, y, width, height, color);
  612.  
  613.     if (DrawingMode & MODE_DRAW_BITMAP_ONLY || pm_draw_line_called)
  614.         return (0);
  615.  
  616.     WinFillRect (pmdev->hpsWin, &rcl, color);
  617.  
  618.     return(0);
  619. }
  620.  
  621.  
  622. /*  Tile a rectangle.  Tiling consists of doing multiple copy_mono  */
  623. /*    operations to fill the rectangle with copies of the tile.     */
  624. int pm_tile_rectangle (gx_device *dev, register const gx_bitmap *tile,
  625.                         int x, int y, int width, int height,
  626.                         gx_color_index color0, gx_color_index color1,
  627.                         int phase_x, int phase_y)
  628. {
  629.     int  data_x, data_y, cw, ch, cx, cy, h, w, dx;
  630.     int  raster, g, i, j, k;
  631.     int  TileSizeX, TileSizeY, TilesX, TilesY, BytesInTile;
  632.     gx_bitmap_id  id;
  633.     BYTE  *data, *TileCache;
  634.     HPS  hpsTile,  hpsWin;
  635.     POINTL  aptl[3];
  636.     
  637.     if (width <= 0 || height <= 0)
  638.         return (0);
  639.  
  640.     if (color0 == gx_no_color_index || color1 == gx_no_color_index)
  641.         return (gx_default_tile_rectangle (dev, tile, x, y, width, height,
  642.                                            color0, color1, phase_x, phase_y));
  643.  
  644.     gx_default_tile_rectangle (pmmdev, tile, x, y, width, height, color0,
  645.                                color1, phase_x, phase_y);
  646.  
  647.     if (DrawingMode & MODE_DRAW_BITMAP_ONLY || pm_draw_line_called)
  648.         return (0);
  649.  
  650.     id = tile->id;
  651.  
  652.     raster = tile->raster;
  653.     data = tile->data;
  654.     TileSizeX = tile->size.x;
  655.     TileSizeY = tile->size.y;
  656.     hpsTile = pmdev->hpsTile;
  657.     hpsWin = pmdev->hpsWin;
  658.     TileCache = pmdev->TileCache;
  659.  
  660.     BytesInTile = TileSizeX / 8;
  661.     TilesX = TILE_CACHE_WIDTH / TileSizeX;
  662.     TilesY = TILE_CACHE_HEIGHT / TileSizeY;
  663.  
  664.     data_x = (x + phase_x) % tile->rep_width;
  665.     data_y = (y + phase_y) % tile->rep_height;
  666.  
  667.     cw = min (TILE_CACHE_WIDTH - data_x, width);
  668.     ch = min (TILE_CACHE_HEIGHT - data_y, height);
  669.  
  670.     if (id != pmdev->last_bitmap_id)
  671.     {
  672.         if (TILE_CACHE_HEIGHT < TileSizeY || TILE_CACHE_WIDTH < TileSizeX)
  673.         {
  674.             fprintf (stdout, "Unexpected tile size: size.x = %d, size.y = %d.\n",
  675.                      TileSizeX, TileSizeY);
  676.             return (0);
  677.         }
  678.  
  679.         for (g = 0; g < TilesY; g++, data = tile->data)
  680.             for (i = 0; i < TileSizeY; i++, data += raster)
  681.                 for (j = 0; j < TilesX; j++)
  682.                     for (k = 0; k < BytesInTile; k++, TileCache++)
  683.                         *(TileCache) = *(data + k);
  684.  
  685.         GpiSetBitmapBits (hpsTile, 0L, TILE_CACHE_HEIGHT, pmdev->TileCache,
  686.                           pmdev->pbmiTile);
  687.  
  688.         pmdev->last_bitmap_id = id;
  689.     }
  690.  
  691.     GpiSetColor (hpsWin, color1);
  692.     GpiSetBackColor (hpsWin, color0);
  693.  
  694.     for (cy = 0, h = ch; cy < height; )
  695.     {
  696.         aptl[0].y = y + cy;
  697.         aptl[1].y = y + cy + h;
  698.         aptl[2].y = data_y;
  699.  
  700.         for (cx = 0, w = cw, dx = data_x; cx < width; )
  701.         {
  702.             aptl[0].x = x + cx;
  703.             aptl[1].x = x + cx + w;
  704.             aptl[2].x = dx;
  705.  
  706.             GpiBitBlt (hpsWin, hpsTile, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  707.  
  708.             dx = 0;
  709.             cx += w;
  710.             w = min (width - cx, TILE_CACHE_WIDTH);
  711.         }
  712.         data_y = 0;
  713.         cy += h;
  714.         h = min (height - cy, TILE_CACHE_HEIGHT);
  715.     }
  716.  
  717.     return (0);
  718. }
  719.  
  720.  
  721. /*  Copy a monochrome bitmap.  Color = gx_no_color_index means transparent  */
  722. /*    (no effect on the image).                                             */
  723. int pm_copy_mono (gx_device *dev, const unsigned char *data,
  724.                    int data_x, int raster, gx_bitmap_id id,
  725.                    int x, int y, int width, int height,
  726.                    gx_color_index color0, gx_color_index color1)
  727. {
  728.     POINTL  aptl[4];
  729.     HPS  hpsWin;
  730.  
  731.     if (width <= 0 || height <= 0)
  732.         return (0);
  733.  
  734.     pmmproc (copy_mono) (pmmdev, data, data_x, raster, id,
  735.                          x, y, width, height, color0, color1);
  736.  
  737.     if (DrawingMode & MODE_DRAW_BITMAP_ONLY)
  738.         return (0);
  739.  
  740.     hpsWin = pmdev->hpsWin;
  741.  
  742.     aptl[0].x = x;
  743.     aptl[0].y = y;
  744.  
  745.     aptl[1].x = x + width - 1;
  746.     aptl[1].y = y + height - 1;
  747.  
  748.     aptl[2].x = x;
  749.     aptl[2].y = y;
  750.  
  751.     aptl[3].x = aptl[1].x + 1;
  752.     aptl[3].y = aptl[1].y + 1;
  753.  
  754.     GpiDrawBits (hpsWin, (PVOID) pmdev->BackingBitmapPtr,
  755.                  pmdev->pbmiBackingBitmap, 4L, aptl, ROP_SRCCOPY,
  756.                  pmdev->DrawBitsflOptions);
  757.     
  758.     return (0);
  759. }
  760.  
  761.  
  762. /*  Copy a color image with multiple bits per pixel.  Not yet implemented.  */
  763. int pm_copy_color (gx_device *dev, const unsigned char *data,
  764.                    int data_x, int raster, gx_bitmap_id id,
  765.                    int x, int y, int width, int height)
  766. {
  767.     int h, bits_shifted, pixels_drawn, bits_offset;
  768.     const BYTE *pdata;
  769.     BYTE clr, bucket;
  770.     POINTL  ptl, *aptl;
  771.     HPS  hpsMemory;
  772.     LONG  *plColor;
  773.  
  774.     if (width <= 0 || height <= 0)
  775.         return (0);
  776.  
  777.     puts ("pm_copy_color called!");
  778.  
  779.     /*  Normally not used by GhostScript 2.6.1  */
  780.  
  781.     return (0);
  782. }
  783.  
  784.  
  785. /*  Draw a minimum-thickness line from (x0,y0) to (x1,y1).  */
  786. int pm_draw_line (gx_device *dev, int x0, int y0, int x1, int y1,
  787.                    gx_color_index color)
  788. {
  789.     POINTL  ptl;
  790.     HPS  hpsWin;
  791.  
  792.     /*  Always return -1 instead of 0 so that GS will use the default  */
  793.     /*    algorithm to draw lines in the backing bitmap.               */
  794.  
  795.     if (x0 == x1 && y0 == y1)
  796.         return (-1);
  797.  
  798.     if (DrawingMode & MODE_DRAW_BITMAP_ONLY)
  799.         return (-1);
  800.  
  801.     hpsWin = pmdev->hpsWin;
  802.  
  803.     GpiSetColor (hpsWin, color);
  804.  
  805.     ptl.x = x0;
  806.     ptl.y = y0;
  807.     GpiMove (hpsWin, &ptl);
  808.  
  809.     ptl.x = x1;
  810.     ptl.y = y1;
  811.     GpiLine (hpsWin, &ptl);
  812.  
  813.     return (-1);
  814. }
  815.  
  816. /*  In case the process is terminated without calling pm_close, free all  */
  817. /*    the resources allocated by the PM driver.  This routine is one of   */
  818. /*    the functions called by DosExitList.                                */
  819. VOID APIENTRY close_pm_driver ()
  820. {
  821.     gx_device_pm  *PMdev;
  822.  
  823.     if (CurrentDev)
  824.         pm_close (CurrentDev);
  825.  
  826.     DosExitList (EXLST_EXIT, NULL);
  827. }
  828.  
  829.  
  830. int alloc_backing_bitmap (gx_device *dev)
  831. {
  832.     gx_device_memory mdev, *mdevp;
  833.     ulong bitmap_size;
  834.     byte *base;
  835.  
  836.     mdevp = gdev_mem_device_for_bits (pmdev->pbmiBackingBitmap->cBitCount);
  837.     if (mdevp == 0)
  838.         fprintf (stdout, "Error determining the appropriate memory device!\n");
  839.     mdev = *mdevp;
  840.     mdev.width = dev->width;
  841.     mdev.height = dev->height;
  842.     mdev.target = (gx_device *) dev;
  843.  
  844.     bitmap_size = gdev_mem_bitmap_size ((gx_device_memory *) &mdev);
  845.     base = (byte *) calloc (bitmap_size / sizeof (long), sizeof (long));
  846.     if (base == NULL)
  847.         fprintf (stdout, "Error allocating backing bitmap memory!\n");
  848.  
  849.     pmdev->mdev = mdev;
  850.     pmdev->mdev.base = base;
  851.     pmdev->BackingBitmapPtr = (byte *) base;
  852.  
  853.     (*pmdev->mdev.procs->open_device)((gx_device *) &pmdev->mdev);
  854.  
  855.     return (0);
  856. }
  857.  
  858.  
  859. int repaint_window (int x0, int y0, int x1, int y1,
  860.                     int x2, int y2, int x3, int y3)
  861. {
  862.     POINTL  aptl [4];
  863.     HWND  hwnd;
  864.     HPS  hps, hpsBitmap;
  865.     ULONG  ulclr;
  866.     RECTL  rcl;
  867.     gx_device *dev;
  868.  
  869.     dev = CurrentDev;
  870.     hwnd = pmdev->hwndClient;
  871.     hps = pmdev->hpsWin;
  872.  
  873.     if (pmdev->BackingBitmapPtr == NULL || x2 < 0 || y2 < 0 ||
  874.         x3 > dev->width || y3 > dev->height)
  875.     {
  876.         rcl.xLeft = x0;
  877.         rcl.yBottom = y0;
  878.  
  879.         rcl.xRight = x1 +1;
  880.         rcl.yTop = y1 + 1;
  881.  
  882.         WinFillRect (hps, &rcl, CLR_WHITE);
  883.         return (0);
  884.     }
  885.  
  886.     aptl[0].x = x0;
  887.     aptl[0].y = y0;
  888.  
  889.     aptl[1].x = x1;
  890.     aptl[1].y = y1;
  891.  
  892.     aptl[2].x = x2;
  893.     aptl[2].y = y2;
  894.  
  895.     aptl[3].x = x3;
  896.     aptl[3].y = y3;
  897.  
  898.     if (DrawingMode & MODE_2_GRAY)
  899.     {
  900.         GpiSetColor (hps, 1);
  901.         GpiSetBackColor (hps, 0);
  902.     }
  903.     else if (pmdev->pbmiBackingBitmap->cBitCount == 4)
  904.     {
  905.         hpsBitmap = pmdev->hpsBackingBitmap;
  906.         GpiSetBitmapBits (hpsBitmap, y2, y3 - y2, pmdev->BackingBitmapPtr +
  907.                           pmdev->mdev.raster * y2, pmdev->pbmiBackingBitmap);
  908.  
  909.         if (DrawingMode & MODE_2_GRAY)
  910.         {
  911.             GpiSetColor (hps, 1);
  912.             GpiSetBackColor (hps, 0);
  913.         }
  914.  
  915.         aptl[1].x += 1;
  916.         aptl[1].y += 1;
  917.  
  918.         GpiBitBlt (hps, hpsBitmap, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  919.         return (0);
  920.     }
  921.  
  922.     if (DrawingMode & MODE_256_COLOR)
  923.         WinRealizePalette (hwnd, hps, &ulclr);
  924.  
  925.     GpiDrawBits (hps, (PVOID) pmdev->BackingBitmapPtr,
  926.                  pmdev->pbmiBackingBitmap, 4L, aptl, ROP_SRCCOPY,
  927.                  pmdev->DrawBitsflOptions);
  928.  
  929.     return (0);
  930. }
  931.  
  932.