!============================================================!
! !
! EDWIN Device Driver for Bitmap Printers !
! !
! Alan Thomson: August 18, 1988 !
! !
!============================================================!
!
! Rev 001 AET+JGH Force form feeds between intermediate plots & epson init
!
from Edwin include Device
from Edwin include Icodes
from Edwin include Consts
from Edwin include Iprocs
from Edwin include pattern
from Imp include Lognames
from Imp include Heap
from Imp include TextUtils
!
! Devices
!
const byte Epson Printer = 1,
Laserjet Printer = 2,
Printronix Printer = 3,
Versatec Printer = 4
const integer Max Models = 12
const integer array Models (1:Max Models) =
{EPSON} 8060, 80120, 10060, 100120,
{LASERJET I} 2686, 2686150, 2686300,
{PRINTRONIX} 300,
{VERSATEC} 80, 81, 82,
{LASERJET II} 33440
const byte FF = 12, CR = 13, LF = 10, Plot = 5, Escape = 27
const byte Zero = 0, Two = 2
const integer HP Start X = 800, HP Start Y = 1100
own string(255) New Page = ""
own integer Page Number = 1
const string (*) Both = "BOTH"
const string (*) Start = "START"
const string (*) End = "END"
own integer Horizontal Map = 1
record format PointFm(integer x,y)
record format DataFm(record(PointFm) p, record(DataFm) name Next)
own record(DataFm) name First Point == 0
own record(DataFm) name Next Point == 0
own string(80) NAME
own integer SX = 0, SY = 0, Drawn = False, Colour = 1
own integer LX = 0, LY = 0
own integer WLX = 0, WLY = 0, WHX, WHY
own integer Start X, Start Y
own integer Shade Mode = Solid
own integer Colour Mode = Or Mode
own integer Res = 0
own integer Scan Bytes
own integer Size Y,Size X, Heap Start, Total Size
own integer Device = 0
own integer NPts = 0
byte map BitMap(integer Y, X)
result == Byte(HeapStart+(Size X*Y)+X)
end
routine Draw Line(integer TX,TY)
! This is algorithm 162 in the Collected Algorithms from CACM.
! It computes the code string required to move the pen of a
! digital incremental X-Y plotter from an initial point (SX,SY) to
! a terminal point (TX,TY) by the "best" approximation to the
! straight line between the points. The permitted elemental pen
! movement is to an adjacent point in a plane Cartesian point latice,
! diagonal moves permitted.
integer A, B, D, E, F, T, I, XMove, YMove, X, Y
const short array XCode(1:16) = 0,1,1,1,1,1,0,1,0,-1,-1,-1,-1,-1,0,-1
const short array YCode(1:16) = 1,1,0,1,0,-1,-1,-1,-1,-1,0,-1,0,1,1,1
! PY,PX+PY,PX,PX+PY,PX,PX+NY,NY,PX+NY,NY,NY+NX,NX,NX+NY,NX,NX+PY,PY,NX+PY
routine Mark
! make mark in line buffer - represented as a linear bit string
byte integer name B
integer Bit
if Horizontal Map = 1 start
B == Bitmap(SX,SY//8)
if Device = Epson Printer start
Bit = 16_01 << (SY&7)
else
Bit = 16_80 >> (SY&7)
finish
else
B == Bitmap(SY,SX//8)
Bit = 16_80 >> (SX&7)
finish
B = B&(~Bit) if Colour Mode = Replace Mode
B = B ! Bit if Colour # 0
end
! The following line can output diagnostics as CIF for plotting with ART
! Oper Message ("L CP; W 0".Itos(SX,1).Itos(SY,1).Itos(TX,1).Itos(TY,1).";")
Drawn = True
Mark and return if SX = TX and SY = TY
if SX < WLX then SX = WLX
if SY < WLY then SY = WLY
if TX > WHX then TX = WHX
if TY > WHY then TY = WHY
A = TX - SX
B = TY - SY
D = A + B
T = B - A
I = 0
if B >= 0 then I = 2
if D >= 0 then I = I + 2
if T >= 0 then I = I + 2
if A >= 0 then I = 8 - I else I = I + 10
A = -A if A < 0
B = -B if B < 0
F = A + B
D = B - A
if D >= 0 then T = A and D = -D else T = B
E = 0
XMove = XCode(I - 1)
YMove = YCode(I - 1)
X = XCode(I)
Y = YCode(I)
cycle
A = D + E
B = T + E + A
Mark
if B >= 0 start
E = A
F = F - 2
SX = SX + X
SY = SY + Y
else
E = E + T
F = F - 1
SX = SX + XMove
SY = SY + YMove
finish
exit if F <= 0
repeat
Mark
end
routine Test(integer name Low, High)
integer i
if Low > High start
i = Low
Low = High
High = i
finish
end
routine Draw Box(integer LX, LY, UX, UY)
integer X, Y, Highbyte, High bits, Lowbyte, Low bits, Shade
integer B, Disp, This Pat
byte name Thisbyte
LX = LX + 1
UX = UX - 1
return if UX < LX
! The following line can output diagnostics as CIF for plotting with ART
! Oper Message ("L CA; W 0".Itos(LX,1).Itos(LY,1).Itos(UX,1).Itos(UY,1).";")
Drawn = True
Shade = Shade Mode<<4
{ This is a solid box, outline boxes are filtered out by EDWIN before driver }
if Horizontal Map = 1 start
Lowbyte = LY>>3
Low bits = LY & 7
Highbyte = UY>>3
High bits = 7 - (UY & 7)
for X = LX, 1, UX cycle
This Pat = Patterns((X&16_F)!Shade)
! Special case of Low byte = Y = High Byte, ie. box of < 8 units
if Low byte = High Byte start
Thisbyte == BitMap(X,Low byte)
if Device = Epson Printer start
B = (16_FF<<Low bits)&255
B = B>>High bits & B
else
B = 16_FF>>Low bits
B = B<<High bits & B
finish
Thisbyte = Thisbyte&(~B) if Colour Mode = Replace Mode
if Colour # 0 start
Disp = 16_08!!((Low Byte&1)<<3)
Thisbyte = Thisbyte!((This Pat>>Disp)&B)
finish
else
! Special case of Y = Low byte removed from the loop
Thisbyte == BitMap(X,Low byte)
if Device = Epson Printer start
B = (16_FF<<Low bits)&255
else
B = 16_FF>>Low bits
finish
Thisbyte = Thisbyte&(~B) if Colour Mode = Replace Mode
if Colour # 0 start
Disp = 16_08!!((Low Byte&1)<<3)
Thisbyte = Thisbyte!((This Pat>>Disp)&B)
finish
! Main loop, zap byte at a time
Y = Low Byte + 1
while Y < High Byte cycle
Thisbyte == BitMap(X,Y)
Thisbyte = 0 if Colour Mode = Replace Mode
if Colour # 0 start
Disp = 16_08!!((Y&1)<<3)
Thisbyte = Thisbyte!((This Pat>>Disp)&255)
finish
Y = Y + 1
repeat
! Special case of Y = High byte removed from the loop
Thisbyte == BitMap(X,High Byte)
if Device = Epson Printer start
B = 16_FF>>High bits
else
B = (16_FF<<(High bits))&255
finish
Thisbyte = Thisbyte&(~B) if Colour Mode = Replace Mode
if Colour # 0 start
Disp = 16_08!!((High Byte&1)<<3)
Thisbyte = Thisbyte!((This Pat>>Disp)&B)
finish
finish
repeat
else
Lowbyte = LX>>3
Low bits = LX & 7
Highbyte = UX>>3
High bits = 7 - (UX & 7)
for Y = LY, 1, UY cycle
Disp = 16_08!!((Y&1)<<3)
for X = Lowbyte, 1, Highbyte cycle
Thisbyte == BitMap(Y,X)
B = 16_FF
if X = Lowbyte then B = B>>Low bits
if X = Highbyte then B = (B<<High Bits)&255
Thisbyte = Thisbyte&(~B) if Colour Mode = Replace Mode
if Colour # 0 start
This Pat = Patterns((X&16_F)!Shade)
Thisbyte = Thisbyte!((This Pat>>Disp)&255)
finish
repeat
repeat
finish
end
include "polyfill.hpl"
routine Draw Polygon
integer i
record(DataFm) name pp
record(PointFm) array Pts(1:NPts + 1)
if Npts > 1 start
pp == First Point
Pts(1) = First Point_p
SX = Pts(1)_x
SY = Pts(1)_y
for i = 2, 1, NPts cycle
Pts(i) = pp_p
Draw Line(pp_p_x, pp_p_y)
pp == pp_Next
repeat
Pts(NPts + 1) = Pts(1)
Draw Line(Pts(1)_x, Pts(1)_y)
Polyfill(NPts + 1, Pts)
finish
NPts = 0
end
routine Initialise(integer Version)
string(80) Param, Value, Device Name
real width, height
integer index=0, i, VTRes
integer Rotation = -1
for i = 1,1,Max Models cycle
Index = i and exit if Models(i) = Version
repeat
Dev Data_Type = Version
Start X = HP Start X
Start Y = HP Start Y
if Index < 5 start
DEV DATA_NAME = "an Epson printer"
Device Name = "Epson"
VTRes = 72
if Version = 8060 start
NAME = "FX80"
Res = 60
DEV DATA_DVX = 500
else if Version = 80120
NAME = "FX80HR"
Res = 120
DEV DATA_DVX = 1000
else if Version = 10060
NAME = "FX100"
Res = 60
DEV DATA_DVX = 795
else
NAME = "FX100HR"
Res = 120
DEV DATA_DVX = 1590
finish
Device = Epson Printer
DEV DATA_DVY = 684
else if Index < 8
DEV DATA_NAME = "an HP 2686A LaserJet printer"
Device Name = "HP 2686A LaserJet"
Device = Laserjet Printer
NAME = itos(Version,0)
DEV DATA_DVX = 767
DEV DATA_DVY = 590
if Version = 2686 start
Res = 100
else if Version = 2686150
Res = 150
else
Res = 300
finish
VTRes = Res
else if Index = 8
Horizontal Map = 0
DEV DATA_NAME = "a Printronix printer"
Device Name = "Printronix"
Device = Printronix Printer
NAME = itos(dev data_type,0)
DEV DATA_DVX = 791
DEV DATA_DVY = 779
VTRes = 72
Res = 60
else if Index < 12
DEV DATA_NAME = "a Versatec printer"
Device Name = "Versatec"
Device = Versatec Printer
if Version = 80 start
Res = 200
Height = 10.55
Scan Bytes = 264
else if Version = 81
Res = 100
Height = 10.23
Scan Bytes = 128
else
Res = 100
Height = 10.55
Scan Bytes = 132
finish
VTRes = Res
NAME = itos(dev data_type,0)
DEV DATA_DVY = Int(Res * Height)
DEV DATA_DVX = Int(VTRes*36.7/2.54)
else
DEV DATA_NAME = "HP LaserJet Series II printer"
Device Name = "HP Laserjet Series II"
Device = Laserjet Printer
NAME = itos(Version,0)
DEV DATA_DVX = 1575
DEV DATA_DVY = 1088
Start X = 120
Start Y = 0
Res = 150
VTRes = Res
finish
NAME = "EDWIN_".NAME
begin
on event 3,4 start
Oper Message("Error in ".Device Name." paper size specification")
-> continue
finish
Param = NAME."_X"
value = translate(Param)
if value # Param start
Width = Stor(Value) / 25.4
DEV DATA_DVX = Int(Res * Width)
finish
continue:
end
begin
on event 3,4 start
Oper Message("Error in ".Device Name." paper size specification")
-> continue
finish
Param = NAME."_Y"
value = translate(Param)
if value # Param start
Height= Stor(Value) / 25.4
DEV DATA_DVY = Int(VTRes * Height)
finish
continue :
end
DEV DATA_MVX = DEV DATA_DVX
DEV DATA_MVY = DEV DATA_DVY
DEV DATA_ARF = Round(VTRes*100/Res)
DEV DATA_NUM CHAR SIZES = 255
DEV DATA_Y Units Per CM = VTRes/2.54
DEV DATA_X Units Per CM = Res/2.54
if device = Laserjet Printer start
Start X = Int(Res/100 * Start X)
Start Y = Int(Res/100 * Start Y)
finish
Read Patterns(Res)
if Horizontal Map = 1 start
Rotation = 1 if Device = Epson Printer
Rotate Pattern(Patterns(i*16),Rotation) for i = 1, 1, Max Pat
finish
if Viewing = 0 start
Set Device(NAME)
TTMode(1)
finish
New Page = Translate(NAME."_NEWPAGE")
ToUpper(New Page)
if Device # Versatec Printer start
TTput(FF) if New Page = Both or New Page = Start
if Device = Epson Printer start
unless Translate(Name."_INITIALISE") = "NO" start
TTput (Escape) and TTput ('@') if Device = Epson Printer
finish
finish
else if Viewing = 0
TTput(0) for I = 1,1,Scan Bytes*Res*8
finish
end
routine Esc(string(255) S)
integer I
TTPut(Escape)
TTPut(Charno(s,i)) for i = 1, 1, Length(s)
end
routine OutPut BitMap
integer X
integer name Dummy
routine Printronix Print
integer LINE MAX = DEV DATA_MVX//8 + 1
integer LIM = LINE MAX // 3 * 3
string (255) LINE BUFF
integer P, J, LB, I
byte name B
! 3-bit inversion table
constbyteintegerarray inverse(0:7) =
2_000, 2_100, 2_010, 2_110, 2_001, 2_101, 2_011, 2_111
! 0 1 2 3 4 5 6 7
for I = DEV DATA_MVY, -1, 0 cycle
LB = ADDR (LINE BUFF)
for J = ADDR(BitMap(I,0)), 3, ADDR(BitMap(I,LIM)) cycle
P = (((BYTE INTEGER(J)<< 8) ! BYTE INTEGER(J+1)) << 8) ! BYTE INTEGER (J+2)
BYTE INTEGER (LB + 4) = (P&63); P = P >> 6
BYTE INTEGER (LB + 3) = (P&63); P = P >> 6
BYTE INTEGER (LB + 2) = (P&63); P = P >> 6
BYTE INTEGER (LB + 1) = (P&63)
LB = LB + 4
repeat
LENGTH(LINE BUFF) = LB - ADDR(LINE BUFF)
if LIM#LINE MAX start
P = 0
for J = LIM+1, 1, LINE MAX cycle
P = (P<<8)!BitMap(I,J)
repeat
P = P << (8*(3-(LINE MAX - LIM)))
for J = 18, -6, 0 cycle
LINE BUFF = LINE BUFF.TO STRING(((P>>J)&63))
repeat
finish
! Strip trailing spaces (represented by binary zero)
B == LENGTH(LINE BUFF)
B = B-1 while B>0 and CHARNO(LINE BUFF, B)=0
! Add various bits and characters required by Printronix printer
for j = addr(line buff)+1,1,lb cycle
p = byte integer(j)
byte integer(j) = inverse(p&7)<<3 ! inverse(p>>3) ! 64
repeat
ttput(charno(line buff,j)) for J = 1, 1, length(line buff)
ttput(plot); ttput (NL)
repeat
end
routine Epson Print
integer Op = 'K', Line Feed = 24, n1,n2
integer X, Y, right, N Dots
Op = 'L' if Res = 120
for Y = DEV DATA_MVY//8, -1, 0 cycle
right = DEV DATA_MVX
while right >= 0 cycle
exit if Bitmap(Right,Y) # 0
right = right - 1
repeat
if right # -1 start
N Dots = Right+1
n2 = N Dots//256
n1 = N Dots - (n2 * 256)
TTput(Escape); TTput(Op); TTput(n1); TTput(n2)
TTPut(Bitmap(X,Y)) for X = 0, 1, Right
TTPut(CR)
finish
TTput(Escape); TTput('J'); TTput(Line Feed)
repeat
ttput(CR)
end
routine Versatec Print
byte name Data == Byte(HeapStart)
integer Ypos, X, Y, Start = 0, Fill = 0
Ypos = DEV DATA_MVY//8
if Ypos < Scan Bytes -1 start
Fill = Scan Bytes - (YPos+2)
finish
for X = 0, 1, DEV DATA_MVX cycle
TTPut(Data[Y]) for Y = Start, 1, Ypos
if Fill # 0 start
TTPut(0) for Y = 1, 1, Fill
finish
Start = Start + Size X
YPos = YPos + Size X
repeat
end
routine Laser Print
integer X, Y, Right
Esc("*t".ItoS(Res,0)."R")
Esc("&a".ItoS(Start X,0)."H")
Esc("&a".ItoS(Start Y,0)."V")
Esc("*r1A")
for X = 0, 1, DEV DATA_MVX cycle
ttput(CR)
ttput(NL)
Esc("&a-1R")
Right = DEV DATA_MVY//8
Right = Right - 1 while Right > 1 and Bitmap(X,Right) = 0
Esc("*b".ItoS(1 + Right,0)."W")
TTPut(Bitmap(X,Y)) for Y = 0, 1, Right
repeat
Esc("*rB")
ttput(CR)
end
if Page Number > 1 start
if Device # Versatec Printer start
TTput(FF)
else
TTput(0) for X = 1,1,Scan Bytes*Res*8
finish
finish
Page Number = Page Number + 1
if Device = Epson Printer start
Epson Print
else if Device = Laserjet Printer
Laser Print
else if Device = Printronix Printer
Printronix Print
else if Device = Versatec Printer
Versatec Print
finish
flush output
Dummy == Integer(HeapStart)
Dummy[X] = 0 for X = 0, 1, Total Size//4-1
Drawn = False
end
routine Append(integer X, Y)
if NPts = 0 start
First Point_p_x = X
First Point_p_y = Y
Next Point == First Point
NPts = 1
finish
return if X = SX and Y = SY
if Next Point_Next == nil start
Next Point_Next == new(Next Point)
Next Point == Next Point_Next
Next Point_Next == nil
else
Next Point == Next Point_Next
finish
Next Point_p_x = X
Next Point_p_y = Y
NPts = NPts + 1
SX = X
SY = Y
end
external routine BitMaps alias "EDWIN___Z" (integer Com, X, Y)
integer name Dummy
switch Att(0:Att Maximum)
switch Command(0:Max Com)
Draw Polygon if NPts # 0 and (Com = 10 or Com < 5)
-> Command(Com)
Command(Dev Initialise):
Initialise(X)
First Point == new(Next Point)
First Point_Next == nil
if Horizontal Map = 1 start
Size X = DEV DATA_MVY//8+1
Size Y = DEV DATA_MVX+1
else
Size X = DEV DATA_MVX//8+1
Size Y = DEV DATA_MVY+1
finish
Total Size = ((Size X*Size Y)+3)&(~3)
HeapStart = Get Space(Total Size)
Dummy == Integer(HeapStart)
Dummy[X] = 0 for X = 0, 1, Total Size//4-1
Drawn = False
WHX = DEV DATA_MVX
WHY = DEV DATA_MVY
Page Number = 1
return
Command(Dev Terminate):
if Drawn = True start
OutPut BitMap
if Device # Versatec Printer start
TTput(FF) if New Page = Both or New Page = End
else if Viewing = 0
TTput(0) for X = 1,1,Scan Bytes*Res*8
finish
finish
Flush Output
Dispose(HeapStart)
return
Command(Dev Newframe):
OutPut BitMap if Drawn = True
return
Command(Dev Move):
Sx = X; Sy = Y
return
Command(Dev Line):
if Shade Mode = 0 start
Draw Line(X, Y)
else
Append(X,Y)
finish
return
Command(Dev Char):
signal 14, 14
Command(Dev Attribute):
if 0 <= X <= Att Maximum start
-> Att(X)
Att(Att Colour):
Y = 1 if Y # 0
Colour = Y
return
Att(Att Colour Mode):
if Y = Replace Mode or Y = Or Mode then Colour Mode = Y
return
Att(Att Shade Mode):
Y = Solid unless 0 <= Y < 32
Shade Mode = Y
return
Att(*):
finish
return
Command(Dev Low WB):
WLX = X; WLY = Y
return
Command(Dev High WB):
WHX = X; WHY = Y
return
Command(Dev Low Box):
LX = X; LY = Y
return
Command(Dev High Box):
Test(LX, X)
Test(LY,Y)
return if LX > WHX or X < WLX or LY > WHY or Y < WLY
LX = WLX if LX < WLX
LY = WLY if LY < WLY
X = WHX if X > WHX
Y = WHY if Y > WHY
Draw Box(LX, LY, X, Y)
! Now outline it
return if Colour = 0
SX = LX
SY = LY
Draw Line(X,LY)
Draw Line(X,Y)
Draw Line(LX,Y)
Draw Line(LX,LY)
return
Command(*):
end
endoffile