-- MesaBandsImpl.mesa -- Last changed by Ken Pier, March 30, 1982 10:47 AM DIRECTORY MesaBands, MesaBandStream USING [InitBandFileBuffer, GetBand], MesaBandFormat USING [Bit, Type, Marker, TBrickRef, tBrickSize, Run, runSize, HeraldRef, HeraldObject, heraldObjectSize, Line, LineRef, ObjectRef, Object, objectSize], MesaBrickBLT USING [InitializeBrickBLT, BrickBLT], PressBandsDefs USING [StoreScanLine], PressNetDefs USING [PageAttributes, ScanDirection], Inline USING [LowHalf, HighHalf, LongMult, LongCOPY], DynamicZone USING [InitializeZones, SystemZone], MiscDefs USING [CallDebugger], SegmentDefs USING [NewDataSegment, DefaultXMBase, LongVMtoDataSegment, DeleteDataSegment, LongDataSegmentAddress], BitBltDefs USING [BBTableSpace, BBptr, BITBLT]; MesaBandsImpl: PROGRAM IMPORTS MesaBandStream, MesaBrickBLT, PressBandsDefs, Inline, BitBltDefs, SegmentDefs, DynamicZone, MiscDefs EXPORTS MesaBands = { OPEN BStream: MesaBandStream, BFormat: MesaBandFormat, BB: BitBltDefs, Seg: SegmentDefs, PB: PressBandsDefs, PN: PressNetDefs, DZ: DynamicZone, MiscDefs, MesaBands; bitsPerWord: CARDINAL = 16; wordsPerPage: CARDINAL = 256; debug: BOOLEAN = TRUE; Error: SIGNAL = CODE; myMark: BFormat.Marker;-- = 98765432 Assert: PROC[pred: BOOLEAN] = INLINE { IF debug AND ~pred THEN CallDebugger["FalseAssertion"L] }; Data: TYPE = POINTER TO DataRep; DataRep: TYPE = RECORD [ device: BandDevice, base: LONG POINTER, -- base address of bitmap in upper bank pages: [0..254], -- pages in bitmap rast: CARDINAL, -- bitmap words per line lines: CARDINAL -- bitmap lines ]; New: PUBLIC PROC [bDevice: BandDevice] RETURNS [Data] = { data _ uz.NEW[DataRep _ [device: bDevice, base: NIL, pages: 0, rast: 0, lines: 0]]; InitBands[data];--verifies device type match [data.base, data.pages] _ AcquireBandBitmap[data]; RETURN[data]; }; InitBands: PROC [data: Data] = { wordsRead: CARDINAL _ 0; BStream.InitBandFileBuffer[]; wordsRead _ BStream.GetBand[heraldRef, BFormat.heraldObjectSize]; Assert[wordsRead=BFormat.heraldObjectSize]; Assert[heraldRef.mark=myMark]; Assert[heraldRef.device=data.device]; data.lines _ heraldRef.bandCount*heraldRef.bandHeight; data.rast _ heraldRef.bandWidth; Assert[data.rast*data.lines<65024D];--one bank less two pages runsRef _ uz.NEW[RunsBuffer[heraldRef.bandHeight]]; lineRef _ uz.NEW[BFormat.Line[maxLx2+(heraldRef.bandWidth*bitsPerWord)]];--brickline limit is (L+xmax+L-1) bits };--InitBands AcquireBandBitmap: PROC[data: Data] RETURNS [lp: LONG POINTER, pages: CARDINAL _ 0] = { SELECT data.device FROM IN [hornet..end] => { longrast, longtemp, longDiv: LONG CARDINAL;--KLUDGE longDiv _ heraldRef.bandCount*wordsPerPage; longrast _ data.rast; longtemp _ ((longrast*data.lines)+longDiv-1)/longDiv; -- number of words per image (+normalize for arithmetic)/(256 words per diskpage * # bands per image) Assert[Inline.HighHalf[longtemp]=0]; pages _ Inline.LowHalf[longtemp]; lp _ Seg.LongDataSegmentAddress[Seg.NewDataSegment[Seg.DefaultXMBase, pages]]; }; screen => ERROR; ENDCASE => ERROR; };--AcquireBandBitmap SpaceZero: PROC[base: LONG POINTER, pages: CARDINAL] = { Inline.LongCOPY[from: longZAddress, nwords: 1, to: base]; Inline.LongCOPY[from: base, nwords: (pages*wordsPerPage)-1, to: base+1]; };--SpaceZero Close: PUBLIC PROC[data: Data] = { Seg.DeleteDataSegment[Seg.LongVMtoDataSegment[data.base]]; data.base _ NIL; uz.FREE[@lineRef]; lineRef _ NIL; uz.FREE[@runsRef]; runsRef _ NIL; };--Close -- Modd copied from CGBrickImpl Modd: PROC[x, y: LONG INTEGER] RETURNS [LONG INTEGER] = INLINE { RETURN [IF x >= 0 THEN (x MOD y) ELSE ((y-1) + (x+1) MOD y)]; };--Modd GetNextOb: PROC [bandIndex: CARDINAL, objRef: BFormat.ObjectRef] = { --GetNextOb takes a local buffer and puts an object head --into the buffer, then fills in globals RunsBuffer, tBrick buffer, as appropriate. OPEN BFormat; wordsRead, runWords, brickWords: CARDINAL _ 0; wordsRead _ BStream.GetBand[to: objRef, words: objectSize]; Assert[ wordsRead=objectSize]; Assert[objRef.mark=myMark]; IF objRef.flags.type=end THEN RETURN; Assert[objRef.band=bandIndex ]; runWords _ IF objRef.flags.rect THEN BFormat.runSize ELSE BFormat.runSize*objRef.height; wordsRead _ BStream.GetBand[to: runsRef, words: runWords];--read runs Assert[ wordsRead=runWords]; SELECT objRef.flags.type FROM all0, all1, bits => RETURN; --no data for allx, scanlines later for bits brick => { --tBrick and runs. Read brick. wordsRead _ BStream.GetBand[to: tBrick, words: tBrickSize]; Assert[ wordsRead=tBrickSize]; brickWords _ (tBrick.brickSize + bitsPerWord-1)/bitsPerWord; wordsRead _ BStream.GetBand[to: brickBuffer, words: brickWords]; Assert[ wordsRead=brickWords]; Assert[ maxL>tBrick.L]; RETURN };--tBrick fontcache, herald, end => ERROR; ENDCASE => ERROR; };--GetNextOb ShowBandsInit: PUBLIC PROC[bDevice: BandDevice] RETURNS[p: PN.PageAttributes] = { scanDirection: PN.ScanDirection; data _ New[bDevice]; scanDirection _ SELECT bDevice FROM hornet => landscape, platemaker => portrait, reticlemaker => landscape, ENDCASE => ERROR; p _ [scanDirection: scanDirection, filler: , firstScan: 0, lastScan: data.lines-1, margin: 0, bitWc: data.rast]; };--ShowBandsInit ShowBands: PUBLIC PROC [] = { lptr: LONG POINTER _ NIL; yOffset _ 0; FOR bI: CARDINAL IN [0..heraldRef.bandCount) DO SpaceZero[data.base, data.pages]; --GetNextOb takes a band and a buffer and puts an object head for this band --into the buffer, then fills in globals RunsBuffer, tBrick buffer, Scanline -- as appropriate. DO GetNextOb[bandIndex: bI, objRef: objectRef]; SELECT objectRef.flags.type FROM all0, all1, bits, brick => Render[data: data]; herald => ERROR; end => EXIT; ENDCASE=> ERROR; ENDLOOP;--for each trap UNTIL end of band --write out the completed band buffer to the bits file lptr _ data.base; THROUGH [0..heraldRef.bandHeight) DO PB.StoreScanLine[lptr]; lptr _ lptr+data.rast; ENDLOOP; yOffset _ yOffset + heraldRef.bandHeight;-- band relative baseline ENDLOOP;--for each band in [0..bandcount) Close[data];--release the band segment };--ShowBands Render: PROC [data: Data] = { rect: BOOLEAN _ objectRef.flags.rect; type: BFormat.Type _ objectRef.flags.type; y, yTop, height, bandWidth, grayWord: CARDINAL; longline: LONG POINTER TO WORD; run: POINTER TO BFormat.Run; runBump: CARDINAL; black: CARDINAL = LAST[CARDINAL]; white: CARDINAL = 0; y _ yTop _ objectRef.yStart-yOffset; height _ objectRef.height; bandWidth _ heraldRef.bandWidth; -- pointer to beginning of first destination scan line longline _ data.base + Inline.LongMult[yTop, data.rast]; run _ LOOPHOLE[runsRef]; -- pointer to first Run -- rectangles use the same Run for each line -- trapezoids have a new Run for each line runBump _ IF rect THEN 0 ELSE BFormat.runSize; SELECT type FROM all0, all1 => { -- constant white or black grayWord _ IF type = all1 THEN black ELSE white; bbPointer^ _ [ ptrs: short, pad: 0, sourcealt: FALSE, destalt: TRUE, sourcetype: gray, function: replace, unused: Inline.HighHalf[data.base], --NOT REALLY UNUSED dbca: Inline.LowHalf[data.base], dbmr: bandWidth, -- destination raster width(in words) dlx: run.xmin, -- destination left x dty: y, -- destination top y dw: run.xmax-run.xmin,--may be zero !! block width in bits dh: height, -- block height in scanlines may be zero !! sbca: NIL, -- no source sbmr: 0, -- source raster width(in words) slx: 0, -- source left x sty: 0, -- source top y gray0: grayWord, -- four words of "gray" gray1: grayWord, gray2: grayWord, gray3: grayWord, slbca: NIL, -- ignored dlbca: NIL]; -- ignored IF rect THEN BB.BITBLT[bbPointer] --BLT a rectangle in one shot!! ELSE {--BLT a trapezoid one line at a time bbPointer.dh _ 1; THROUGH [0..height) DO bbPointer.dlx _ run.xmin; -- destination left x bbPointer.dty _ y; -- destination top y bbPointer.dw _ run.xmax-run.xmin; --may be zero !! block width bits BB.BITBLT[bbPointer]; run _ run + runBump; y _ y+1;--index of next line ENDLOOP; };--BLT a trapezoid one line at a time }; -- constant white or black bits => { -- specified bits (opaque), fetch each line and BLT it bbPointer^ _ [ ptrs: short, pad: 0, sourcealt: FALSE, destalt: TRUE, sourcetype: block, function: replace, unused: Inline.HighHalf[data.base], --NOT REALLY UNUSED dbca: Inline.LowHalf[data.base], dbmr: bandWidth, -- destination raster width(in words) dlx: 0, -- destination left x dty: 0, -- destination top y dw: 0, -- block width in bits dh: 1, -- block height in scanlines sbca: lineRef, sbmr: 0, -- source raster width(UNUSED for height=1) slx: 0, -- source left x sty: 0, -- source top y slbca: NIL, -- ignored dlbca: NIL]; -- ignored THROUGH [0..height) DO--BLT either trap or rect one line at a time [] _ BStream.GetBand[lineRef, (run.xmax-run.xmin+15)/bitsPerWord];--may fetch 0 words bbPointer.dlx _ run.xmin; -- destination left x bbPointer.dty _ y; -- destination top y bbPointer.dw _ run.xmax-run.xmin; -- block width in bits BB.BITBLT[bbPointer]; run _ run + runBump; y _ y + 1;--index of start of next line ENDLOOP; };-- specified bits (opaque), fetch each line and BLT it brick => { -- construct each line and BLT it L, p, hx, hy: CARDINAL; D: INTEGER _ 0; L _ tBrick.L; p _ tBrick.p; D _ tBrick.D; y _ objectRef.yStart; -- absolute, not relative y THROUGH [0..height) DO hy _ y MOD p; hx _ Inline.LowHalf[Modd[(run.xmin - LONG[D]*(y/p)), L]]; MesaBrickBLT.BrickBLT[bbptr: bbPointer, tBrick: tBrick, destLine: longline, hx: hx, hy: hy, xmin: run.xmin, xmax: run.xmax, lineBuffer: lineRef]; run _ run + runBump; y _ y+1;--index of start of next line absolute longline _ longline + bandWidth; ENDLOOP; };-- construct each line and BLT it ENDCASE => ERROR; };--Render --START CODE FOR MesaBandImageImpl uz: MDSZone; data: Data _ NIL; yOffset: CARDINAL _ 0; -- global buffering requiring POINTERS heraldRef: BFormat.HeraldRef; heraldSizeX2: CARDINAL _ 2*BFormat.heraldObjectSize; objectRef: BFormat.ObjectRef; zeroWord: CARDINAL _ 0; longZAddress: LONG POINTER _ LONG[@zeroWord]; -- see SpaceZero TBrick: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF WORD];--buffer for tBrick words coming from stream maxTBrick: CARDINAL = 400+BFormat.tBrickSize;--6400 bits maximum in a tBrick for now TBrickPtr: TYPE = POINTER TO TBrick; brickBuffer: TBrickPtr; tBrick: BFormat.TBrickRef; RunsBuffer: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF BFormat.Run]; RunsRef: TYPE = POINTER TO RunsBuffer; runsRef: RunsRef _ NIL; -- initialized by InitBands runsIndex: CARDINAL _ 0; -- runs buffer index maxL: CARDINAL = 2000;--longest permitted L for a thresholded brick maxLx2: CARDINAL = maxL*2;--longest permitted L for a thresholded brick times 2 lineRef: BFormat.LineRef _ NIL; -- initialized by InitBands lineIndex: CARDINAL _ 0;-- Scanline bit index BBTable: BB.BBTableSpace; bbPointer: BB.BBptr; DZ.InitializeZones[]; uz _ DZ.SystemZone[]; heraldRef _ uz.NEW[BFormat.HeraldObject]; objectRef _ uz.NEW[BFormat.Object[1]]; brickBuffer _ uz.NEW[TBrick[maxTBrick]]; bbPointer _ MesaBrickBLT.InitializeBrickBLT[@BBTable]; --fix up tBrick from brickBuffer tBrick _ LOOPHOLE[brickBuffer];--common storage covering tBHead+brickBuffer brickBuffer _ brickBuffer+BFormat.tBrickSize; }. LOG March 11, 1982 changed everything to SHORT POINTERS March 30, 1982 changed everything to use Assert