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

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gdevdjet.c */
  21. /* HP LaserJet/DeskJet driver for Ghostscript */
  22. #include "gdevprn.h"
  23.  
  24. #define X_DPI 300
  25. #define Y_DPI 300
  26. #define LINE_SIZE ((X_DPI * 85 / 10 + 7) / 8)    /* bytes per line */
  27.  
  28. /* Printer types */
  29. #define LJ    0
  30. #define LJ2p    1
  31. #define LJ3    2
  32. #define DJ    3
  33.  
  34. /* The device descriptors */
  35. private dev_proc_print_page(djet_print_page);
  36. private dev_proc_print_page(ljet_print_page);
  37. private dev_proc_print_page(ljet3_prt_page);
  38. private dev_proc_print_page(ljet2p_prt_page);
  39.  
  40. gx_device_printer gs_deskjet_device =
  41.   prn_device(prn_std_procs, "deskjet",
  42.     85,                /* width_10ths, 8.5" */
  43.     110,                /* height_10ths, 11" */
  44.     X_DPI, Y_DPI,
  45.     0.25, 0.25, 0.25, 0.25,        /* margins */
  46.     1, djet_print_page);
  47.  
  48. gx_device_printer gs_laserjet_device =
  49.   prn_device(prn_std_procs, "laserjet",
  50.     85,                /* width_10ths, 8.5" */
  51.     110,                /* height_10ths, 11" */
  52.     X_DPI, Y_DPI,
  53.     0.05, 0.25, 0.55, 0.25,        /* margins */
  54.     1, ljet_print_page);
  55.  
  56. gx_device_printer gs_ljet3_device =
  57.   prn_device(prn_std_procs, "ljet3",
  58.     85,                /* width_10ths, 8.5" */
  59.     110,                /* height_10ths, 11" */
  60.     X_DPI, Y_DPI,
  61.     0.20, 0.25, 0.25, 0.25,        /* margins */
  62.     1, ljet3_prt_page);
  63.  
  64. gx_device_printer gs_ljet2p_device =
  65.   prn_device(prn_std_procs, "ljet2p",
  66.     85,                /* width_10ths, 8.5" */
  67.     110,                /* height_10ths, 11" */
  68.     X_DPI, Y_DPI,
  69.     0.20, 0.25, 0.25, 0.25,        /* margins */
  70.     1, ljet2p_prt_page);
  71.  
  72. /* Forward references */
  73. private int mode2compress(P3(char *, char *, char *));
  74. private int mode3compress(P4(int, char *, char *, char *));
  75. private int hpjet_print_page(P3(gx_device_printer *, FILE *, int));
  76.  
  77. /* ------ Internal routines ------ */
  78.  
  79. /* The DeskJet can compress (mode 2) */
  80. private int
  81. djet_print_page(gx_device_printer *pdev, FILE *prn_stream)
  82. {    return hpjet_print_page(pdev, prn_stream, DJ);
  83. }
  84. /* The LaserJet series II can't compress */
  85. private int
  86. ljet_print_page(gx_device_printer *pdev, FILE *prn_stream)
  87. {    return hpjet_print_page(pdev, prn_stream, LJ);
  88. }
  89. /* All LaserJet series IIIs (III,IIId,IIIp,IIIsi) compress (mode 3) */
  90. private int
  91. ljet3_prt_page(gx_device_printer *pdev, FILE *prn_stream)
  92. {    return hpjet_print_page(pdev, prn_stream, LJ3);
  93. }
  94. /* LaserJet series IIp & IId  compress (mode 2) */
  95. private int
  96. ljet2p_prt_page(gx_device_printer *pdev, FILE *prn_stream)
  97. {    return hpjet_print_page(pdev, prn_stream, LJ2p);
  98. }
  99.  
  100. /* Send the page to the printer.  For speed, compress each scan line, */
  101. /* since computer-to-printer communication time is often a bottleneck. */
  102. private int
  103. hpjet_print_page(gx_device_printer *pdev, FILE *prn_stream, int compress)
  104. {    char data[LINE_SIZE*2];
  105.     char out_row[LINE_SIZE*2],
  106.          prev_row[LINE_SIZE*2],
  107.          *out_data;
  108.     int out_count;
  109.     char *skip_pattern;
  110.  
  111.     /* select the most compressed mode available & clear tmp storage */
  112.     switch ( compress )
  113.       {
  114.         case LJ3: /* PCL 5 printers ... mode 3 compression */
  115.              /* put printer in known state */
  116.         fputs("\033E",prn_stream);
  117.  
  118.         /* ends raster graphics to set raster graphics resolution */
  119.         fputs("\033*rB", prn_stream);
  120.  
  121.         /* set raster graphics resolution -- 300 dpi */
  122.         fputs("\033*t300R", prn_stream);
  123.         /* move to top left of page & set current position */
  124.         fputs("\033*r0f0A", prn_stream);
  125.         fputs("\033&l0E", prn_stream);
  126.         fputs("\033&l-185U", prn_stream);
  127.         fputs("\033*p0x0Y", prn_stream);
  128.             fputs("\033*b3M", prn_stream);
  129.         memset( out_row,0,LINE_SIZE*2 );
  130.         memset( prev_row,0,LINE_SIZE*2 );
  131.         skip_pattern = "\033*b%dY";
  132.         break;
  133.         case LJ2p: /* PCL 4 printers ... mode 2 compression */
  134.              /* put printer in known state */
  135.         fputs("\033E",prn_stream);
  136.  
  137.         /* ends raster graphics to set raster graphics resolution */
  138.         fputs("\033*rB", prn_stream);
  139.  
  140.         /* set raster graphics resolution -- 300 dpi */
  141.         fputs("\033*t300R", prn_stream);
  142.         /* move to top left of page & set current position */
  143.         fputs("\033*r0f0A", prn_stream);
  144.         fputs("\033&l0E", prn_stream);
  145.         fputs("\033&l-185U", prn_stream);
  146.         fputs("\033*p0x0Y", prn_stream);
  147.             fputs("\033*b2M", prn_stream);
  148.         memset( out_row,0,LINE_SIZE*2 );
  149.         skip_pattern = "\033*b%dY";
  150.         break;
  151.         case DJ: /* almost PCL 4 printers ... mode 2 compression */
  152.         /* ends raster graphics to set raster graphics resolution */
  153.         fputs("\033*rB", prn_stream);
  154.  
  155.         /* set raster graphics resolution -- 300 dpi */
  156.         fputs("\033*t300R", prn_stream);
  157.         /* move to top left of page & set current position */
  158.         fputs("\033*p0x0Y", prn_stream);
  159.         fputs("\033*r0A", prn_stream);
  160.             fputs("\033*b2M", prn_stream);
  161.         memset( out_row,0,LINE_SIZE*2 );
  162.         skip_pattern = "\033*b%dY";
  163.         break;
  164.         default: /* LaserJet PCL 3 printers support un-compressed images */
  165.              /* put printer in known state */
  166.         fputs("\033E",prn_stream);
  167.  
  168.         /* ends raster graphics to set raster graphics resolution */
  169.         fputs("\033*rB", prn_stream);
  170.  
  171.         /* set raster graphics resolution -- 300 dpi */
  172.         fputs("\033*t300R", prn_stream);
  173.         /* move to top left of page & set current position */
  174.         fputs("\033*r0A", prn_stream);
  175.         fputs("\033&l0E", prn_stream);
  176.         fputs("\033*p0x0Y", prn_stream);
  177.             fputs("\033*b0M", prn_stream);
  178.         memset( out_row,0,LINE_SIZE*2 );
  179.         skip_pattern = "\033*p+%dY";
  180.         break;
  181.           }
  182.     
  183.  
  184.     /* Send each scan line in turn */
  185.        {    int lnum;
  186.         int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
  187.         int num_blank_lines = 0;
  188.         byte rmask = (byte)(0xff << (-pdev->width & 7));
  189.         /* look for top margin white space... You would think that
  190.            the normal (raster) white space mechanism would work... it
  191.            doesn't... Sometimes PCL printers are brain-dead */
  192.         for ( lnum = 0; lnum < pdev->height; lnum++ )
  193.            {    char *end_data = data + LINE_SIZE;
  194.             gdev_prn_copy_scan_lines(pdev, lnum,
  195.                          (byte *)data, line_size);
  196.                /* Mask off 1-bits beyond the line width. */
  197.             end_data[-1] &= rmask;
  198.             /* Remove trailing 0s. */
  199.             while ( end_data > data && end_data[-1] == 0 )
  200.                 end_data--;
  201.             if ( end_data == data )
  202.                /* Blank line */
  203.                num_blank_lines++;
  204.             else
  205.                break;
  206.            }
  207.         /* Skip blank lines if any */
  208.         if ( num_blank_lines > 0 )
  209.           {    /* move down from current position */
  210.                  fprintf(prn_stream,"\033*p+%dY", num_blank_lines);
  211.                  num_blank_lines = 0;
  212.           }
  213.              /* transfer raster graphics */
  214.         for ( ; lnum < pdev->height; lnum++ )
  215.            {    char *end_data = data + LINE_SIZE;
  216.             gdev_prn_copy_scan_lines(pdev, lnum,
  217.                          (byte *)data, line_size);
  218.                /* Mask off 1-bits beyond the line width. */
  219.             end_data[-1] &= rmask;
  220.             /* Remove trailing 0s. */
  221.             while ( end_data > data && end_data[-1] == 0 )
  222.                 end_data--;
  223.             if ( end_data == data )
  224.                {    /* Blank line */
  225.                 num_blank_lines++;
  226.                 continue;
  227.                }
  228.             switch (compress)
  229.               {
  230.               case LJ3:
  231.                 out_data = out_row;
  232.                   out_count = mode3compress(line_size, data,
  233.                               prev_row,out_row);
  234.                 break;
  235.               case DJ:
  236.               case LJ2p:
  237.                 out_data = out_row;
  238.                    out_count = mode2compress(data, end_data,
  239.                               out_row);
  240.                 break;
  241.               default:
  242.                 out_data = data;
  243.                 out_count = end_data - data;
  244.               }
  245.             /* Skip blank lines if any */
  246.             if ( num_blank_lines > 0 )
  247.                {    /* move down from current position */
  248.                 fprintf(prn_stream, skip_pattern,
  249.                     num_blank_lines);
  250.                 num_blank_lines = 0;
  251.                }
  252.             /* transfer raster graphics */
  253.             fprintf(prn_stream, "\033*b%dW", out_count);
  254.             /* send the row */
  255.             fwrite(out_data, sizeof(char), out_count,
  256.                    prn_stream);
  257.            }
  258.     }
  259.  
  260.     /* end raster graphics */
  261.     fputs("\033*rB", prn_stream);
  262.  
  263.     /* eject page */
  264.     fputs("\033&l0H", prn_stream);
  265.  
  266.     return 0;
  267. }
  268.  
  269.  
  270. /* Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp. */
  271. /* Compresses data from row up to end_row, storing the result */
  272. /* starting at compressed.  Returns the number of bytes stored. */
  273. /* Runs of K<=127 literal bytes are encoded as K-1 followed by */
  274. /* the bytes; runs of 2<=K<=127 identical bytes are encoded as */
  275. /* 257-K followed by the byte. */
  276. /* In the worst case, the result is N+(N/127)+1 bytes long, */
  277. /* where N is the original byte count (end_row - row). */
  278. private int
  279. mode2compress(char *row, char *end_row, char *compressed)
  280. {    register char *i_exam = row; /* byte being examined in the row to compress */
  281.     char *stop_exam = end_row - 4; /* stop scanning for similar bytes here */
  282.     register char *cptr = compressed; /* output pointer into compressed bytes */
  283.  
  284.     while ( i_exam < end_row )
  285.        {    /* Search ahead in the input looking for a run */
  286.         /* of at least 4 identical bytes. */
  287.         char *i_compr = i_exam;
  288.         char *i_next;        /* end of run */
  289.         char byte_value;
  290.         while ( i_exam <= stop_exam &&
  291.             ((byte_value = *i_exam) != i_exam[1] ||
  292.              byte_value != i_exam[2] ||
  293.              byte_value != i_exam[3]) )
  294.           i_exam++;
  295.  
  296.         /* Find out how long the run is */
  297.         if ( i_exam > stop_exam )    /* no run */
  298.             i_next = i_exam = end_row;
  299.         else
  300.            {    i_next = i_exam + 4;
  301.             while ( i_next < end_row && *i_next == byte_value )
  302.                 i_next++;
  303.            }
  304.  
  305.         /* Now [i_compr..i_exam) should be encoded as dissimilar, */
  306.         /* and [i_exam..i_next) should be encoded as similar. */
  307.         /* Note that either of these ranges may be empty. */
  308.  
  309.         while ( i_compr < i_exam )
  310.            {    /* Encode up to 127 dissimilar bytes */
  311.             int count = i_exam - i_compr;
  312.             if ( count > 127 ) count = 127;
  313.             *cptr++ = count - 1;
  314.             while ( count > 0 )
  315.                {    *cptr++ = *i_compr++;
  316.                 count--;
  317.                }
  318.            }
  319.  
  320.         while ( i_exam < i_next )
  321.            {    /* Encode up to 127 similar bytes */
  322.             int count = i_next - i_exam;
  323.             if ( count > 127 ) count = 127;
  324.             *cptr++ = 1 - count;
  325.             *cptr++ = byte_value;
  326.             i_exam += count;
  327.            }
  328.        }
  329.     return (cptr - compressed);
  330. }
  331.  
  332. /* Row compression routine for the HP LaserJet III family. */
  333. /* Compresses data from row up to end_row, storing the result */
  334. /* starting at compressed.  Returns the number of bytes stored. */
  335. private int
  336. mode3compress(int bytecount, char *current, char *previous, char *compressed)
  337. {    register int j;          
  338.     int          l,          
  339.              cap=0,      
  340.              outbytes=0, 
  341.              byteschanged=0,    
  342.              offset,loffset,loffset1; 
  343.     char *ptmp;     
  344.     static char bittab[9] =
  345.         { 0x00,0x00,0x20,0x40,0x60,0x80,0xa0,0xc0,0xe0 };
  346.  
  347.     for( j = 0; j < bytecount; j++ )
  348.        {    if (*previous == *current)
  349.             {    *previous++ = *current++; 
  350.                 if (byteschanged) /* 1st non-change after at least one change */
  351.                    {    offset = j - cap - byteschanged; 
  352.                        cap = j;
  353.                        loffset = offset - 31;
  354.                        if ( offset > 30 )
  355.                      offset = 31;
  356.                        loffset1 = loffset - 255;
  357.                        if ( loffset > 254 )
  358.                      loffset = 255;
  359.                    /* setup byte1 */
  360.                    *compressed++ = bittab[byteschanged] | offset;
  361.                    outbytes++;
  362.                    if (loffset >= 0)
  363.                   {     *compressed++ = (char)loffset;
  364.                     loffset = 0;
  365.                     outbytes++;
  366.                       if (loffset1 >= 0)
  367.                          {     *compressed++ = (char)loffset1;
  368.                              loffset1 = 0;
  369.                              outbytes++;
  370.                          }
  371.                   }
  372.                    ptmp = current - byteschanged -1;
  373.                    for (l=0;l < byteschanged;l++)
  374.                   *compressed++ = *ptmp++;
  375.                    outbytes = outbytes + byteschanged;
  376.                    byteschanged = 0;
  377.                }
  378.            }
  379.           else
  380.            {     *previous++ = *current++; 
  381.                 if (++byteschanged == 8)
  382.                    {     offset = j - cap - 7;
  383.                        cap = j + 1;
  384.                        loffset = offset - 31;
  385.                        if (offset > 30)
  386.                     offset = 31;
  387.                        loffset1 = loffset - 255;
  388.                        if (loffset > 254)
  389.                      loffset = 255;
  390.                        *compressed++ = (char)(0xE0 | offset);
  391.                        outbytes++;
  392.                        if (loffset >= 0)
  393.                           {     *compressed++ = (char)loffset;
  394.                       loffset = 0;
  395.                       outbytes++;
  396.                       if (loffset1 >= 0)
  397.                          {     *compressed++ = (char)loffset1;
  398.                              loffset1 = 0;
  399.                              outbytes++;
  400.                          }   
  401.                           }
  402.                        ptmp = current - byteschanged;
  403.                        for (l=0;l < byteschanged;l++)
  404.                      *compressed++ = *ptmp++;
  405.                        outbytes = outbytes + byteschanged;
  406.                        byteschanged = 0;
  407.                    }
  408.              }
  409.       }
  410.        if (byteschanged)
  411.       {     offset = j - cap - byteschanged;
  412.           loffset = offset - 31;
  413.           if (offset > 30)
  414.            offset = 31;
  415.                loffset1 = loffset - 255;
  416.                if (loffset > 254)
  417.            loffset = 255;
  418.                *compressed++ = bittab[byteschanged] | offset;
  419.                outbytes++;
  420.                if (loffset >= 0)
  421.                   {     *compressed++ = (char)loffset;
  422.               loffset = 0;
  423.               outbytes++;
  424.               if (loffset1 >= 0)
  425.                  {     *compressed++ = (char)loffset1;
  426.                      loffset1 = 0;
  427.                      outbytes++;
  428.                  }
  429.           }
  430.                ptmp = current - byteschanged; 
  431.                for (l=0;l < byteschanged;l++)
  432.            *compressed++ = *ptmp++;
  433.                outbytes = outbytes + byteschanged;
  434.  
  435.        }
  436.  
  437.        return(outbytes);         
  438.       
  439.