ColorTrixMapEditImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, December 1, 1986 8:30:20 pm PST
DIRECTORY ColorTrixMap, ColorTrixPrivate, Commander, Imager, ImagerFont, ImagerOps, ImagerTransformation, InterminalBackdoor, Menus, Process, Real, Rope, Terminal, TIPUser, ViewerClasses, ViewerEvents, ViewerOps;
ColorTrixMapEditImpl: CEDAR PROGRAM
IMPORTS ColorTrixMap, Imager, ImagerFont, ImagerOps, InterminalBackdoor, Menus, Process, Real, Terminal, TIPUser, ViewerEvents, ViewerOps
EXPORTS ColorTrixPrivate
~ BEGIN
Cmap: TYPE ~ ColorTrixMap.Cmap;
CmEditData: TYPE ~ REF CmEditDataRec;
CmEditDataRec: TYPE ~ RECORD [
cm, cmSave: Cmap,
watch: BOOLFALSE,
w, n, base, i0, i1, y0, y1: NAT ← 0,
yMul, xScale, yScale: REAL ← 0.0,
x: ARRAY[0..255] OF NATALL[0],
y: ARRAY[0..2] OF ARRAY[0..255] OF NATALL[ALL[0]],
bases: ARRAY[0..2] OF NATALL[0],
viewer: ViewerClasses.Viewer ← NIL,
close: ViewerEvents.EventRegistration ← NIL
];
Paint: ViewerClasses.PaintProc ~ {
d: CmEditData ← NARROW[self.data];
Action: PROC ~ {
IF whatChanged = NIL
THEN {InitData[d]; DrawCmap[context, d, self.ww, self.wh]}
ELSE Update[context, d];
Imager.SetFont[context, ImagerFont.Find["Xerox/TiogaFonts/Helvetica14"]];
FOR n: NAT IN[0..2] DO
Imager.SetXYI[context, self.ww-50, 10+d.bases[n]];
Imager.ShowRope[context, SELECT n FROM 0 => "red", 1 => "green", ENDCASE => "blue"];
Imager.MaskRectangleI[context, 0, d.bases[n], self.ww, 1];
ENDLOOP;
};
ImagerOps.DoWithBuffer[context, Action, 0, 0, self.ww, self.wh]
};
InitData: PROC [d: CmEditData] ~ {
x: REAL ← 0;
xInc: REAL ← d.viewer.cw/255.0;
compH: NAT ← d.viewer.ch/3;
d.w ← Real.RoundI[xInc];
d.yMul ← compH/255.0;
d.xScale ← IF d.viewer.cw > 1.0 THEN 255.0/(d.viewer.cw-1) ELSE 0.0;
d.yScale ← IF d.yMul # 0.0 THEN 1.0/d.yMul ELSE 0.0;
FOR i: NAT IN[0..255] DO d.x[i] ← Real.RoundI[x]; x ← x+xInc; ENDLOOP;
FOR n: NAT IN[0..2] DO
y: INTEGER ← d.bases[n] ← (2-n)*compH;
FOR i: NAT IN[0..255] DO d.y[n][i] ← Real.RoundI[y+d.yMul*d.cm[n][i]]; ENDLOOP;
ENDLOOP;
TRUSTED {IF NOT d.watch THEN Process.Detach[FORK CmWatch[d]]};
};
CompIndex: PROC [d: CmEditData, y: INTEGER] RETURNS [NAT] ~ INLINE {
RETURN[SELECT y FROM > d.bases[0] => 0, > d.bases[1] => 1, ENDCASE => 2];
};
Notify: ViewerClasses.NotifyProc ~ {
d: CmEditData ← NARROW[self.data];
mouse: TIPUser.TIPScreenCoords ← NARROW[input.first];
SELECT input.rest.first FROM
$move => {
d.n ← CompIndex[d, mouse.mouseY];
d.base ← d.bases[d.n];
d.i0 ← d.i1 ← Real.RoundI[mouse.mouseX*d.xScale];
d.y0 ← d.y1 ← mouse.mouseY-d.bases[d.n];
};
$movingRed => {
IF d.n # CompIndex[d, mouse.mouseY] THEN RETURN; -- deny component transition
d.i0 ← d.i1;
d.y0 ← d.y1;
d.i1 ← Real.RoundI[mouse.mouseX*d.xScale];
d.y1 ← mouse.mouseY-d.base;
};
$moveBlue => {
IF d.n # CompIndex[d, mouse.mouseY] THEN RETURN; -- deny component transition
d.i0 ← d.i1;
d.y0 ← d.y1;
d.i1 ← Real.RoundI[mouse.mouseX*d.xScale];
d.y1 ← mouse.mouseY-d.base;
};
ENDCASE => RETURN;
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: d, clearClient: FALSE];
};
Update: PROC [cxt: Imager.Context, d: CmEditData] ~ {
i0, i1: NAT;
y, dy, imy, imdy: REAL;
IF d.i1 > d.i0
THEN {i0 ← d.i0; i1 ← d.i1; y ← d.yScale*d.y0; imy ← d.base+d.y0}
ELSE {i0 ← d.i1; i1 ← d.i0; y ← d.yScale*d.y1; imy ← d.base+d.y1};
Imager.SetColor[cxt, Imager.white];
FOR i: NAT IN[i0..i1] DO Imager.MaskRectangleI[cxt, d.x[i], d.y[d.n][i], d.w, 1]; ENDLOOP;
Imager.SetColor[cxt, Imager.black];
dy ← IF i0 = i1 THEN 0.0 ELSE d.yScale*Real.Float[d.y1-d.y0]/(d.i1-d.i0);
imdy ← d.yMul*dy;
FOR i: NAT IN[i0..i1] DO
d.cm[d.n][i] ← Real.RoundI[y];
ColorTrixMap.WriteEntry[i, d.cm[0][i], d.cm[1][i], d.cm[2][i]];
Imager.MaskRectangleI[cxt, d.x[i], d.y[d.n][i] ← Real.Round[imy], d.w, 1];
imy ← imy+imdy;
y ← y+dy;
ENDLOOP;
};
CmEdit: PUBLIC Commander.CommandProc ~ {
cm: Cmap ← ColorTrixMap.Read[];
data: CmEditData ← NEW[CmEditDataRec ← [cm: cm, cmSave: ColorTrixMap.Copy[cm]]];
outer: ViewerClasses.Viewer ← ViewerOps.CreateViewer[
flavor: $CmEdit,
paint: FALSE,
info: [
data: data,
name: "Color Map Editor",
openHeight: 300+24,
iconic: TRUE,
column: right,
menu: Menus.CreateMenu[],
scrollable: FALSE]];
Menus.AppendMenuEntry[outer.menu, Menus.CreateEntry["Undo", Undo, data,, FALSE, ]];
Menus.AppendMenuEntry[outer.menu, Menus.CreateEntry["Read", Read, data,, FALSE, ]];
data.viewer ← outer;
data.close ← ViewerEvents.RegisterEventProc[proc: Close, event: close, filter: outer];
ViewerOps.AddProp[outer, $CmEdit, data];
ViewerOps.OpenIcon[outer];
};
DrawCmap: PROC [context: Imager.Context, d: CmEditData, w, h: INTEGER] ~ {
Imager.SetColor[context, Imager.white];
Imager.MaskRectangleI[context, 0, 0, w, h];
Imager.SetColor[context, Imager.black];
FOR n: NAT IN[0..2] DO
b: NAT ← d.bases[n];
FOR i: NAT IN[0..255] DO
Imager.MaskRectangleI[context, d.x[i], Real.RoundI[b+d.yMul*d.cm[n][i]], d.w, 1];
ENDLOOP;
ENDLOOP;
};
NewCmap: PROC [d: CmEditData] ~ {
d.cmSave ← ColorTrixMap.Copy[d.cm ← ColorTrixMap.Read[]];
Terminal.WaitForBWVerticalRetrace[InterminalBackdoor.terminal];
ViewerOps.PaintViewer[d.viewer, client, FALSE, NIL];
};
Read: Menus.ClickProc ~ {
NewCmap[NARROW[clientData, CmEditData]];
};
Undo: Menus.ClickProc ~ {
ColorTrixMap.Write[NARROW[clientData, CmEditData].cmSave];
};
CmWatch: PROC [d: CmEditData] ~ {
d.watch ← TRUE;
WHILE d.watch DO
ColorTrixMap.WaitTilNew[];
NewCmap[d];
ENDLOOP;
};
Destroy: ViewerClasses.DestroyProc ~ {
data: CmEditData ← NARROW[self.data];
ViewerEvents.UnRegisterEventProc[proc: data.close, event: close];
data.watch ← FALSE;
};
Close: ViewerEvents.EventProc ~ {
data: CmEditData ← NARROW[ViewerOps.FetchProp[viewer, $CmEdit]];
IF data # NIL THEN data.watch ← FALSE;
};
ViewerOps.RegisterViewerClass[$CmEdit, NEW[ViewerClasses.ViewerClassRec ← [
destroy: Destroy,
paint: Paint,
notify: Notify,
tipTable: TIPUser.InstantiateNewTIPTable["CmEdit.TIP"]]]];
END.