!============================================================! ! ! ! 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