PDInterpOutputViewerImpl.mesa
Copyright (C) 1984, Xerox Corporation. All rights reserved.
Michael Plass, October 31, 1984 8:50:43 am PST
Implements a Cedar PD output device that shows the bitmap in a viewer.
DIRECTORY PDFileFormat, PDInterpBitmap, Menus, ImagerPixelMaps, PDInterpOutput, ViewerClasses, ViewerOps, CGContext, Graphics, GraphicsOps, Real, ImagerFrameBuffer, Process, PDTextBitmap, String, PDQueue, IO, FS;
PDInterpOutputViewerImpl: PROGRAM
IMPORTS Menus, ImagerPixelMaps, ViewerOps, Graphics, GraphicsOps, Real, ImagerFrameBuffer, Process, PDTextBitmap, PDInterpBitmap, String, IO, FS, PDQueue
EXPORTS PDInterpOutput
= BEGIN
viewer: ViewerClasses.Viewer ← NIL;
pageMap: ImagerPixelMaps.PixelMap ← ImagerPixelMaps.Create[0, [0,0,0,0]];
currentStartImage: PDFileFormat.StartImage;
currentHerald: PDFileFormat.Herald;
bandNumber: NAT ← 0;
oneBandAtATime: BOOLEANFALSE;
StartImage: PUBLIC PROC [herald: PDFileFormat.Herald, startImage: PDFileFormat.StartImage, request: PDQueue.Request]
RETURNS [PDInterpBitmap.BitmapDesc] = {
bandMap: ImagerPixelMaps.PixelMap;
pageMapLines: NATIF oneBandAtATime THEN herald.bandSSize ELSE startImage.nBands*herald.bandSSize;
pageMap ← ImagerPixelMaps.Create[0, [startImage.passBands*herald.bandSSize, startImage.fMinPage, pageMapLines, startImage.fSizePage]];
currentStartImage ← startImage;
currentHerald ← herald;
bandNumber ← 0;
pageMap.Clear;
bandMap ← pageMap.Clip[[startImage.passBands*herald.bandSSize, startImage.fMinPage, herald.bandSSize, startImage.fSizePage]];
RETURN [[
sOrigin: bandMap.sOrigin,
fOrigin: bandMap.fOrigin,
sMin: bandMap.sMin,
fMin: bandMap.fMin,
sSize: bandMap.sSize,
fSize: bandMap.fSize,
pointer: bandMap.refRep.pointer,
rast: bandMap.refRep.rast,
lines: bandMap.refRep.lines
]]
};
EndBand: PUBLIC PROC RETURNS [PDInterpBitmap.BitmapDesc] = {
bandMap: ImagerPixelMaps.PixelMap;
bandNumber ← bandNumber + 1;
IF oneBandAtATime THEN ShowPage[];
IF oneBandAtATime THEN {pageMap ← pageMap.ShiftMap[currentHerald.bandSSize, 0]; pageMap.Clear};
bandMap ← pageMap.Clip[[(currentStartImage.passBands+bandNumber)*currentHerald.bandSSize, currentStartImage.fMinPage, currentHerald.bandSSize, currentStartImage.fSizePage]];
RETURN [[
sOrigin: bandMap.sOrigin,
fOrigin: bandMap.fOrigin,
sMin: bandMap.sMin,
fMin: bandMap.fMin,
sSize: bandMap.sSize,
fSize: bandMap.fSize,
pointer: bandMap.refRep.pointer,
rast: bandMap.refRep.rast,
lines: bandMap.refRep.lines
]]
};
ShowPage: PROC = {
data: ViewerData;
IF viewer = NIL OR viewer.destroyed THEN viewer ← ViewerOps.CreateViewer[$PDInterpOutputViewerClass, [name: "PD page", column: left, iconic: TRUE]];
data ← NARROW [viewer.data];
data.nextPage ← FALSE;
data.sShift ← -pageMap.sOrigin;
data.fShift ← -pageMap.fOrigin;
ViewerOps.PaintViewer[viewer, client];
DO
IF viewer.destroyed OR data.nextPage OR data.noPause OR oneBandAtATime THEN EXIT;
Process.Pause[Process.MsecToTicks[200]];
ENDLOOP;
};
EndImage: PUBLIC PROC [request: PDQueue.Request] = {
separator: LONG STRING ← [160];
String.Copy[separator, request.requestTime];
THROUGH [0..2) DO String.AppendChar[separator, ' ] ENDLOOP;
String.AppendString[separator, request.fileName];
THROUGH [0..2) DO String.AppendChar[separator, ' ] ENDLOOP;
String.AppendString[separator, request.requestor];
THROUGH [0..2) DO String.AppendChar[separator, ' ] ENDLOOP;
ShowPage[];
IF PDTextBitmap.fontName.length = 0 THEN IF NOT PDTextBitmap.SetFont["[Indigo]<Peach>Fonts>TimesRoman36B.ks", request.requestor, request.requestorPassword] THEN ERROR;
pageMap ← pageMap.refRep.Reshape[0, [-1-PDTextBitmap.FontAscent[], -PDTextBitmap.FontAscent[], PDTextBitmap.FontAscent[]+PDTextBitmap.FontDescent[]+2, PDTextBitmap.TextWidth[separator]+2*PDTextBitmap.FontAscent[]]];
{
bits: PDInterpBitmap.BitmapDesc ← [
sOrigin: pageMap.sOrigin,
fOrigin: pageMap.fOrigin,
sMin: pageMap.sMin,
fMin: pageMap.fMin,
sSize: pageMap.sSize,
fSize: pageMap.fSize,
pointer: pageMap.refRep.pointer,
rast: pageMap.refRep.rast,
lines: pageMap.refRep.lines
];
PDInterpBitmap.Fill[bits, [-10000, -10000, 20000, 20000], 1];
PDTextBitmap.TextToBitmap[dest: bits, string: separator, function: [and, complement]];
};
ShowPage[];
};
ReprintLastPage: PUBLIC PROC [copies: CARDINAL] = {
IF currentHerald.password # PDFileFormat.passwordValue THEN RETURN;
currentHerald.copies ← copies;
ShowPage[];
};
viewerClass: ViewerClasses.ViewerClass ← NEW [ViewerClasses.ViewerClassRec ← [
init: ViewerInit,
paint: ViewerPaint,
scroll: ViewerScroll,
coordSys: bottom,
icon: tool
]];
ViewerData: TYPE = REF ViewerDataRep;
ViewerDataRep: TYPE = RECORD [
sShift: INTEGER ← 0,
fShift: INTEGER ← 0,
nextPage: BOOLEANFALSE,
noPause: BOOLEANFALSE
];
HScrollHit: Menus.ClickProc = TRUSTED {
viewer: ViewerClasses.Viewer ← NARROW[parent];
data: ViewerData ← NARROW[viewer.data];
IF data = NIL THEN RETURN;
data.fShift ← data.fShift + (IF mouseButton = red THEN -128 ELSE 128);
IF mouseButton = yellow THEN data.fShift ← -pageMap.fMin;
ViewerOps.PaintViewer[viewer, client];
};
PageHit: Menus.ClickProc = TRUSTED {
viewer: ViewerClasses.Viewer ← NARROW[parent];
data: ViewerData ← NARROW[viewer.data];
IF data = NIL THEN RETURN;
data.nextPage ← TRUE;
};
NoPauseHit: Menus.ClickProc = TRUSTED {
viewer: ViewerClasses.Viewer ← NARROW[parent];
data: ViewerData ← NARROW[viewer.data];
IF data = NIL THEN RETURN;
data.noPause ← mouseButton = red;
};
lfGraphicsData: CGContext.Ref = NARROW[Graphics.NewContext[].data];
ViewerInit: ViewerClasses.InitProc = TRUSTED {
viewerData: ViewerData ← NEW[ViewerDataRep];
menu: Menus.Menu ← Menus.CreateMenu[1];
Menus.InsertMenuEntry[menu, Menus.CreateEntry[name: "<<<-->>>", proc: HScrollHit]];
Menus.InsertMenuEntry[menu, Menus.CreateEntry[name: "Page", proc: PageHit]];
Menus.InsertMenuEntry[menu, Menus.CreateEntry[name: "NoPause", proc: NoPauseHit]];
viewerData.sShift ← 0;
viewerData.fShift ← 0;
self.data ← viewerData;
self.menu ← menu;
};
ViewerScroll: ViewerClasses.ScrollProc = TRUSTED {
data: ViewerData ← NARROW [self.data];
IF data = NIL OR op = query THEN RETURN [0, 100];
IF op = thumb THEN {data.sShift ← -pageMap.sOrigin; RETURN [0, 100]};
IF amount = 0 THEN RETURN [0, 100];
IF op = down THEN amount ← -amount;
data.sShift ← data.sShift - amount;
ViewerOps.PaintViewer[self, client];
RETURN [0, 100];
};
OnLFDisplay: PROC [graphics: Graphics.Context] RETURNS [BOOLEAN] = {
data: CGContext.Ref = NARROW[graphics.data];
RETURN [data.device.Show = lfGraphicsData.device.Show]
};
GetViewerPixelMap: PROC [graphics: Graphics.Context] RETURNS [pixelMap: ImagerPixelMaps.PixelMap] = {
x, y, w, h: REAL;
[x, y] ← GraphicsOps.UserToDevice[graphics,0,0];
IF GraphicsOps.UserToDevice[graphics,0,1].ty > y THEN ERROR;
[[xmax: w, ymax: h]] ← Graphics.GetBounds[graphics];
IF OnLFDisplay[graphics] THEN {
sMin: INTEGER ← Real.RoundLI[y]-Real.RoundLI[h];
pixelMap ← ImagerFrameBuffer.LFDisplay[];
pixelMap ← pixelMap.ShiftMap[-sMin, -Real.RoundLI[x]];
pixelMap ← pixelMap.Clip[[0, 0, Real.RoundLI[h], Real.RoundLI[w]]];
}
ELSE pixelMap ← ImagerPixelMaps.Create[0, [0,0,0,0]];
};
ViewerPaint: ViewerClasses.PaintProc = TRUSTED {
data: ViewerData ← NARROW [self.data];
pixelMap: ImagerPixelMaps.PixelMap ← GetViewerPixelMap[context];
pixelMap.Transfer[pageMap.ShiftMap[data.sShift, data.fShift]];
};
ReadQueue: PROC [address: LONG POINTER, nwords: CARDINAL] = TRUSTED {
stream: IO.STREAM;
stream ← FS.StreamOpen["[]<>Peach.queue", $read, ALL[FALSE] ! FS.Error => CONTINUE];
IF stream#NIL THEN {
[] ← stream.UnsafeGetBlock[[base: address, startIndex: 0, count: nwords*2]];
stream.Close;
};
};
WriteQueue: PROC [address: LONG POINTER, nwords: CARDINAL] = TRUSTED {
stream: IO.STREAMFS.StreamOpen["[]<>Peach.queue", $create];
[] ← stream.UnsafePutBlock[[base: address, startIndex: 0, count: nwords*2]];
stream.Close;
};
RegisterDisk: PROC = {PDQueue.RegisterDisk[ReadQueue, WriteQueue, 1024]};
ViewerOps.RegisterViewerClass[$PDInterpOutputViewerClass, viewerClass];
currentHerald.password ← 0;
PDQueue.RegisterDisk[ReadQueue, WriteQueue, 1024];
END.