PressImageImpl.mesa
Last edited by Shore; December 4, 1982 12:25 am
Last edited by Wyatt; December 1, 1983 5:47 pm
DIRECTORY
Basics USING [bitsPerWord],
CGArea USING [Empty, Ref],
CGContext USING [GenBox, Rep],
CGDevice USING [Ref],
CGMatrix USING [Assign, Concat, ConcatTransformation, Make, New, Ref, SetTrans],
CGSource USING [Ref, Rep],
CGStorage USING [qZone],
Graphics USING [Context, Scale],
GraphicsBasic USING [black],
IO USING [GetIndex, SetIndex, STREAM, UnsafeGetBlock],
PressImage,
PressReader USING [Dots],
VM USING [AddressForPageNumber, Allocate, Free, Interval, PagesForBytes];
PressImageImpl:
PROGRAM
-- MONITOR
IMPORTS CGArea, CGContext, CGMatrix, CGStorage, Graphics, IO, VM
EXPORTS PressImage
SHARES Graphics = BEGIN
Context: TYPE = Graphics.Context;
ContextData: TYPE = REF ContextDataRep;
ContextDataRep: PUBLIC TYPE = CGContext.Rep;
PressImage: PUBLIC TYPE = REF PressImageData;
PressImageData:
PUBLIC
TYPE =
RECORD [
file: IO.STREAM,
numberPages: NAT,
streamIndex: INT,
byteLength: INT,
scanDirection: CARDINAL,
scanCount: CARDINAL, -- lines
scanLength: CARDINAL, -- dots
wordsPerLine: CARDINAL, -- words per scan line
imageHeight: REAL,
imageWidth: REAL,
miv: CGMatrix.Ref, -- image-to-virtual matrix
matrix: CGMatrix.Ref, -- image-to-device matrix
src: CGSource.Ref -- source info for image
];
dataZone: ZONE = CGStorage.qZone;
srcZone: ZONE = CGStorage.qZone;
PressImageError: PUBLIC ERROR = CODE;
MakePressImage:
PUBLIC
PROCEDURE [sampleType, dots, lines, mode, pd, dd, pl, dl:
INT, width, height:
REAL, bits: PressReader.Dots]
RETURNS [self: PressImage ←
NIL] = {
scanlines, pixels, wpl, bps: CARDINAL;
scanlines ← lines;
pixels ← dots;
wpl ← (dots*(IF sampleType IN [1..16] THEN sampleType ELSE 1) + (Basics.bitsPerWord-1)) / Basics.bitsPerWord;
IF dots MOD Basics.bitsPerWord # 0 THEN ERROR PressImageError;
bps ← sampleType;
self ← dataZone.
NEW[PressImageData ← [
file: bits.file,
numberPages: bits.numberPages,
streamIndex: LONG[bits.pageNumber]*512+bits.byteOffset,
byteLength: bits.length*2, -- bits.length is in words!
scanDirection: mode,
scanCount: scanlines,
scanLength: pixels,
wordsPerLine: wpl,
imageHeight: height,
imageWidth: width,
miv:
SELECT mode
FROM
2 => CGMatrix.Make[[1,0,0,1,0,0]],
3 => CGMatrix.Make[[1,0,0,-1,0,lines]],
8 => CGMatrix.Make[[0,1,1,0,0,0]],
ENDCASE => ERROR, -- unexpected scanDirection
matrix: CGMatrix.New[], -- placeholder for image-to-device mapping
src: srcZone.NEW[CGSource.Rep ← [type: array, mode: opaque, fat: FALSE, raw: FALSE, bps: bps, color: GraphicsBasic.black, xbase: NIL, xrast: wpl, Get: NIL]]]];
RETURN [self];
};
DrawPressImage:
PUBLIC
PROCEDURE [self: Context, image: PressImage] = {
ctx: ContextData;
data: PressImage ~ image;
T: CGMatrix.Ref; -- virtual to destination mapping
M: CGMatrix.Ref ← data.matrix; -- image to destination mapping
src: CGSource.Ref ← data.src;
wpl: CARDINAL ← data.wordsPerLine;
device: CGDevice.Ref;
area: CGArea.Ref;
stream: IO.STREAM ~ data.file;
vm: VM.Interval;
savedIndex: INT;
basePtr: LONG POINTER;
Graphics.Scale[self, data.imageWidth/REAL[data.scanLength], data.imageHeight/REAL[data.scanCount]];
ctx ← NARROW[self.data];
T ← ctx.matrix;
device ← ctx.device;
CGMatrix.Assign[M,T];
CGMatrix.SetTrans[M, ctx.cp]; -- translate to current position
IF NOT ctx.yUp THEN CGMatrix.Concat[M,1,0,0,-1];
CGMatrix.ConcatTransformation[M, data.miv.m]; -- M ← miv * T
src.color ← ctx.src.color; src.mode ← ctx.src.mode;
vm ← VM.Allocate[count: VM.PagesForBytes[data.byteLength]];
savedIndex ← stream.GetIndex[];
stream.SetIndex[data.streamIndex];
TRUSTED {
basePtr ← VM.AddressForPageNumber[vm.page];
[] ← stream.UnsafeGetBlock[[base: basePtr, count: data.byteLength]];
};
stream.SetIndex[savedIndex];
src.xbase ← basePtr;
area ← CGContext.GenBox[ctx,
[xmin: 0, ymin: 0, xmax: data.scanLength-1, ymax: data.scanCount-1], M];
IF NOT CGArea.Empty[area] THEN device.Show[device, area, src, M];
TRUSTED {VM.Free[vm]};
};
END.