--d.wyatt December 11, 1980 9:34 AM --nbitmapfns.mesa DIRECTORY BitBltDefs: FROM "BitBltDefs", LongDefs: FROM "LongDefs", --long BITBLT different for D0,Alto GeneralDisplayDefs: FROM "GeneralDisplayDefs", GraphicsDefs: FROM "GraphicsDefs", InlineDefs: FROM "InlineDefs", SystemDefs: FROM "SystemDefs", SegmentDefs: FROM "SegmentDefs"; BitmapFns: PROGRAM IMPORTS LongDefs, InlineDefs, SegmentDefs, SystemDefs EXPORTS GraphicsDefs = BEGIN OPEN GeneralDisplayDefs; Machine: SegmentDefs.MachineType = SegmentDefs.GetMemoryConfig[].AltoType; DMachine: BOOLEAN = (Machine = D0) OR (Machine = Dorado); Screen: POINTER TO GraphicsDefs.Bitmap ← NIL; Scale: PROCEDURE [factor,c: CARDINAL] RETURNS [CARDINAL] = INLINE BEGIN RETURN[(CARDINAL[c*factor])/10];END; --data structures for D0 style color display colorData: TYPE = MACHINE DEPENDENT RECORD [ addr: [0..16), r,g,b,unused: BOOLEAN, data: [0..256) ]; colorEntry: TYPE = RECORD [ red,green,blue: colorData ]; colorTable: TYPE = RECORD --must be hexAligned [ front: ARRAY [0..2) OF UNSPECIFIED, entry: ARRAY [0..16) OF colorEntry, back: ARRAY [0..10) OF UNSPECIFIED, hexAlignPad: ARRAY [0..16) OF UNSPECIFIED ]; --data structures for D1 style color display from GeneralDisplayDefs --data structure for Alto type displays DCB: TYPE = MACHINE DEPENDENT RECORD [ Link: POINTER TO DCB, Resolution: [0..1], Invert: [0..1], Offset: [0..100B), Width: [0..400B), Bitmap: POINTER TO ARRAY OF UNSPECIFIED, Long: BOOLEAN, Height: [0..77777B], LongBitmap: LONG POINTER TO ARRAY OF UNSPECIFIED ]; DCBSeal: POINTER = LOOPHOLE[177423B]; --global variables ColorBitmap: POINTER TO POINTER = LOOPHOLE[414B]; ColorBitmapBank: POINTER TO CARDINAL = LOOPHOLE[415B]; ColorMap: POINTER TO POINTER = LOOPHOLE[416B]; ColorMapBank: POINTER TO CARDINAL = LOOPHOLE[417B]; ColorCtrlBlk: ColorControlBlock; AChanCtrlBlk: ChannelControlBlock; ColorMonitor: MonitorControlBlock; cx: ARRAY [0..SIZE[colorTable]] OF UNSPECIFIED; ColorTable: POINTER TO colorTable ← @cx[LOOPHOLE[@cx,CARDINAL] MOD 16]; ColorTable8: POINTER TO ATableImage; x,xx: ARRAY [0..SIZE[BitBltDefs.BBTable]] OF UNSPECIFIED; DCBhead: POINTER TO POINTER TO DCB = LOOPHOLE[420B]; SetPointBLT: POINTER TO BitBltDefs.BBTable ← @x[LOOPHOLE[@x,CARDINAL] MOD 2]; BLT: POINTER TO BitBltDefs.BBTable ← @xx[LOOPHOLE[@xx,CARDINAL] MOD 2]; DefaultAllocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER] ← BEGIN IF DMachine THEN RETURN [SegmentDefs.LongDataSegmentAddress[ SegmentDefs.NewDataSegment[ SegmentDefs.DefaultXMBase,(nwords+255)/256]]] ELSE RETURN[SystemDefs.AllocateSegment[nwords]]; END; DefaultFree: PROCEDURE [XVM: LONG POINTER] ← BEGIN IF DMachine THEN SegmentDefs.DeleteDataSegment[SegmentDefs.LongVMtoDataSegment[XVM]] ELSE SystemDefs.FreeSegment[InlineDefs.LowHalf[XVM]]; END; SetXMAlloc: PUBLIC PROCEDURE [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER]] = BEGIN DefaultAllocate ← Allocate; DefaultFree ← Free; END; GetXMAlloc: PUBLIC PROCEDURE RETURNS [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER]] = BEGIN RETURN[DefaultAllocate,DefaultFree]; END; --even dot distribution, maximum flicker --GrayThresholds: ARRAY [0..16) OF CARDINAL ← -- [ 00,08,02,10, -- 14,04,12,06, -- 03,11,01,09, -- 13,07,15,05 -- ]; GrayThresholds: ARRAY [0..16) OF CARDINAL ← [ 15,01,05,11, --minimum flicker 06,08,12,02, 07,09,13,03, 14,00,04,10 ]; GrayLevel: CARDINAL ← 0; Gray0,Gray1,Gray2,Gray3: CARDINAL ← 177777B; SetGrayThresholds: PUBLIC PROCEDURE [new: POINTER TO ARRAY [0..0) OF CARDINAL, outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 1=> BEGIN i: CARDINAL; FOR i IN [0..16] DO GrayThresholds[i] ← new[i]; ENDLOOP; END; 4=> BEGIN i: CARDINAL; ColorTable.front ← ALL[0]; ColorTable.back ← ALL[0]; FOR i IN [0..17B] DO ColorTable.entry[i].red ← [i,TRUE,FALSE,FALSE,FALSE,new[i]]; ColorTable.entry[i].green ← [i,FALSE,TRUE,FALSE,FALSE,new[i]]; ColorTable.entry[i].blue ← [i,FALSE,FALSE,TRUE,FALSE,new[i]]; ENDLOOP; END; 8=> BEGIN i: CARDINAL; FOR i IN [0..1024) DO ColorTable8[i].zeroHigh ← ColorTable8[i].zeroLow ← 0; ENDLOOP; FOR i IN [0..256) DO ColorTable8[i*4] ← [0,new[i] MOD 16,new[i],0,new[i],new[i]/16]; ENDLOOP; pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE]; END; ENDCASE=>ERROR; END; halftoneWord: TYPE = MACHINE DEPENDENT RECORD [ unused: [0..7777B], val1,val2,val3,val4: BOOLEAN ]; SetGrayLevel: PUBLIC PROCEDURE [intensity: CARDINAL, outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 1=> BEGIN h: halftoneWord; value,scanline: CARDINAL; IF GrayLevel = intensity THEN RETURN; GrayLevel ← intensity; FOR scanline IN [0..4) DO h.val1 ← intensity <= GrayThresholds[scanline*4+0]; h.val2 ← intensity <= GrayThresholds[scanline*4+1]; h.val3 ← intensity <= GrayThresholds[scanline*4+2]; h.val4 ← intensity <= GrayThresholds[scanline*4+3]; h.unused ← 0; value ← LOOPHOLE[h]; value ← value + value*16; value ← value + value*256; SELECT scanline FROM 0=> Gray0←value; 1=> Gray1←value; 2=> Gray2←value; 3=> Gray3←value; ENDCASE; ENDLOOP; END; 4=> BEGIN intensity ← 15 - MIN[intensity,15]; Gray0 ← Gray1 ← Gray2 ← Gray3 ← intensity + intensity*16 + intensity*256 + intensity*4096; END; 8=> Gray0 ← Gray1 ← Gray2 ← Gray3 ← intensity + intensity*256; ENDCASE=>ERROR; BLT.gray0 ← Gray0;BLT.gray1 ← Gray1; BLT.gray2 ← Gray2;BLT.gray3 ← Gray3; END; --a hack --only works for 8 bits/pixel. pattern is 8 bits, set low, high, gray0-gray3 SetHalfTone: PUBLIC PROCEDURE[black,white: CARDINAL, pattern: CARDINAL] = BEGIN i: CARDINAL; highblack: CARDINAL ← black * 256; highwhite: CARDINAL ← white * 256; gray: ARRAY[0..3] OF CARDINAL ← ALL[0]; FOR i IN [0..3] DO gray[i] ← (IF InlineDefs.BITAND[pattern,1]=0 THEN black ELSE white); gray[i] ← (IF InlineDefs.BITAND[pattern,2]=0 THEN gray[i]+highblack ELSE gray[i]+highwhite); pattern ← pattern/4; --shift it ENDLOOP; Gray0 ← gray[0]; Gray1 ← gray[1]; Gray2 ← gray[2]; Gray3 ← gray[3]; BLT.gray0 ← Gray0;BLT.gray1 ← Gray1; BLT.gray2 ← Gray2;BLT.gray3 ← Gray3; END; SetRed: PUBLIC PROCEDURE[gray: [0..256),newVal: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 8=>BEGIN ColorTable8[gray*4].redHigh ← newVal/16; ColorTable8[gray*4].redLow ← newVal MOD 16; pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE]; END; ENDCASE; END; SetGreen: PUBLIC PROCEDURE[gray: [0..256),newVal: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 8=>BEGIN ColorTable8[gray*4].green ← newVal; pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE]; END; ENDCASE; END; SetBlue: PUBLIC PROCEDURE[gray: [0..256),newVal: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 8=>BEGIN ColorTable8[gray*4].blue ← newVal; pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE]; END; ENDCASE; END; GetRed: PUBLIC PROCEDURE[gray: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] RETURNS [CARDINAL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 8=>RETURN[ColorTable8[gray*4].redHigh*16+ColorTable8[gray*4].redLow]; ENDCASE=>RETURN[0]; END; GetGreen: PUBLIC PROCEDURE[gray: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] RETURNS [CARDINAL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 8=>RETURN[ColorTable8[gray*4].green]; ENDCASE=>RETURN[0]; END; GetBlue: PUBLIC PROCEDURE[gray: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] RETURNS [CARDINAL] = BEGIN IF outputDevice = NIL THEN outputDevice ← Screen; SELECT outputDevice.nBitsPerPixel FROM 8=>RETURN[ColorTable8[gray*4].blue]; ENDCASE=>RETURN[0]; END; GetGrayBlock: PUBLIC PROCEDURE RETURNS [gray0,gray1,gray2,gray3: CARDINAL] = BEGIN RETURN [Gray0,Gray1,Gray2,Gray3];END; SetDefaultBitmap: PUBLIC PROCEDURE [width,height: CARDINAL] = BEGIN IF Screen = NIL THEN --ought to be able to return a couple of screens... Screen ← SystemDefs.AllocateHeapNode[SIZE[GraphicsDefs.Bitmap]]; Screen.nBits ← width; Screen.nLines ← height; END; TurnOnGraphics: PUBLIC PROCEDURE [bitsPerPixel: CARDINAL ← 1,portraitMode: BOOLEAN ← TRUE,scalePercent: CARDINAL ← 100] RETURNS [POINTER TO GraphicsDefs.Bitmap] = BEGIN scaleFactor: CARDINAL ← scalePercent/10; IF Screen = NIL THEN --ought to be able to return a couple of screens... BEGIN Screen ← SystemDefs.AllocateHeapNode[SIZE[GraphicsDefs.Bitmap]]; SELECT bitsPerPixel FROM 1=> IF portraitMode THEN BEGIN Screen.nBits ← (608*10)/scaleFactor; Screen.nLines ← (800*10)/scaleFactor; END ELSE BEGIN Screen.nBits ← (800*10)/scaleFactor; Screen.nLines ← (608*10)/scaleFactor; END; 4,8=> IF portraitMode THEN BEGIN Screen.nBits ← (640*10)/scaleFactor; Screen.nLines ← (480*10)/scaleFactor; END ELSE BEGIN Screen.nBits ← (480*10)/scaleFactor; Screen.nLines ← (640*10)/scaleFactor; END; ENDCASE=> ERROR; END; Screen.nBitsPerPixel ← bitsPerPixel; Screen.portraitMode ← portraitMode; Screen.scaleFactor ← scaleFactor; Screen.nWords ← IF portraitMode THEN 2*bitsPerPixel*((Scale[scaleFactor,Screen.nBits]+31)/32) ELSE 2*bitsPerPixel*((Scale[scaleFactor,Screen.nLines]+31)/32) ; SetPointBLT↑ ← [ptrs: long,pad: 0,sourcealt: FALSE,sourcetype: gray, dw: Screen.nBitsPerPixel,dh: 1, destalt: ,function: ,dbca: NIL,dbmr: ,dlx:,dty:, gray0: 177777B,gray1: 177777B,gray2: 177777B,gray3:177777B, sbca: NIL,unused: 0,sbmr: 0,slx:,sty:,slbca:,dlbca:]; BLT↑ ← [ptrs: long,pad: 0,sourcealt: FALSE,sourcetype: gray, dw: ,dh: , destalt: ,function: ,dbca: NIL,dbmr: ,dlx:,dty:, gray0: 177777B,gray1: 177777B,gray2: 177777B,gray3:177777B, sbca: NIL,unused: 0,sbmr: 0,slx:,sty:,slbca:,dlbca:]; SELECT Screen.nBitsPerPixel FROM 1=> BEGIN myDCB: POINTER TO DCB ← IF DMachine THEN SystemDefs.AllocateHeapNode[SIZE[DCB]+1] ELSE SystemDefs.AllocateSegment[Screen.nWords*Screen.nLines+SIZE[DCB]+1]; myScreen: LONG POINTER TO ARRAY OF UNSPECIFIED ← IF DMachine THEN DefaultAllocate[Screen.nWords*Screen.nLines+1] ELSE NIL; IF InlineDefs.BITAND[LOOPHOLE[InlineDefs.LowHalf[myScreen],CARDINAL],1]=1 THEN myScreen←myScreen+1; IF InlineDefs.BITAND[LOOPHOLE[myDCB,CARDINAL],1]=1 THEN myDCB←myDCB+1; IF DMachine THEN BEGIN Screen.bank←InlineDefs.HighHalf[myScreen]; Screen.bits←InlineDefs.LowHalf[myScreen]; END ELSE BEGIN Screen.bank ← 0; Screen.bits ← LOOPHOLE[myDCB+SIZE[DCB]]; END; myDCB↑←[Link: LOOPHOLE[0],Resolution: 0,Invert: 0,Offset: 0, Width: Screen.nWords, Bitmap: IF DMachine THEN DCBSeal ELSE LOOPHOLE[Screen.bits], Long: DMachine,Height: Screen.nLines/2,LongBitmap: myScreen]; EraseArea[0,0,Screen.nBits,Screen.nLines]; DCBhead↑←myDCB; END; 4=> BEGIN normalThresholds: ARRAY [0..17B] OF CARDINAL ← [0,17,34,51,68,85,102,119,136,153,170,187,204,221,238,255]; SetGrayThresholds[LOOPHOLE[@normalThresholds]]; ColorBitmap↑ ← LOOPHOLE[0]; --InlineDefs.LowHalf[longP]; ColorBitmapBank↑ ← 4; --InlineDefs.HighHalf[longP]; ColorMap↑ ← ColorTable; ColorMapBank↑ ← 0; Screen.bank ← 4; --1; Screen.bits←LOOPHOLE[ColorBitmap↑]; EraseArea[0,0,Screen.nBits,Screen.nLines]; END; 8=> BEGIN normalThresholds: ARRAY [0..256) OF CARDINAL; i: CARDINAL; FOR i IN [0..256) DO normalThresholds[i] ← i;ENDLOOP; ColorTable8 ← SystemDefs.AllocateSegment[SIZE[ATableImage]]; Screen.bank ← 4; Screen.bits←NIL; ColorCtrlBlk ← [ ATable: ColorTable8, BTable: NIL,CTable: NIL,MiniMixer: NIL, VBlank: [VBtoVS: 3,VStoVS: 3],VStoVB: 20B,VisibleLines: 240, HRamMaxAddr: 379,HBlank: [HBLeadLength: 6,HSTrailAddr: 47B], HBTrailLength: 16B,PClock: [unused: 0,PClockMul: 130B,PClockDiv: 14B], reserved: 0 ]; AChanCtrlBlk ← [ NIL,Screen.nWords,MakeLongPointer[Screen.bits,Screen.bank], Screen.nLines/2,Screen.nBits+377B,MarginOffset[Ramtek525], [unused: 0, b24BitsPerPixel: FALSE,AByPass: FALSE,BByPass: FALSE,A8B2: TRUE, Resolution: full,Size8: TRUE,Size4:FALSE,Size2: FALSE,Size1: FALSE ] ]; ColorMonitor ← [ 177456B,[0,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE], @AChanCtrlBlk,NIL,@ColorCtrlBlk ]; EraseArea[0,0,Screen.nBits,Screen.nLines]; pMonitorHead↑ ← @ColorMonitor; SetGrayThresholds[LOOPHOLE[@normalThresholds]]; END; ENDCASE => ERROR; RETURN[Screen]; END; GetDefaultBitmapHandle: PUBLIC PROCEDURE RETURNS [POINTER TO GraphicsDefs.Bitmap] = BEGIN RETURN[Screen];END; --first, the dummy routines using default bitMap (Screen) PutPoint: PUBLIC PROCEDURE[x,y: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL]= BEGIN SetPoint[x,y,replace,b];END; ErasePoint: PUBLIC PROCEDURE [x,y: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetPoint[x,y,erase,b];END; XorPoint: PUBLIC PROCEDURE [x,y: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetPoint[x,y,invert,b];END; PutLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetLine[x1,y1,x2,y2,replace,b];END; EraseLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetLine[x1,y1,x2,y2,erase,b];END; XorLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetLine[x1,y1,x2,y2,invert,b];END; PutArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetArea[x1,y1,x2,y2,paint,b];END; EraseArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetArea[x1,y1,x2,y2,erase,b];END; XorArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetArea[x1,y1,x2,y2,invert,b];END; ReplaceArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetArea[x1,y1,x2,y2,replace,b];END; PutGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetGray[x1,y1,x2,y2,paint,b];END; EraseGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetGray[x1,y1,x2,y2,erase,b];END; XorGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetGray[x1,y1,x2,y2,invert,b];END; ReplaceGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN SetGray[x1,y1,x2,y2,replace,b];END; PutBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap] = BEGIN SetBitmap[b,x,y,paint,dest];END; EraseBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap] = BEGIN SetBitmap[b,x,y,erase,dest];END; XorBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap] = BEGIN SetBitmap[b,x,y,invert,dest];END; ReplaceBitmap: PUBLIC PROCEDURE[b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap]= BEGIN SetBitmap[b,x,y,replace,dest];END; --and the real guys SetPoint: PUBLIC PROCEDURE [x,y: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] = BEGIN logBitsPerPixel: CARDINAL; IF b = NIL THEN b ← Screen; logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; IF NOT x IN [0..b.nBits) THEN RETURN; IF NOT y IN [0..b.nLines) THEN RETURN; -- save your ass IF b.portraitMode THEN BEGIN x ← Scale[b.scaleFactor,x];y ← Scale[b.scaleFactor,y];END ELSE BEGIN t: CARDINAL ← Scale[b.scaleFactor,b.nLines-y];y ← Scale[b.scaleFactor,x];x ← t;END; SetPointBLT.function ← fn; SetPointBLT.dlbca ← MakeLongPointer[b.bits,b.bank]; SetPointBLT.dbmr ← b.nWords; SetPointBLT.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel]; SetPointBLT.dty ← y; LongDefs.BITBLT[SetPointBLT]; END; MakeLongPointer: PROCEDURE [ptr: POINTER,bank: UNSPECIFIED] RETURNS [LONG POINTER] = MACHINE CODE BEGIN END; SetLine: PUBLIC PROCEDURE [x1,y1,x2,y2: INTEGER,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] = BEGIN hstep,vstep,hsign,vsign,count: INTEGER; horizontal: BOOLEAN; xMax,yMax: INTEGER; logBitsPerPixel: CARDINAL; IF b = NIL THEN b ← Screen; logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; IF b.portraitMode THEN BEGIN x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2]; xMax ← Scale[b.scaleFactor,b.nBits];yMax ← Scale[b.scaleFactor,b.nLines]; END ELSE BEGIN t: CARDINAL; t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1];x1 ← t; t ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t; xMax ← Scale[b.scaleFactor,b.nLines];yMax ← Scale[b.scaleFactor,b.nBits]; END; SetPointBLT.function ← fn; SetPointBLT.dbmr ← b.nWords; SetPointBLT.dlbca ← MakeLongPointer[b.bits,b.bank]; hstep ← x1-x2; vstep ← y1-y2; hsign ← IF hstep >= 0 THEN 1 ELSE -1; vsign ← IF vstep >= 0 THEN 1 ELSE -1; horizontal←ABS[hstep] > ABS[vstep]; count ← IF horizontal THEN ABS[vstep]+(ABS[hstep]-ABS[vstep])/2 ELSE ABS[hstep]+(ABS[vstep]-ABS[hstep])/2 ; SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel];SetPointBLT.dty ← y2; IF INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN LongDefs.BITBLT[SetPointBLT]; UNTIL (x1 = x2) AND (y1 = y2) DO IF count >= ABS[vstep] THEN -- go horizontal BEGIN x2 ← x2 + hsign; count ← count - ABS[vstep]; IF horizontal AND INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN BEGIN SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel]; SetPointBLT.dty ← y2; LongDefs.BITBLT[SetPointBLT]; END; END ELSE BEGIN y2 ← y2+vsign; count ← count + ABS[hstep]; IF NOT horizontal AND INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN BEGIN SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel]; SetPointBLT.dty ← y2; LongDefs.BITBLT[SetPointBLT]; END; END; ENDLOOP; SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel];SetPointBLT.dty ← y2; IF INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN LongDefs.BITBLT[SetPointBLT]; END; SetArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] = BEGIN logBitsPerPixel: CARDINAL; IF b = NIL THEN b ← Screen; logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; IF INTEGER[x1] > INTEGER[x2] THEN BEGIN t: CARDINAL ← x1;x1 ← x2;x2 ← t;END; IF INTEGER[y1] > INTEGER[y2] THEN BEGIN t: CARDINAL ← y1;y1 ← y2;y2 ← t;END; IF INTEGER[x2] < 0 OR INTEGER[y2] < 0 OR INTEGER[x1] >= INTEGER[b.nBits] OR INTEGER[y1] >= INTEGER[b.nLines] THEN RETURN; x1 ← MAX[0,INTEGER[x1]];y1 ← MAX[0,INTEGER[y1]]; x2 ← MIN [x2,b.nBits-1];y2 ← MIN[y2,b.nLines-1]; IF b.portraitMode THEN BEGIN x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2]; END ELSE BEGIN t: CARDINAL; t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1]; x1 ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t; END; BLT.sourcetype ← gray; BLT.function ← fn; BLT.dlbca ← MakeLongPointer[b.bits,b.bank]; BLT.dbmr ← b.nWords; BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel]; BLT.dty ← y1; BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel]; BLT.dh ← (y2+1-y1); BLT.gray0 ← BLT.gray1 ← BLT.gray2 ← BLT.gray3 ← 177777B; LongDefs.BITBLT[BLT]; BLT.gray0 ← Gray0;BLT.gray1 ← Gray1; BLT.gray2 ← Gray2;BLT.gray3 ← Gray3; END; SetGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] = BEGIN logBitsPerPixel: CARDINAL; IF b = NIL THEN b ← Screen; logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; IF INTEGER[x1] > INTEGER[x2] THEN BEGIN t: CARDINAL ← x1;x1 ← x2;x2 ← t;END; IF INTEGER[y1] > INTEGER[y2] THEN BEGIN t: CARDINAL ← y1;y1 ← y2;y2 ← t;END; IF INTEGER[x2] < 0 OR INTEGER[y2] < 0 OR INTEGER[x1] >= INTEGER[b.nBits] OR INTEGER[y1] >= INTEGER[b.nLines] THEN RETURN; x1 ← MAX[0,INTEGER[x1]];y1 ← MAX[0,INTEGER[y1]]; x2 ← MIN [x2,b.nBits-1];y2 ← MIN[y2,b.nLines-1]; IF b.portraitMode THEN BEGIN x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2]; END ELSE BEGIN t: CARDINAL; t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1]; x1 ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t; END; BLT.sourcetype ← gray; BLT.function ← fn; BLT.dlbca ← MakeLongPointer[b.bits,b.bank]; BLT.dbmr ← b.nWords; BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel]; BLT.dty ← y1; BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel]; BLT.dh ← (y2+1-y1); BLT.sty ← 0; --DORADO looks here LongDefs.BITBLT[BLT]; END; MaskGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap] = BEGIN logBitsPerPixel: CARDINAL; IF b = NIL THEN b ← Screen; logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; IF INTEGER[x1] > INTEGER[x2] THEN BEGIN t: CARDINAL ← x1;x1 ← x2;x2 ← t;END; IF INTEGER[y1] > INTEGER[y2] THEN BEGIN t: CARDINAL ← y1;y1 ← y2;y2 ← t;END; IF INTEGER[x2] < 0 OR INTEGER[y2] < 0 OR INTEGER[x1] >= INTEGER[b.nBits] OR INTEGER[y1] >= INTEGER[b.nLines] THEN RETURN; x1 ← MAX[0,INTEGER[x1]];y1 ← MAX[0,INTEGER[y1]]; x2 ← MIN [x2,b.nBits-1];y2 ← MIN[y2,b.nLines-1]; IF b.portraitMode THEN BEGIN x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2]; END ELSE BEGIN t: CARDINAL; t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1]; x1 ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t; END; BLT.sourcetype ← andgray; BLT.function ← replace; BLT.dlbca ← MakeLongPointer[b.bits,b.bank]; BLT.dbmr ← b.nWords; BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel]; BLT.dty ← y1; BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel]; BLT.dh ← (y2+1-y1); BLT.slbca ← MakeLongPointer[b.bits,b.bank]; BLT.sbmr ← b.nWords; BLT.slx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel]; BLT.sty ← y1; LongDefs.BITBLT[BLT]; END; SetBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap, x,y: CARDINAL,fn: BitBltDefs.BBoperation,dest: POINTER TO GraphicsDefs.Bitmap] = BEGIN x2,y2: CARDINAL; sx,sy,dy: CARDINAL ← 0; logBitsPerPixel: CARDINAL; IF dest = NIL THEN dest ← Screen; logBitsPerPixel ← SELECT dest.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; x2 ← x+b.nBits-1; y2 ← y+b.nLines-1; IF x >= dest.nBits OR y >= dest.nLines THEN RETURN; IF x2 >= dest.nBits THEN x2 ← dest.nBits - 1; IF y2 >= dest.nLines THEN BEGIN dy ← y2-(dest.nLines-1);y2 ← dest.nLines-1;END; IF INTEGER[x] < 0 THEN BEGIN sx ← -x;x ← 0;END; IF INTEGER[y] < 0 THEN BEGIN sy ← -y;y ← 0;END; IF dest.portraitMode THEN BEGIN x ← Scale[dest.scaleFactor,x];y ← Scale[dest.scaleFactor,y];x2 ← Scale[dest.scaleFactor,x2];y2 ← Scale[dest.scaleFactor,y2]; sx ← Scale[dest.scaleFactor,sx];sy ← Scale[dest.scaleFactor,sy]; END ELSE BEGIN t: CARDINAL; t ← Scale[dest.scaleFactor,(dest.nLines-1)-y];y ← Scale[dest.scaleFactor,x]; x ← Scale[dest.scaleFactor,(dest.nLines-1)-y2]; y2 ← MIN[Scale[dest.scaleFactor,x2],y+Scale[dest.scaleFactor,b.nBits]-1];x2 ← MIN[t,x+Scale[dest.scaleFactor,b.nLines]-1]; sy ← Scale[dest.scaleFactor,sx];sx ← Scale[dest.scaleFactor,dy]; END; BLT.sourcetype ← block; BLT.function ← fn; BLT.dlbca ← MakeLongPointer[dest.bits,dest.bank]; BLT.dbmr ← dest.nWords; BLT.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel]; BLT.dty ← y; BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x),logBitsPerPixel]; BLT.dh ← (y2+1-y); BLT.slbca ← MakeLongPointer[b.bits,b.bank]; BLT.sbmr ← b.nWords; BLT.slx ← InlineDefs.BITSHIFT[sx,logBitsPerPixel]; BLT.sty ← sy; LongDefs.BITBLT[BLT]; END; PutGrayBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap, x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap ← NIL] = BEGIN x2,y2: CARDINAL; sx,sy,dy: CARDINAL ← 0; logBitsPerPixel: CARDINAL; IF dest = NIL THEN dest ← Screen; logBitsPerPixel ← SELECT dest.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; x2 ← x+b.nBits-1; y2 ← y+b.nLines-1; IF x >= dest.nBits OR y >= dest.nLines THEN RETURN; IF x2 >= dest.nBits THEN x2 ← dest.nBits - 1; IF y2 >= dest.nLines THEN BEGIN dy ← y2-(dest.nLines-1);y2 ← dest.nLines-1;END; IF INTEGER[x] < 0 THEN BEGIN sx ← -x;x ← 0;END; IF INTEGER[y] < 0 THEN BEGIN sy ← -y;y ← 0;END; IF dest.portraitMode THEN BEGIN x ← Scale[dest.scaleFactor,x];y ← Scale[dest.scaleFactor,y];x2 ← Scale[dest.scaleFactor,x2];y2 ← Scale[dest.scaleFactor,y2]; sx ← Scale[dest.scaleFactor,sx];sy ← Scale[dest.scaleFactor,sy]; END ELSE BEGIN t: CARDINAL; t ← Scale[dest.scaleFactor,(dest.nLines-1)-y];y ← Scale[dest.scaleFactor,x]; x ← Scale[dest.scaleFactor,(dest.nLines-1)-y2]; y2 ← MIN[Scale[dest.scaleFactor,x2],y+Scale[dest.scaleFactor,b.nBits]-1];x2 ← MIN[t,x+Scale[dest.scaleFactor,b.nLines]-1]; sy ← Scale[dest.scaleFactor,sx];sx ← Scale[dest.scaleFactor,dy]; END; --first, erase BLT.sourcetype ← block; BLT.function ← erase; BLT.dlbca ← MakeLongPointer[dest.bits,dest.bank]; BLT.dbmr ← dest.nWords; BLT.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel]; BLT.dty ← y; BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x),logBitsPerPixel]; BLT.dh ← (y2+1-y); BLT.slbca ← MakeLongPointer[b.bits,b.bank]; BLT.sbmr ← b.nWords; BLT.slx ← sx; BLT.sty ← sy; LongDefs.BITBLT[BLT]; --now, paint gray bits BLT.sourcetype ← andgray; BLT.function ← paint; LongDefs.BITBLT[BLT]; END; TransferRectangle: PUBLIC PROCEDURE [src,dest: POINTER TO GraphicsDefs.Bitmap, srcRectangle,destRectangle: POINTER TO GraphicsDefs.Rectangle, fn: BitBltDefs.BBoperation ← replace,type: BitBltDefs.BBsourcetype ← block] = BEGIN srcWidth,destWidth,srcHeight,destHeight: CARDINAL; myBitmap: GraphicsDefs.Bitmap; myRectangle: GraphicsDefs.Rectangle; svd: POINTER TO GraphicsDefs.Bitmap ← NIL; svdRectangle: POINTER TO GraphicsDefs.Rectangle; x,y,count: CARDINAL; dy: CARDINAL ← 0; logBitsPerPixel: CARDINAL ← SELECT dest.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3; funnyFinishProc: PROCEDURE = BEGIN BLT.slbca ← MakeLongPointer[dest.bits,dest.bank]; BLT.dlbca ← MakeLongPointer[svd.bits,svd.bank]; BLT.dbmr ← svd.nWords; BLT.slx ← BLT.sty ← 0; BLT.dlx ← svdRectangle.x1; BLT.dty ← svdRectangle.y1; BLT.dw ← destWidth; BLT.dh ← destHeight; BLT.sbmr ← dest.nWords; BLT.function ← fn; BLT.sourcetype ← type; LongDefs.BITBLT[BLT]; SystemDefs.FreeSegment[dest.bits]; END; --first check trivial exclusion IF (srcRectangle.x1 > INTEGER[src.nBits]) OR (INTEGER[srcRectangle.x2] < 0) OR (srcRectangle.y1 > INTEGER[src.nLines]) OR (INTEGER[srcRectangle.y2] < 0) OR (INTEGER[destRectangle.x2] < 0) OR (INTEGER[destRectangle.y2] < 0) THEN BEGIN gotcha: BOOLEAN; gotcha ← TRUE; RETURN; END; --clipping for safety, not accuracy (will cause distortion...) IF CARDINAL[destRectangle.x1] >= dest.nBits OR CARDINAL[destRectangle.y1] >= dest.nLines THEN RETURN; IF CARDINAL[destRectangle.x2] >= dest.nBits THEN destRectangle.x2 ← dest.nBits-1; IF CARDINAL[destRectangle.y2] >= dest.nLines THEN BEGIN dy ← destRectangle.y2-(dest.nLines-1); destRectangle.y2 ← dest.nLines-1; END; srcWidth ← (srcRectangle.x2 - srcRectangle.x1)+1; destWidth ← (destRectangle.x2 - destRectangle.x1)+1; srcHeight ← (srcRectangle.y2 - srcRectangle.y1)+1; destHeight ← (destRectangle.y2 - destRectangle.y1)+1; BLT.sourcetype ← type; BLT.function ← fn; BLT.dlbca ← MakeLongPointer[dest.bits,dest.bank]; BLT.dbmr ← dest.nWords; BLT.slbca ← MakeLongPointer[src.bits,src.bank]; BLT.sbmr ← src.nWords; IF srcWidth = destWidth AND srcHeight = destHeight THEN --easy BEGIN x1: CARDINAL ← destRectangle.x1; y1: CARDINAL ← destRectangle.y1; x2: CARDINAL ← destRectangle.x2; y2: CARDINAL ← destRectangle.y2; sx: CARDINAL ← srcRectangle.x1; sy: CARDINAL ← srcRectangle.y1; IF INTEGER[x1] < 0 THEN BEGIN sx ← sx-x1;x1 ← 0;END; IF INTEGER[y1] < 0 THEN BEGIN sy ← sy-y1;y1←0;END; IF dest.portraitMode THEN BEGIN x1 ← Scale[dest.scaleFactor,x1];y1 ← Scale[dest.scaleFactor,y1];x2 ← Scale[dest.scaleFactor,x2];y2 ← Scale[dest.scaleFactor,y2]; BLT.slx ← InlineDefs.BITSHIFT[Scale[dest.scaleFactor,sx],logBitsPerPixel]; BLT.sty ← Scale[dest.scaleFactor,sy]; END ELSE BEGIN t: CARDINAL ← Scale[dest.scaleFactor,(dest.nLines-1)-y1];y1 ← Scale[dest.scaleFactor,x1]; x1 ← Scale[dest.scaleFactor,(dest.nLines-1)-y2];y2 ← Scale[dest.scaleFactor,x2];x2 ← t; BLT.slx ← InlineDefs.BITSHIFT[Scale[dest.scaleFactor,dy+(src.nLines-1)-srcRectangle.y2],logBitsPerPixel]; BLT.sty ← Scale[dest.scaleFactor,sx]; IF INTEGER[BLT.slx] < 0 THEN BEGIN x1 ← InlineDefs.BITSHIFT[x1-BLT.slx,-logBitsPerPixel];BLT.slx←0; END; END; BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel]; BLT.dh ← (y2+1-y1); BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel]; BLT.dty ← y1; LongDefs.BITBLT[BLT]; RETURN; END; --easy case --rescaling case BLT.function ← replace; BLT.sourcetype ← block; IF (destHeight < srcHeight) OR (fn # replace) OR (type # block) THEN BEGIN svd ← dest; dest ← @myBitmap; dest.bank ← 0; dest.nWords ← (destWidth+15)/16; --note: if fn = paint: -- 1) we could allocate ((..)*srcHeight), and be smarter later -- 2) we could ignore this if destHeight=srcHeight dest.nLines ← destHeight; dest.bits ← SystemDefs.AllocateSegment[((destWidth+15)/16)* MAX[srcHeight,destHeight]]; dest.nBitsPerPixel ← svd.nBitsPerPixel; BLT.dbmr ← dest.nWords; BLT.dlbca ← dest.bits; myRectangle ← [0,0,destWidth-1,destHeight-1]; svdRectangle ← destRectangle; destRectangle ← @myRectangle; END; BLT.dty ← destRectangle.y1; BLT.dw ← dest.nBitsPerPixel; BLT.dh ← srcHeight; BLT.slx ← srcRectangle.x1; BLT.sty ← srcRectangle.y1; count ← 0; FOR x IN [CARDINAL[destRectangle.x1]..CARDINAL[destRectangle.x2]] DO BLT.dlx ← x; LongDefs.BITBLT[BLT]; count ← count+srcWidth; IF count >= destWidth THEN DO BLT.slx ← BLT.slx + 1; count ← count - destWidth; IF count < destWidth THEN BEGIN BLT.function←replace;EXIT;END; BLT.function←paint; LongDefs.BITBLT[BLT]; ENDLOOP; ENDLOOP; IF destHeight = srcHeight THEN BEGIN IF svd # NIL THEN funnyFinishProc[]; RETURN; END; BLT.dlx ← destRectangle.x1; BLT.dw ← destWidth; BLT.dh ← 1; BLT.slx ← destRectangle.x1; BLT.sbmr ← BLT.dbmr; BLT.slbca ← BLT.dlbca; count ← 0; IF destHeight > srcHeight THEN BEGIN BLT.sty ← destRectangle.y1 + srcHeight-1; FOR y DECREASING IN [CARDINAL[destRectangle.y1]..CARDINAL[destRectangle.y2]] DO BLT.dty ← y; LongDefs.BITBLT[BLT]; count ← count + srcHeight; IF count >= destHeight THEN BEGIN BLT.sty ← BLT.sty-1; count ← count - destHeight; END; ENDLOOP; END; IF destHeight < srcHeight THEN BEGIN BLT.sty ← destRectangle.y1; FOR y IN [CARDINAL[destRectangle.y1]..CARDINAL[destRectangle.y2]] DO BLT.dty ← y; LongDefs.BITBLT[BLT]; count ← count + srcHeight; DO BLT.sty ← BLT.sty+1; count ← count - destHeight; IF count < destHeight THEN BEGIN BLT.function←replace;EXIT;END; BLT.function←paint; LongDefs.BITBLT[BLT]; ENDLOOP; ENDLOOP; END; IF svd # NIL THEN funnyFinishProc[]; END; END.