home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / os2 / hpgl312.zip / PICBUF.C < prev    next >
C/C++ Source or Header  |  1993-04-18  |  13KB  |  561 lines

  1. /*
  2.    Copyright (c) 1991 - 1993 Heinz W. Werntges.  All rights reserved.
  3.    Distributed by Free Software Foundation, Inc.
  4.  
  5. This file is part of HP2xx.
  6.  
  7. HP2xx is distributed in the hope that it will be useful, but
  8. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  9. to anyone for the consequences of using it or for whether it serves any
  10. particular purpose or works at all, unless he says so in writing.  Refer
  11. to the GNU General Public License, Version 2 or later, for full details.
  12.  
  13. Everyone is granted permission to copy, modify and redistribute
  14. HP2xx, but only under the conditions described in the GNU General Public
  15. License.  A copy of this license is supposed to have been
  16. given to you along with HP2xx so you can know your rights and
  17. responsibilities.  It should be in a file named COPYING.  Among other
  18. things, the copyright notice and this notice must be preserved on all
  19. copies.
  20.  
  21. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  22. */
  23.  
  24. /** picbuf.c: Part of hp2xx project dealing with the picture buffer
  25.  **
  26.  ** 91/01/19  V 1.00  HWW  Derived from hptopcl.c
  27.  ** 91/01/29  V 1.01  HWW  Tested on SUN
  28.  ** 91/02/15  V 1.02  HWW  stdlib.h supported
  29.  ** 91/02/20  V 1.03a HWW  minor mod. in fread(); adaptation to
  30.  **               new HPGL_Pt structures in tmpfile_to_PicBuf()
  31.  ** 91/06/09  V 1.04  HWW  new options acknowledged; minimal changes
  32.  ** 91/10/15  V 1.05  HWW  ANSI_C
  33.  ** 91/11/20  V 1.06  HWW  "SPn;" consequences
  34.  ** 92/02/17  V 1.07b HWW  Preparations for font support
  35.  ** 92/05/24  V 2.00c HWW  Color supported! Fonts ok now; "init" bug fixed
  36.  ** 92/06/08  V 2.00d HWW  GIVE_BACK: 5 --> 8; free_PicBuf() debugged
  37.  ** 92/12/24  V 2.00e HWW  plot_RowBuf() augmented to bit REsetting
  38.  ** 93/04/02  V 2.01a HWW  Always use four bit planes in color mode!
  39.  **               Out-dated "DotBlock" concept replaced by "char".
  40.  **/
  41.  
  42.  
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <math.h>
  47. #include "bresnham.h"
  48. #include "hp2xx.h"
  49.  
  50.  
  51. static    RowBuf    *first_buf = NULL, *last_buf = NULL;
  52.  
  53.  
  54.  
  55.  
  56. #ifndef SEEK_SET
  57. #define SEEK_SET 0
  58. #endif
  59.  
  60.  
  61.  
  62. void    swapout_RowBuf (RowBuf *row, PicBuf *picbuf)
  63. {
  64.   if (fseek (picbuf->sd, (long) row->index*picbuf->nb*picbuf->depth, SEEK_SET))
  65.   {
  66.     perror    ("swapout_RowBuf (on seek)");
  67.     exit    (ERROR);
  68.   }
  69.  
  70.   if (fwrite((char *) row->buf, picbuf->nb, picbuf->depth, picbuf->sd)
  71.     != picbuf->depth)
  72.   {
  73.     perror    ("swapout_RowBuf (on write)");
  74.     exit    (ERROR);
  75.   }
  76. }
  77.  
  78.  
  79.  
  80. void    swapin_RowBuf (RowBuf *row, PicBuf *picbuf)
  81. {
  82.   if (fseek (picbuf->sd, (long) row->index*picbuf->nb*picbuf->depth, SEEK_SET))
  83.   {
  84.     perror    ("swapin_RowBuf (on seek)");
  85.     exit    (ERROR);
  86.   }
  87.  
  88.   if (fread ((char *) row->buf, picbuf->nb, picbuf->depth, picbuf->sd)
  89.     != picbuf->depth)
  90.   {
  91.     perror    ("swapin_RowBuf (on read)");
  92.     exit    (ERROR);
  93.   }
  94. }
  95.  
  96.  
  97.  
  98.  
  99.  
  100. void    link_RowBuf (RowBuf *act, RowBuf *prev)
  101. {
  102.   if (prev == NULL)            /* Make act the new "first_buf"    */
  103.   {
  104.     if (first_buf == NULL)
  105.     {
  106.         first_buf = act;
  107.         act->next = act->prev = NULL;
  108.         return;
  109.     }
  110.     act->next = first_buf;
  111.     act->prev = NULL;
  112.     first_buf->prev = act;
  113.     first_buf = act;
  114.   }
  115.   else                /* Squeeze act between prev & prev->next */
  116.   {
  117.     if ((act->next = prev->next) != NULL)
  118.         act->next->prev = act;
  119.     act->prev = prev;
  120.     prev->next = act;
  121.   }
  122. }
  123.  
  124.  
  125.  
  126.  
  127.  
  128. void    unlink_RowBuf (RowBuf *act)
  129. {
  130.   if ((act->prev==NULL) && (act->next==NULL))
  131.     return;
  132.  
  133.   if (act->prev)
  134.     act->prev->next = act->next;
  135.   else
  136.     first_buf = act->next;
  137.  
  138.   if (act->next)
  139.     act->next->prev = act->prev;
  140.   else
  141.     last_buf = act->prev;
  142.  
  143.   act->next = act->prev = NULL;
  144. }
  145.  
  146.  
  147.  
  148.  
  149. RowBuf    *get_RowBuf (PicBuf *picbuf, int index)
  150. {
  151. RowBuf    *row;
  152.  
  153.   row = picbuf->row + index;
  154. /**
  155.  ** If swapped, load first. Put into first position, if not already there:
  156.  **/
  157.   if ((row->prev == NULL) && (row->next == NULL))
  158.   {
  159.     swapout_RowBuf    (last_buf, picbuf);
  160.     row->buf = last_buf->buf;
  161.     unlink_RowBuf    (last_buf);        /* Mark as swapped     */
  162.     swapin_RowBuf    (row, picbuf);
  163.     link_RowBuf    (row, NULL);        /* Put in first position */
  164.   }
  165.   else
  166.     if (row->prev != NULL)
  167.     {
  168.         unlink_RowBuf (row);
  169.         link_RowBuf (row, NULL);    /* Put in first position */
  170.     }
  171.     /* else: Leave it in first position */
  172.  
  173.   return row;
  174. }
  175.  
  176.  
  177.  
  178.  
  179.  
  180. void    plot_RowBuf (RowBuf *rowbuf, int x, PicBuf *pb, int color_index)
  181. /**
  182.  ** Write color index into pixel x of given row buffer
  183.  **/
  184. {
  185. int    i, Mask;
  186. Byte    *addr;
  187.  
  188. /**
  189.  ** color_index is either the low bit (b/w) or the low nybble (color)
  190.  ** rowbuf->buf is either a sequence of such bits or nybbles.
  191.  ** High bits show left, low bits show right.
  192.  **
  193.  ** This is a time-critical step, so code here is compact,
  194.  ** but not easily readable...
  195.  **/
  196.  
  197.   if (pb->depth == 1)
  198.   {
  199.     Mask = 0x80;
  200.     if ((i = x & 0x07) != 0)
  201.     {
  202.         Mask >>= i;
  203.         if (i!=7)
  204.             color_index <<= (7-i);
  205.     }
  206.     else
  207.         color_index <<= 7;
  208.     addr = rowbuf->buf + (x >> 3);
  209.   }
  210.   else
  211.   {
  212.     Mask = 0xF0;
  213.     if ((x & 0x01) != 0)
  214.         Mask >>= 4;
  215.     else
  216.         color_index <<= 4;
  217.     addr = rowbuf->buf + (x >> 1);
  218.   }
  219.  
  220.   *addr &= ~Mask;
  221.   *addr |=  color_index;
  222. }
  223.  
  224.  
  225.  
  226.  
  227.  
  228. int    index_from_RowBuf (RowBuf *rowbuf, int x, PicBuf *pb)
  229. /**
  230.  ** Return color index of pixel x in given row
  231.  **/
  232. {
  233. int    i, Mask, color_index;
  234. Byte    *addr;
  235.  
  236.   if (pb->depth == 1)
  237.   {
  238.     Mask = 0x80;
  239.     if ((i = x & 0x07) != 0)
  240.         Mask >>= i;
  241.     addr = rowbuf->buf + (x >> 3);
  242.     return (*addr & Mask) ? xxForeground : xxBackground;
  243.   }
  244.   else
  245.   {
  246.     Mask = 0xF0;
  247.     if ((x & 0x01) != 0)
  248.         Mask >>= 4;
  249.     addr = rowbuf->buf + (x >> 1);
  250.     color_index = *addr & Mask;
  251.     if ((x & 0x01) == 0)
  252.         color_index >>= 4;
  253.     return color_index;
  254.   }
  255. }
  256.  
  257.  
  258.  
  259.  
  260. PicBuf    *allocate_PicBuf (DevPt *maxdotcoord, PAR *p)
  261. /**
  262.  ** Here we allocated the picture buffer. This memory is used by all raster
  263.  ** modes. It is organized in rows (scan lines). Rows which do not
  264.  ** end on a byte boundary will be right-padded with "background" bits.
  265.  **
  266.  ** If colors are active, there will always be four bit layers per row,
  267.  ** even if you need only three colors.
  268.  ** These layers are implemented by allocating longer rows
  269.  ** (regular length times number of bit planes per pel (depth)).
  270.  **
  271.  ** We try to allocate all row buffers from main memory first.
  272.  ** If allocation fails, we first free a few lines (see constant GIVE_BACK)
  273.  ** to avoid operation close to the dyn. memory limit,
  274.  ** and then initiate swapping to a file.
  275.  **/
  276. {
  277. PicBuf    *pb;
  278. RowBuf    *prev, *act;
  279. int    nr, not_allocated;
  280. #define    GIVE_BACK 8
  281.  
  282.   if ((pb = (PicBuf *) malloc(sizeof(*pb))) == NULL)
  283.   {
  284.     fprintf(stderr,"cannot malloc() PicBuf structure\n");
  285.     return NULL;
  286.   }
  287.   pb->nr = maxdotcoord->y + 1;    /* Number of rows    to buffer    */
  288.   pb->nc = maxdotcoord->x + 1;    /* Number of columns to buffer    */
  289.   pb->sd = NULL;
  290.  
  291.   first_buf    = NULL;        /* Re-init for multiple-file    */
  292.   last_buf    = NULL;        /* applications            */
  293.  
  294. /**
  295.  ** Number of buffer bytes per row:
  296.  **
  297.  ** Example:
  298.  **
  299.  ** dot range (horiz.): 0...2595 ==> 2596 dots per row, pb->nc=2096 ==>
  300.  **     [2596 bits / 8 bits per byte]
  301.  ** ==> 324 DotBlocks + 4 bits which require another whole byte (!)
  302.  **/
  303.  
  304.   pb->nb = (pb->nc >> 3);
  305.   if (pb->nc & 7)
  306.     pb->nb++;
  307.  
  308. /**
  309.  ** Auto-detection of depth (# bits per pel):
  310.  **
  311.  ** B/W mode      (1 bit per pel, Foreground & Background),
  312.  ** or color mode (4 bits per pel)
  313.  **/
  314.  
  315.   pb->depth = (p->is_color) ? 4 : 1;
  316.  
  317. /**
  318.  ** Allocate a (large) array of RowBuf structures: One for each scan line.
  319.  ** !!! The NULL initialization done implicitly by calloc() is crucial !!!
  320.  **/
  321.  
  322.   if ((pb->row = (RowBuf *) calloc((unsigned) pb->nr, sizeof(RowBuf)))
  323.         == NULL)
  324.   {
  325.     fprintf(stderr,"cannot calloc() %d RowBuf structures\n", pb->nr);
  326.     return NULL;
  327.   }
  328.  
  329. /**
  330.  ** Now try to allocate as many buffers as possible. Double-link all RowBuf's
  331.  ** which succeed in buffer allocation, leave the rest isolated (swapping
  332.  ** candidates!)
  333.  **/
  334.  
  335.   not_allocated = 0;
  336.   prev = (RowBuf *) NULL;
  337.   for (nr=0, act = pb->row; nr < pb->nr; nr++, act++)
  338.   {
  339.     act->prev = act->next = NULL;
  340.     act->index= nr;
  341.     if ((act->buf=
  342.         (Byte *) calloc((unsigned) (pb->nb * pb->depth),1)) == NULL)
  343.         not_allocated++;
  344.     else
  345.     {
  346.         link_RowBuf (act, prev);
  347.         prev = act;
  348.         last_buf = act;
  349.     }
  350.   }
  351.  
  352. /**
  353.  ** Prepare swapping
  354.  **/
  355.  
  356.   if (not_allocated)
  357.   {
  358.     if (last_buf->index > GIVE_BACK) for (nr = 0; nr < GIVE_BACK; nr++)
  359.     {
  360.             /* Return some memory for internal use */
  361.         free ((char *) last_buf->buf);
  362.         unlink_RowBuf (last_buf);
  363.         not_allocated++;
  364.     }
  365.     else
  366.     {
  367.         fprintf(stderr,"\nNot enough memory for swapping -- sorry!\n");
  368.         exit (ERROR);
  369.     }
  370.  
  371.     fprintf(stderr,"\nCouldn't allocate %d row buffers: swapping to disk\n",
  372.         not_allocated);
  373.     if ((pb->sd = fopen (p->swapfile, WRITE_BIN)) == NULL)
  374.     {
  375.         fprintf(stderr,"Couldn't open swap file: %s\n", p->swapfile);
  376.         perror ("hp2xx");
  377.         return NULL;
  378.     }
  379.  
  380. /**
  381.  ** Init. swap file data to background color (0), using a shortcut by
  382.  ** assuming that all data are stored without gaps. Thus, instead of
  383.  ** row-by-row operation, we simply write a sufficient number of 0 rows
  384.  ** into the swap file sequentially.
  385.  **/
  386.  
  387.     for (nr=0; nr < pb->nr; nr++)
  388.         if (fwrite((char *) pb->row[0].buf, pb->nb, pb->depth, pb->sd)
  389.         != pb->depth)
  390.         {
  391.             fprintf(stderr,"Couldn't clear swap file!\n");
  392.             perror ("hp2xx");
  393.             fclose (pb->sd);
  394.             return NULL;
  395.         }
  396.   }
  397.  
  398.   return pb;
  399. }
  400.  
  401.  
  402.  
  403.  
  404. void    free_PicBuf (PicBuf *picbuf, char *swapfilename)
  405. /**
  406.  ** De-allocate all row buffersand the picture puffer struct,
  407.  ** remove the swap file (if any).
  408.  **/
  409. {
  410. RowBuf    *row;
  411. int    i;
  412.  
  413.   if (picbuf->sd)
  414.   {
  415.     fclose (picbuf->sd);
  416.     picbuf->sd = NULL;
  417. #ifdef VAX
  418.     delete (swapfilename);
  419. #else
  420.     unlink (swapfilename);
  421. #endif
  422.   }
  423.   for (i=0; i< picbuf->nr; i++)
  424.   {
  425.     row = &(picbuf->row[i]);
  426.     if ((row->prev != NULL) || (row->next != NULL))
  427.         free ((char *) row->buf);
  428.   }
  429.   free((char *) picbuf->row);
  430.   free((char *) picbuf);
  431. }
  432.  
  433.  
  434.  
  435.  
  436.  
  437. void    plot_PicBuf(PicBuf *picbuf, DevPt *pt, int color_index)
  438. {
  439.   plot_RowBuf(get_RowBuf(picbuf, pt->y), pt->x, picbuf, color_index);
  440. }
  441.  
  442.  
  443.  
  444.  
  445. int    index_from_PicBuf(PicBuf *picbuf, DevPt *pt)
  446. {
  447.   return index_from_RowBuf(get_RowBuf(picbuf, pt->y), pt->x, picbuf);
  448. }
  449.  
  450.  
  451.  
  452.  
  453. void    line_PicBuf (PicBuf *picbuf, DevPt *p0, DevPt *p1, PAR *p)
  454. /**
  455.  ** Rasterize a vector (draw a line in the picture buffer), using the
  456.  ** Bresenham algorithm.
  457.  **/
  458. {
  459. DevPt    pt, *p_act;
  460. int    pensize, pencolor;
  461.  
  462.   pensize = p->pensize[p->pen];
  463.   if (pensize == 0)        /* No pen selected!    */
  464.     return;
  465.  
  466.   pencolor = p->pencolor[p->pen];
  467.   if (pencolor == xxBackground)    /* No drawable color!    */
  468.     return;
  469.  
  470.   p_act = bresenham_init (p0, p1);
  471.   if (pensize == 1) do
  472.   {
  473.     plot_PicBuf (picbuf, p_act, pencolor);
  474.   } while (bresenham_next() != BRESENHAM_ERR);
  475.   else do
  476.   {
  477.     plot_PicBuf (picbuf, p_act, pencolor);
  478.  
  479.     pt = *p_act;
  480.     pt.x++;    plot_PicBuf (picbuf, &pt, pencolor);
  481.     pt.y++; plot_PicBuf (picbuf, &pt, pencolor);
  482.     pt.x--; plot_PicBuf (picbuf, &pt, pencolor);
  483.  
  484.     if (pensize > 2)
  485.     {
  486.         pt = *p_act;
  487.         pt.x += 2;    plot_PicBuf (picbuf, &pt, pencolor);
  488.         pt.y++;        plot_PicBuf (picbuf, &pt, pencolor);
  489.         pt.y++;        plot_PicBuf (picbuf, &pt, pencolor);
  490.         pt.x--;        plot_PicBuf (picbuf, &pt, pencolor);
  491.         pt.x--;        plot_PicBuf (picbuf, &pt, pencolor);
  492.  
  493.         if (pensize > 3)    /* expecting 4 ... 9    */
  494.         {
  495.             pt = *p_act;
  496.             pt.x += 3;    plot_PicBuf (picbuf, &pt, pencolor);
  497.             pt.y++;        plot_PicBuf (picbuf, &pt, pencolor);
  498.             pt.y++;        plot_PicBuf (picbuf, &pt, pencolor);
  499.             pt.y++;        plot_PicBuf (picbuf, &pt, pencolor);
  500.             pt.x--;        plot_PicBuf (picbuf, &pt, pencolor);
  501.             pt.x--;        plot_PicBuf (picbuf, &pt, pencolor);
  502.             pt.x--;        plot_PicBuf (picbuf, &pt, pencolor);
  503.         }
  504.     }
  505.   } while (bresenham_next() != BRESENHAM_ERR);
  506. }
  507.  
  508.  
  509.  
  510.  
  511.  
  512. void    tmpfile_to_PicBuf (PicBuf *picbuf, PAR *p, FILE *td)
  513. /**
  514.  ** Interface to higher-level routines:
  515.  **   Assuming a valid picture buffer, read the drawing commands from
  516.  **   the temporary file, transform HP_GL coordinates into dot coordinates,
  517.  **   and draw (rasterize) vectors.
  518.  **/
  519. {
  520. HPGL_Pt        pt1;
  521. static    DevPt    ref = {0};
  522. DevPt        next;
  523. PlotCmd        cmd;
  524.  
  525.   if (!p->quiet)
  526.     fprintf(stderr, "\nPlotting in buffer\n");
  527.   rewind (td);
  528.   while ((cmd = PlotCmd_from_tmpfile()) != EOF)
  529.     switch (cmd)
  530.     {
  531.       case NOP:
  532.         break;
  533.       case SET_PEN:
  534.         if ((p->pen = fgetc(td)) == EOF)
  535.         {
  536.             perror("Unexpected end of temp. file");
  537.             exit (ERROR);
  538.         }
  539.         break;
  540.       case MOVE_TO:
  541.         HPGL_Pt_from_tmpfile(&pt1);
  542.         HPcoord_to_dotcoord (&pt1, &ref);
  543.         break;
  544.       case DRAW_TO:
  545.         HPGL_Pt_from_tmpfile(&pt1);
  546.         HPcoord_to_dotcoord (&pt1, &next);
  547.         line_PicBuf (picbuf, &ref, &next, p);
  548.         memcpy (&ref, &next, sizeof(ref));
  549.         break;
  550.       case PLOT_AT:
  551.         HPGL_Pt_from_tmpfile(&pt1);
  552.         HPcoord_to_dotcoord (&pt1, &ref);
  553.         line_PicBuf (picbuf, &ref, &ref, p);
  554.         break;
  555.  
  556.       default:
  557.         fprintf(stderr,"Illegal cmd in temp. file!\n");
  558.         exit (ERROR);
  559.     }
  560. }
  561.