home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / printing / ghostscrip / source / _gs / c / gdevarc1 < prev    next >
Encoding:
Text File  |  1991-11-24  |  14.2 KB  |  464 lines

  1. /* Copyright (C) 1991 David Elworthy.  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. /* gdevarc1.c */
  21. /* Ghostscript driver for Acorn Archimedes (RISC OS) */
  22. /* The code here does output to a sprite, but none of the sprite display,
  23.    or the general user interface stuff.
  24.  */
  25.  
  26. /*
  27.    1.0  --  April 1991  --  First working version
  28.    2.0  --  June 1991   --  Changed for GhostScript 2.2
  29.    2.1  --  Nov  1991   --  Some code moved to gp_arc
  30.                             Split into two parts
  31.  
  32.  
  33.    If the symbol GS$Options is defined, up to four floats may be read from it, setting
  34.    height and width in inches, and the x and y resolutions in dpi. The output is in the
  35.    current mode. Finally, there may be an integer, which is non zero for save only mode.
  36.    The defaults are A4, and 180 dpi. Specifying -1 for a variable gets you the default.
  37.    From version 2.2, a menu for the read and print windows allows this to be altered.
  38.  
  39.    From version 2.0 onwards, the size of the window is changed to fit the sprite, and
  40.    the sprite is redraw manually, rather than being attached to an icon.
  41.  
  42.    If the size is too large or the resolution too high, GS may fall over, probably not
  43.    cleanly.
  44. */
  45.  
  46. #include <stdlib.h>
  47. #include <string.h>
  48.  
  49. #include "wimpc.h"
  50.  
  51. #include "gx.h"
  52. #include "gsmatrix.h"                   /* for gxdevice.h */
  53. #include "gxbitmap.h"
  54. #include "gxdevice.h"
  55. /* Do all allocation directly */
  56. #include "malloc_.h"
  57.  
  58. #include "h.os"
  59. #include "bbc.h"
  60. #include "wimp.h"
  61. #include "wimpt.h"
  62. #include "wimpio.h"
  63. #include "colourtran.h"
  64. #include "sprite.h"
  65. #include "menu.h"
  66. #include "werr.h"
  67. #include "saveas.h"
  68. #include "magnify.h"
  69. #include "dbox.h"
  70.  
  71. #include "gdevarc.h"
  72. #include "gp_arc.h"
  73.  
  74. /*-------------------------------------------------------------------------------*/
  75.  
  76. BOOL arc_saver(char *filename, void *handle)
  77. {
  78.     /* Save the whole sprite in one go */
  79.     os_filestr f;
  80.     adev_needed(handle);
  81.  
  82.     f.action   = 10; /* Save with type info */
  83.     f.name     = filename;
  84.     f.loadaddr = file_type;
  85.     f.start    = 4 + (int)(adev->sarea);
  86.     f.end      = adev->sarea->freeoff + (int)(adev->sarea);
  87.  
  88.     return (wimpt_complain(os_file(&f)) == NULL);   
  89. }
  90.  
  91. /*--- Low level window functions ---*/
  92.  
  93. /* Pixel translation table - must be set up at start of redraw loop. */
  94. static char pixtrans[256];
  95.  
  96. /* Set up the pixel translation table */
  97. void set_pixtrans(gx_device_arc *adev)
  98. {
  99.     wimpt_noerr(
  100.         colourtran_select_table(adev->mode,
  101.                                 (wimp_paletteword *)(adev->paltab), -1, (wimp_paletteword *)-1,
  102.                                 &pixtrans[0]));
  103. }
  104.  
  105. /* Redraw the sprite: called on each iteration round the redraw loop */
  106. static void redraw_sprite(wimp_redrawstr *r, void *handle)
  107. {
  108.     adev_needed(handle);
  109.     wimp_winfo w_info;
  110.  
  111.     w_info.w = adev->page_window;
  112.     wimpt_noerr(wimp_get_wind_info(&w_info));
  113.  
  114.     wimpt_noerr(
  115.       sprite_put_scaled(adev->sarea, &(adev->sprite), 0,
  116.                         r->box.x0 - r->scx, r->box.y1 - r->scy + w_info.info.ex.y0,
  117.                         &(adev->f), (sprite_pixtrans *)&pixtrans[0]));
  118. }
  119.  
  120. /* Set window title string */
  121. void arc_set_title(gx_device_arc *adev, char *title)
  122. {
  123.     static char *window_title = "GhostScript Output";
  124.  
  125.     if (adev->f.xdiv == 1)
  126.     {
  127.         if (adev->f.xmag == 1)
  128.             sprintf(title, "%s", window_title);
  129.         else
  130.             sprintf(title, "%s Zoom x %d", window_title, adev->f.xmag);
  131.     }
  132.     else if (adev->f.xdiv == 1)
  133.         sprintf(title, "%s Zoom / %d", window_title, adev->f.xdiv);
  134.     else
  135.         sprintf(title, "%s Zoom x %d / %d", window_title, adev->f.xmag, adev->f.xdiv);
  136. }
  137.  
  138. /* Set the extent of the window to the size of the output sprite */
  139. /* We get the extent from the current icon size and scale factors */
  140. void arc_set_window_extent(gx_device_arc *adev)
  141. {
  142.     wimp_redrawstr  wsize;
  143.  
  144.     wsize.w = adev->page_window;
  145.     wsize.box.x0 = 0;
  146.     wsize.box.y0 = -(adev->f.ymag * (adev->height << adev->yeig)) / adev->f.ydiv;
  147.     wsize.box.x1 = (adev->f.xmag * (adev->width << adev->xeig)) / adev->f.xdiv;
  148.     wsize.box.y1 = 0;
  149.     wimpt_noerr(wimp_set_extent(&wsize));
  150. }
  151.  
  152. /* Redraw on zoom change */
  153. static void do_zoom(void *handle)
  154. {
  155.     gx_device_arc *adev = (gx_device_arc *)handle;
  156.     wimp_redrawstr r;
  157.     wimp_winfo  w_info;
  158.     wimp_wstate w_state;
  159.  
  160.     adev->f.ymag = adev->f.xmag;
  161.     adev->f.ydiv = adev->f.xdiv;
  162.     arc_set_window_extent(adev);
  163.  
  164.     /* Change the title string - assumes buffer is big enough! */
  165.     w_info.w = adev->page_window;
  166.     wimpt_noerr(wimp_get_wind_info(&w_info));
  167.     arc_set_title(adev, w_info.info.title.indirecttext.buffer);
  168.  
  169.     /* Reopen the window to force the outline to be redrawn */
  170.     /* This doesn't work unless you close it first! */
  171.     wimpt_noerr(wimp_get_wind_state(adev->page_window, &w_state));
  172.     wimpt_noerr(wimp_close_wind(adev->page_window));
  173.     wimpt_noerr(wimp_open_wind(&w_state.o));
  174.  
  175.     r.w = adev->page_window;
  176.     r.box.x0 = -1000000;
  177.     r.box.y0 = -1000000;
  178.     r.box.x1 =  1000000;
  179.     r.box.y1 =  1000000;
  180.     wimpt_noerr(wimp_force_redraw(&r));
  181. }
  182.  
  183. /*--- Menus ---*/
  184.  
  185. /* Page menu */
  186. static char *page_menu_text = ">Save,>Zoom,Zoom x 1";
  187. #define page_menu_Save      (1)
  188. #define page_menu_Zoom      (2)
  189. #define page_menu_ResetZoom (3)
  190.  
  191. /* Page menu handler */
  192. void arc_process_page_menu(void *handle, char* hit)
  193. {
  194.     adev_needed(handle);
  195.  
  196.     switch (hit[0])
  197.     {
  198.         case page_menu_Save:
  199.             saveas(file_type, "GSOutput", adev->sarea_size, arc_saver, 0, 0, (void *)adev);
  200.             break;
  201.  
  202.         case page_menu_Zoom:
  203.             magnify_select(&(adev->f.xmag), &(adev->f.xdiv), Max_Zoom, Max_Zoom, do_zoom, adev);
  204.             break;
  205.  
  206.         case page_menu_ResetZoom:
  207.             adev->f.xmag = adev->f.xdiv = 1;
  208.             do_zoom(adev);
  209.             break;
  210.     }
  211. }
  212.  
  213. /* Create page menu */
  214. menu arc_create_page_menu(void *handle)
  215. {
  216.     menu m = menu_new("GhostScript", page_menu_text);
  217.     return m;
  218. }
  219.  
  220. /*--- High level window functions ---*/
  221.  
  222. /* Page window event handler - click on icon 1 is save */
  223. /* Do own redraw, so we can plot sprite zoomed */
  224. void arc_page_event_handler(wimp_eventstr *e, void *handle)
  225. {
  226.     adev_needed(handle);
  227.     if ((e->e == wimp_ESEND || e->e == wimp_ESENDWANTACK)
  228.         && e->data.msg.hdr.action == wimp_PALETTECHANGE)
  229.     {
  230.         /* Force window redraw on palette change */
  231.         wimp_redrawstr r;
  232.         r.w = adev->page_window;
  233.         r.box.x0 = r.box.y0 = -1000000;
  234.         r.box.x1 = r.box.y1 = 1000000;
  235.  
  236.         wimp_force_redraw(&r);
  237.         return;
  238.     }
  239.  
  240.     if (e->e == wimp_EREDRAW) set_pixtrans(adev);
  241.     w_event(e, redraw_sprite, &(adev->page_closed), handle);
  242. }
  243.  
  244.  
  245. /* Allocate space for a sprite of given size and mode, including palette */
  246. /* Also creates the palette table for colour translation */
  247. /* Deletes the sprite if it already exists */
  248. /* Returns true if there was enough memory - other errors via wimp (shouldn't happen) */
  249. /* There appears to be a bug in the standard GS allocators, such that if there is not enough
  250.    memory, you get given a small black rather than a NULL return. Se we claim memory directly.
  251. */
  252. BOOL arc_create_op(gx_device_arc *dev)
  253. {
  254.     int sbpp  = 1 << bbc_modevar(dev->mode, bbc_Log2BPC);
  255.     int nc    = bbc_modevar(dev->mode, bbc_NColour)+1;
  256.     int spritesize = dev->width * sbpp;
  257.     sprite_header *header;
  258.  
  259.     spritesize = (spritesize/8 + 4) & ~3;   /* word units */
  260.     spritesize *= dev->height;
  261.  
  262.     spritesize += sizeof(sprite_header);
  263.  
  264.     /* Add space for palette */
  265.     spritesize += 2*sizeof(int)*nc;
  266.  
  267.     /* Allow space for header */
  268.     spritesize += sizeof(sprite_area);
  269.  
  270.     /* Allocate space for the sprite, and the sprite area header */
  271.     if (spritesize > dev->sarea_size)
  272.     {
  273.         if (dev->sarea)
  274.         {   /* Free old memory - delete the sprite, too, to be safe */
  275.             wimpt_noerr(sprite_delete(dev->sarea, &(dev->sprite)));
  276.             free((char *)(dev->sarea));
  277.         }
  278.  
  279.         dev->sarea_size = 0;
  280.         dev->sarea = (sprite_area *)heap_alloc(spritesize);
  281.  
  282.         if (dev->sarea == NULL)
  283.             return FALSE;
  284.         dev->sarea_size = spritesize;
  285.         dev->is_256 = (nc == 64);
  286.     }
  287.  
  288.     /* Initialise the header */
  289.     sprite_area_initialise(dev->sarea, dev->sarea_size);
  290.  
  291.     /* Initialise the sprite */
  292.     dev->sprite.tag = sprite_id_addr;
  293.     wimpt_noerr(
  294.         sprite_create_rp(dev->sarea, sprite_name, sprite_haspalette, dev->width, dev->height, dev->mode,
  295.                      &(dev->sprite.s.addr)));
  296.  
  297.     /* The following is rather hacky, but seems to give a reasonable palette. */
  298.     header = (sprite_header *)dev->sprite.s.addr;
  299.  
  300.     if (bbc_modevar(dev->mode, bbc_Log2BPP) != 3) /* Do nothing for 256 colour modes */
  301.     {
  302.         int *start = (&header->mode) + 1;
  303.         int *end   = (int *)((char *)header + header->image);
  304.  
  305.         /* Fix up the palette */
  306.         while (start < end)
  307.         {
  308.             int t = *start & 0xF0F0F000;
  309.             *start++ = t | ((t >> 4) & 0xF0F0F00);
  310.         }
  311.     }
  312.  
  313.     /* Create colour translation table */
  314.     {
  315.         int *from  = (&header->mode) + 1;
  316.         int *to    = dev->paltab;
  317.         int i;
  318.  
  319.         for (i = nc ; i > 0 ; i--) { *to++ = *from; from += 2; }
  320.     }
  321.     return TRUE;
  322. }
  323.  
  324. /* Set the control block from the options. < 0 gets you the default. */
  325. void arc_set_options(gx_device_arc *adev, int mode, float width, float height, float xres, float yres)
  326. {
  327.     float pwidth, pheight;
  328.  
  329.     adev->mode = mode;
  330.     adev->xeig = bbc_modevar(adev->mode, bbc_XEigFactor);
  331.     adev->yeig = bbc_modevar(adev->mode, bbc_YEigFactor);
  332.  
  333.     /* Default resolution is to assume 180 OS units per inch */
  334.     if (xres <= 0) xres = 180;
  335.     if (yres <= 0) yres = 180;
  336.  
  337.     /* Width and height default to A4 */
  338.     pwidth =  ((width <= 0)  ? 8.27 : width) * xres;
  339.     pheight = ((height <= 0) ? 11.70 : height) * yres;
  340.  
  341.     pwidth  = pwidth  / (1 << adev->xeig);
  342.     pheight = pheight / (1 << adev->yeig);
  343.     xres    = xres / (1 << adev->xeig);
  344.     yres    = yres / (1 << adev->yeig);
  345.     
  346.     adev->width  = (int)(pwidth + 0.5);
  347.     adev->height = (int)(pheight + 0.5);
  348.     adev->x_pixels_per_inch = xres;
  349.     adev->y_pixels_per_inch = yres;
  350. }
  351.  
  352. /* Dbox fields for options */
  353. #define opt_OK       (0)
  354. /* #define opt_Cancel   (1) No longer used */
  355. #define opt_Width    (2)
  356. #define opt_Height   (3)
  357. #define opt_XRes     (4)
  358. #define opt_YRes     (5)
  359. #define opt_SaveOnly (6)
  360.  
  361. /* Floating point field access */
  362. static void set_field(dbox d, int field, float n)
  363. {
  364.   char buffer[256];
  365.   sprintf(buffer, "%g", n);
  366.   dbox_setfield(d, field, buffer);
  367. }
  368.  
  369. static void get_field(dbox d, int field, float *n)
  370. {
  371.   char buffer[256];
  372.   dbox_getfield(d, field, buffer, 256);
  373.   sscanf(buffer, "%g", n);
  374. }
  375.  
  376. /* Main menu handler: called on device options hit */
  377. BOOL arc_device_options(void *handle, char* hit)
  378. {
  379.     adev_needed(handle);
  380.  
  381.     dbox d = dbox_new("GS_Options");
  382.  
  383.     if (d) /* If not, dbox_new failed */
  384.     {
  385.         int   field;
  386.         float xres, yres, width, height;
  387.         float oxres, oyres, owidth, oheight;
  388.         int   mode, omode;
  389.         BOOL  saveonly, osaveonly;
  390.         BOOL  filling = TRUE;
  391.  
  392.         xres   = adev->x_pixels_per_inch * (1 << adev->xeig);
  393.         yres   = adev->y_pixels_per_inch * (1 << adev->yeig);
  394.         width  = adev->width  / adev->x_pixels_per_inch;
  395.         height = adev->height / adev->y_pixels_per_inch;
  396.         mode   = adev->mode;
  397.         saveonly = adev->save_only;
  398.  
  399.         /* Set current options in dbox */
  400.         set_field(d, opt_Width,  width);
  401.         set_field(d, opt_Height, height);
  402.         set_field(d, opt_XRes,   xres);
  403.         set_field(d, opt_YRes,   yres);
  404.         dbox_setnumeric(d, opt_SaveOnly, adev->save_only);
  405.         dbox_show(d);
  406.  
  407.         while (filling)
  408.         {
  409.             field = dbox_fillin(d);
  410.             if (field == opt_OK)
  411.             {
  412.                 /* Set new options */
  413.                 owidth = width;
  414.                 oheight = height;
  415.                 oxres = xres;
  416.                 oyres = yres;
  417.                 omode = mode;
  418.                 osaveonly = saveonly;
  419.  
  420.                 get_field(d, opt_Width,  &width);
  421.                 get_field(d, opt_Height, &height);
  422.                 get_field(d, opt_XRes,   &xres);
  423.                 get_field(d, opt_YRes,   &yres);
  424.                 saveonly = (dbox_getnumeric(d, opt_SaveOnly) != 0);
  425. #ifdef AllowModeChange
  426.                 mode = wimpt_mode();
  427. #endif
  428.                 if (mode != omode || width != owidth || height != oheight ||
  429.                     xres != oxres || yres != oyres)
  430.                 {
  431.                     arc_set_options(adev, mode, width, height, xres, yres);
  432.                     if (!arc_create_op(adev))
  433.                     {   /* Try to restore old options */
  434.                         arc_set_options(adev, omode, owidth, oheight, oxres, oyres);
  435.                         if (arc_create_op(adev))
  436.                         {
  437.                             werr(0,
  438. "Unable to create output (probably short of memory). Old options restored");
  439.                         }
  440.                         else
  441.                         {
  442.                             werr(0,
  443. "Unable to create output (probably short of memory), and old options could not be restored");
  444.                             return FALSE;
  445.                             gs_exit(1);
  446.                         }
  447.                     }
  448.  
  449.                     arc_set_window_extent(adev);
  450.                 }
  451.  
  452.                 adev->save_only = saveonly;
  453.                 filling = dbox_persist();
  454.             }
  455.             else if (/* field == opt_Cancel || */ field < 0)
  456.                 filling = FALSE;
  457.         }
  458.         dbox_dispose(&d);
  459.     }
  460.  
  461.     return TRUE;
  462. }
  463.  
  464.