[comp.lang.pascal] Turbo Graphics Printing -- Thank you All.

jbb@mvaxcs1.cse.nau.edu (Jon Bonnell) (06/12/91)

Thanks to everyone out there that helped me with this.  Here is the unit.
The unit is set to printout to Epson printers and LAserprinters.  

Following the Unit is also the quick code on saving the data to disk.
 
Thanks again to everyone that sent me mail and especially Ron Mead and
Gary Kleman (the latter who sent me the Unit).

---------------------------------------------------------------------
printer.  It was originally from compuserve, I picked it up on the
Borland BBS.  

By the way, I found that for a proper aspect ratio (ie circles on the
screen are circles on the paper) for EGAHI (640 x 350) you want to pass
the parameter (mode) which causes the printer to print graphics at
90 dots per inch.  This is 6 or 4 on some printers.

Hope this helps.

Gary Kleman
Kleman@magnus.acs.ohio-state.edu



Here is the unit.
<-----Snip here --------------------->
{
The  following example routines are public domain  programs  that
have  been uploaded to our Forum on CompuServe.  As a courtesy to
our  users  that  do not have  immediate  access  to  CompuServe,
Technical Support distributes these routines free of charge.

However,  because these routines are public domain programs,  not
developed by Borland International,  we are unable to provide any
technical support or assistance using these routines. If you need
assistance   using   these   routines,    or   are   experiencing
difficulties,  we  recommend  that you log  onto  CompuServe  and
request  assistance  from the Forum members that developed  these
routines.
}

Unit GraphPRN;

Interface

Uses Graph,     { Used to get the Image from the Screen }
     Printer2;  { Used to circumvent DOS's striping of  }
                { $1A from output stream ( a MUST for   }
                { Graphics output! ).                   }

Procedure HardCopy (Gmode: Integer);
{ Procedure HardCopy prints the current ViewPort    }
{   To an IBM or Epson compatible printer.          }
{                                                   }
{ Valid Gmode numbers are :                         }
{     -4 to -1 for Epson and IBM Graphic Printers   }
{      0 to 7  for Epson Printers                   }

Implementation

Procedure HardCopy {Gmode: Integer};

Const
   Bits : Array [0..7] of Byte = (128,64,32,16,8,4,2,1);


Var
    X,Y,YOfs         : Integer;
    BitData,MaxBits : Byte;
    Vport           : ViewPortType;
    Height, Width   : Word;
    HiBit, LoBit    : Char;
    LineSpacing,
    GraphixPrefix   : String[10];

Begin
  LineSpacing   := #27+'3'+#24; { 24/216 inch line spacing    }
  Case Gmode Of
       -1: GraphixPrefix := #27+'K'; { Std. Density           }
       -2: GraphixPrefix := #27+'L'; { Double Density         }
       -3: GraphixPrefix := #27+'Y'; { Dbl. Density Dbl. Speed}
       -4: GraphixPrefix := #27+'Z'; { Quad. Density          }
     0..7: GraphixPrefix := #27+'*'+Chr(Gmode);{ 8-Pin Bit Img}
    Else
     Exit;
  End;
  GetViewSettings( Vport );
  Height := Vport.Y2 - Vport.Y1;
  Width  := ( Vport.X2 + 1 ) - Vport.X1;
  HiBit := Chr(Hi(Width));
  LoBit := Chr(Lo(Width));
  Write( LST, LineSpacing );
  Y := 0;
  While Y < Height Do
  Begin
     Write( LST,GraphixPrefix,LoBit,HiBit );
     For X := 0 to Width-1 Do
     Begin
        BitData := 0;
        If y + 7 <= Height
          Then MaxBits := 7
        Else
          MaxBits := Height - Y;
        For YOfs := 0 to MaxBits do
        Begin
         If GetPixel( X, YOfs+Y ) > 0
           Then BitData := BitData or Bits[YOfs];
        End;
        Write( LST, Chr(BitData) );
     End;
     WriteLn ( LST );
     Inc(Y,8);
  End;
End;
End.

*****  Type this to the a second file "Printer2.Pas" *********


{      This Unit is a replacement for the Printer unit that   }
{ came with Turbo Pascal Version 4.  It's purpose is two      }
{ fold.  It will allow a user to change the printer port that }
{ the LST file is writing to on the fly.  This takes the      }
{ place of LstOutPtr and the routine on page 369 of the Turbo }
{ Pascal Version 3 manual.  The second purpose of this unit   }
{ is that it will also circumvent DOS's stripping of a Ctrl-Z }
{ ($1A, the End Of File character) when writing to the        }
{ printer as an ASCII device.  Ctrl-Z was usually sent as     }
{ part of a graphics string to a printer.  In version 3.0 of  }
{ Turbo Pascal an ASCII device was opened in binary mode, and }
{ in version 4 an ASCII device is opened in ASCII mode and    }
{ DOS thus strips a Ctrl-Z.                                   }
{                                                             }
{      This also provides a good example of a Text file       }
{ device driver.                                              }
{                                                             }
{      Type this to a file called PRINTER2.PAS                }

Unit Printer2;

Interface

Uses DOS;                                  { for using INTR() }

Var
  LST : Text;                      { Public LST file variable }

Procedure SetPrinter( Port:Byte );
{      SetPrinter sets the printer number to Port where Port  }
{ is 'n' in 'LPTn'.  ie.  To write to LPT1: SetPrinter(1),    }
{ for LPT2: SetPrinter(2).  SetPrinter changes the Port that  }
{ subsequent Write operations will write to.  This lets you   }
{ change the printer that you are printing to on the fly.     }

Implementation

{      The following routines MUST be FAR calls because they  }
{ are called by the Read and Write routines.  (They are not   }
{ Public (in the implementation section ) because they should }
{ only be accessed by the Read and Write routines.            }

{$F+}

{      LSTNoFunction performs a NUL operation for a Reset or  }
{ Rewrite on LST (Just in case)                               }

Function LSTNoFunction( Var F: TextRec ): integer;
Begin
  LSTNoFunction := 0;                    { No error           }
end;

{      LSTOutputToPrinter sends a the output to the Printer   }
{ port number stored in the first byte or the UserData area   }
{ of the Text Record.                                         }

Function LSTOutputToPrinter( Var F: TextRec ): integer;
var
  Regs: Registers;
  P : word;
begin
  With F do
  Begin
    P := 0;
    Regs.AH := 16;
    While (P < BufPos) and ((regs.ah and 16) = 16) do
    Begin
      Regs.AL := Ord(BufPtr^[P]);
      Regs.AH := 0;
      Regs.DX := UserData[1];
      Intr($17,Regs);
      Inc(P);
    end;
    BufPos := 0;
  End;
  if (Regs.AH and 16) = 16 then
    LSTOutputToPrinter := 0              { No error           }
   else
     if (Regs.AH and 32 ) = 32 then
       LSTOutputToPrinter := 159         { Out of Paper       }
   else
       LSTOutputToPrinter := 160;        { Device write Fault }
End;

{$F-}

{      AssignLST both sets up the LST text file record as     }
{ would ASSIGN, and initializes it as would a RESET.  It also }
{ stores the Port number in the first Byte of the UserData    }
{ area.                                                       }

Procedure AssignLST( Port:Byte );
Begin
  With TextRec(LST) do
    begin
      Handle      := $FFF0;
      Mode        := fmOutput;
      BufSize     := SizeOf(Buffer);
      BufPtr      := @Buffer;
      BufPos      := 0;
      OpenFunc    := @LSTNoFunction;
      InOutFunc   := @LSTOutputToPrinter;
      FlushFunc   := @LSTOutputToPrinter;
      CloseFunc   := @LSTOutputToPrinter;
      UserData[1] := Port - 1;  { We subtract one because }
  end;                          { Dos Counts from zero.   }
end;


Procedure SetPrinter( Port:Byte ); { Documented above     }
Begin
  With TextRec(LST) do
    UserData[1] := Port - 1;{ We subtract one because DOS }
End;                        { Counts from zero.           }

Begin  { Initilization }
  AssignLST( 1 );           { Call assignLST so it works  }
end.                        { like Turbo's Printer unit   }
-----------------------end of Unit---------------------------

Saving and restoring a screen is a piece of cake.  First, you get the
size of the image.  Then you capture the image on the heap using a
pointer and GetMem (I got this from the BIGDEMO that comes with TP).
Then you can write the image as a string of bytes, ie 

  Offset := 0;
  while Offset < ImageSize do begin
    write( outfil,byte( ^Pointer+Offset ) );
    inc( Offset ); 
  end;
    ----From Alan Mead
-- 
Jon Bonnell                "Like I always say --
jbb@mvaxcs1.cse.nau.edu       Why Jack off when you can jack in?"

Disclaimer :NAU has no opinion and I have mine...