--m.stone October 2, 1980 12:32 PM 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: INTEGER] RETURNS [INTEGER] = INLINE BEGIN RETURN[(INTEGER[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: 47], HBTrailLength: 6,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;(635)\f1 325b9B119b140B40b5B101b55B96b10B49b10B197b114B287b69B39b15B40b8B39b12B40b12B21b12B23b12B23b2B46b10B62b11B26b4B54b7B46b11B68b3B71b15B263b11B186b10B175b11B216b14B106b14B114b9B16b23B23b17B941b1B5b13B91b12B1093b100B566b7B387b9B339b8B338b7B300b9B269b8B268b13B110b16B242b15B1721b11B49b4B122b11B53b4B184b11B109b5B174b12B12b6B21b18B25b4B6b10B1361b40B212b22B147b8B111b10B111b8B112b8B128b9B126b7B127b8B126b9B126b7B127b11B128b8B126b9B126b7B127b11B128b10B148b11B148b9B149b13B169b8B734b15B95b7B 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. e6\f1 1b7B1362b7B1264b8B1342b9B1626b13B1680b17B3520b36B95b137B