BitmapViewerImpl.mesa
Copyright (C) 1984, Xerox Corporation. All rights reserved.
Michael Plass, September 26, 1984 5:22:14 pm PDT
Implements a Cedar PD output device that shows the bitmap in a viewer.
DIRECTORY Menus, ImagerPixelMaps, ViewerClasses, ViewerOps, CGContext, Graphics, GraphicsOps, Real, ImagerFrameBuffer, ImagerManhattan, BitmapViewer;
BitmapViewerImpl: CEDAR PROGRAM
IMPORTS Menus, ImagerPixelMaps, ViewerOps, Graphics, GraphicsOps, Real, ImagerFrameBuffer, ImagerManhattan
EXPORTS BitmapViewer
= BEGIN OPEN BitmapViewer;
ViewerData: TYPE = REF ViewerDataRep;
ViewerDataRep: TYPE = RECORD [
sShift: INTEGER ← 0,
fShift: INTEGER ← 0,
bitmap: PixelMap ← ImagerPixelMaps.Create[0, [0,0,0,0]]
];
Create: PUBLIC PROC [info: ViewerClasses.ViewerRec ← [], paint: BOOLTRUE] RETURNS [Viewer] ~ {
RETURN [ViewerOps.CreateViewer[flavor, info, paint]];
};
SetBitmap: PUBLIC PROC [viewer: Viewer, bitmap: PixelMap] ~ {
data: ViewerData ← NARROW[viewer.data];
data.bitmap ← bitmap;
ViewerOps.PaintViewer[viewer, client, FALSE];
};
GetBitmap: PUBLIC PROC [viewer: Viewer] RETURNS [bitmap: PixelMap] ~ {
data: ViewerData ← NARROW[viewer.data];
bitmap ← data.bitmap;
};
TouchUp: PUBLIC PROC [viewer: Viewer, deviceRectangle: DeviceRectangle] ~ {
ViewerOps.PaintViewer[viewer, client, FALSE];
};
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 ← 0;
ViewerOps.PaintViewer[viewer, client, FALSE];
};
ViewerInit: ViewerClasses.InitProc = TRUSTED {
viewerData: ViewerData ← NEW[ViewerDataRep];
menu: Menus.Menu ← Menus.CreateMenu[1];
Menus.InsertMenuEntry[menu, Menus.CreateEntry[name: "<<<-->>>", proc: HScrollHit]];
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 ← 0; ViewerOps.PaintViewer[self, client]; 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];
};
lfGraphicsData: CGContext.Ref = NARROW[Graphics.NewContext[].data];
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];
TRUSTED {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]];
};
Normalize: PROC [viewer: Viewer] RETURNS [Viewer] ~ {
data: ViewerData ← NARROW[viewer.data];
b: DeviceRectangle ← data.bitmap.ShiftMap[data.sShift, data.fShift].Window;
w: DeviceRectangle ← [-2*viewer.ch/3, -viewer.cw/3, viewer.ch, viewer.cw];
IF b.sMin >= w.sMin+w.sSize THEN data.sShift ← data.sShift - (b.sMin-(w.sMin+w.sSize)+1)
ELSE IF b.sMin + b.sSize <= w.sMin THEN data.sShift ← data.sShift + (w.sMin-(b.sMin + b.sSize) + 1);
IF b.fMin >= w.fMin+w.fSize THEN data.fShift ← data.fShift - (b.fMin-(w.fMin+w.fSize)+1)
ELSE IF b.fMin + b.fSize <= w.fMin THEN data.fShift ← data.fShift + (w.fMin-(b.fMin + b.fSize) + 1);
RETURN [viewer]
};
ViewerPaint: ViewerClasses.PaintProc = TRUSTED {
data: ViewerData ← NARROW [Normalize[self].data];
screen: PixelMap ← GetViewerPixelMap[context].ShiftMap[-2*self.ch/3, -self.cw/3];
bits: PixelMap ← data.bitmap.ShiftMap[data.sShift, data.fShift];
whiten: LIST OF DeviceRectangle ← ImagerManhattan.Difference[
ImagerManhattan.CreateFromBox[screen.Window],
ImagerManhattan.CreateFromBox[bits.Window]
];
screen.Transfer[bits];
FOR w: LIST OF DeviceRectangle ← whiten, w.rest UNTIL w = NIL DO
screen.Fill[w.first, 0];
ENDLOOP;
ImagerManhattan.Destroy[whiten];
};
viewerClass: ViewerClasses.ViewerClass ← NEW [ViewerClasses.ViewerClassRec ← [
init: ViewerInit,
paint: ViewerPaint,
scroll: ViewerScroll,
coordSys: bottom,
icon: tool
]];
flavor: PUBLIC ViewerClasses.ViewerFlavor ← $BitmapViewer;
ViewerOps.RegisterViewerClass[flavor, viewerClass];
END.