ColorTrixCommands2Impl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, November 30, 1986 12:17:24 pm PST
DIRECTORY Args, Atom, Buttons, ChoiceButtons, CedarProcess, ClassIncreek, ColorDisplay, ColorTrixBasics, ColorTrixMap, Commander, Containers, Convert, Draw2d, Imager, ImagerBackdoor, ImagerColor, ImagerPixelMap, IO, MessageWindow, Process, Real, Rope, Terminal, TerminalDefs, TextNode, TiogaAccess, TiogaImager, TypeScript, ViewerClasses, ViewerIO, ViewerOps, ViewerTools;
ColorTrixCommands2Impl:
CEDAR
PROGRAM
IMPORTS Args, Atom, Buttons, ChoiceButtons, CedarProcess, ClassIncreek, ColorDisplay, ColorTrixBasics, ColorTrixMap, Commander, Containers, Convert, Draw2d, Imager, ImagerBackdoor, ImagerColor, ImagerPixelMap, IO, MessageWindow, Process, Real, Rope, Terminal, TiogaAccess, TiogaImager, TypeScript, ViewerIO, ViewerOps, ViewerTools
~
BEGIN
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
Viewer: TYPE ~ ViewerClasses.Viewer;
PixelMap: TYPE ~ ColorTrixBasics.PixelMap;
PixelMapMisc: TYPE ~ ColorTrixBasics.PixelMapMisc;
Cmap: TYPE ~ ColorTrixMap.Cmap;
Context: TYPE ~ Imager.Context;
Color: TYPE ~ Imager.Color;
CtDif
CtDif: Commander.CommandProc ~ {
Dif:
PROC [pm: PixelMap] ~ {
src0: PixelMap ~ ImagerPixelMap.Clip[pm, [y0.int, x0.int, h.int, w.int]];
src1: PixelMap ~ ImagerPixelMap.Clip[pm, [y1.int, x1.int, h.int, w.int]];
dif: PixelMap ~ ImagerPixelMap.Clip[pm, [y2.int, x2.int, h.int, w.int]];
FOR y:
INT
IN [0..h.int)
DO
FOR x:
INT
IN [0..w.int)
DO
src0Value: INTEGER ~ ColorTrixBasics.GetPixel[src0, x+src0.fMin, y+src0.sMin];
src1Value: INTEGER ~ ColorTrixBasics.GetPixel[src1, x+src1.fMin, y+src1.sMin];
ColorTrixBasics.PutPixel[dif, x+dif.fMin, y+dif.sMin, ABS[src0Value-src1Value]];
ENDLOOP;
ENDLOOP;
};
ok: BOOL;
x0, y0, x1, y1, x2, y2, w, h: Args.Arg;
[ok, x0, y0, x1, y1, x2, y2, w, h] ← Args.ArgsGet[cmd, "%iiiiiiii"];
IF
NOT ok
THEN RETURN[$Failure, "Bad argument(s)."]
ELSE {
pmMisc: PixelMapMisc ← ColorTrixBasics.GetColorDisplayPmMisc[];
SELECT pmMisc.bpp
FROM
8 => Dif[pmMisc.bw];
24 => {
Dif[pmMisc.rg];
Dif[pmMisc.b];
};
ENDCASE;
};
};
CtText
CtTextData: TYPE ~ REF CtTextDataRec;
CtTextDataRec:
TYPE ~
RECORD [
viewer: Viewer ← NIL,
context: Context ← NIL,
bounds: Imager.Rectangle,
x, y, c: Viewer ← NIL,
printButton: Viewer ← NIL
];
CtText: Commander.CommandProc ~ {
context: Context ~ ColorTrixBasics.InitCd[smooth, TRUE, FALSE, FALSE];
IF Args.NArgs[cmd] > 0
THEN {
x: Args.Arg ← Args.ArgInt[cmd, 0];
y: Args.Arg ← Args.ArgInt[cmd, 1];
text: Args.Arg ← Args.ArgRope[cmd, 2];
IF NOT x.ok OR NOT y.ok OR NOT text.ok THEN RETURN[$Failure, ctTextUsage];
Draw2d.Label[context, [x.int, y.int], text.rope];
}
ELSE {
data: CtTextData ← NEW[CtTextDataRec];
data.context ← context;
data.bounds ← ImagerBackdoor.GetBounds[data.context];
data.viewer ← Containers.Create[
info: [name: "CtText", openHeight: 33, iconic: TRUE, column: right, scrollable: FALSE],
paint: FALSE];
data.x ← ChoiceButtons.BuildTextPrompt[data.viewer, 0, 0, "x:", "0", , 30].textViewer;
data.y ← ChoiceButtons.BuildTextPrompt[data.viewer, 60, 0, "y:", "0", , 30].textViewer;
data.c ← ChoiceButtons.BuildTextPrompt[data.viewer, 120, 0, "color:", "Black", , 50].textViewer;
data.printButton ← Buttons.Create[
info: [parent: data.viewer, name: "Print", wx: 240, wy: 3],
proc: Print,
clientData: data,
paint: TRUE];
ViewerOps.OpenIcon[data.viewer];
};
};
Blink:
PROC [rope: Rope.
ROPE] ~ {
MessageWindow.Append[rope, TRUE];
MessageWindow.Blink[];
};
Print: Buttons.ButtonProc ~ {
badButton: ERROR;
GetValue:
PROC [viewer: Viewer]
RETURNS [
NAT] ~ {
num: INT;
selection: Rope.ROPE ← ViewerTools.GetContents[viewer];
num ← Convert.IntFromRope[selection ! Convert.Error => ERROR badButton];
IF num < 0 THEN ERROR badButton;
RETURN[num];
};
data: CtTextData ~ NARROW[clientData];
x, y: NAT;
formattedNode: TiogaImager.FormattedNodes;
color: Color ← ImagerColor.ColorFromAtom[Atom.MakeAtom[ViewerTools.GetContents[data.c]]];
reader: TiogaAccess.Reader ~ TiogaAccess.FromSelection[];
location: TextNode.Location ~ [NARROW[TiogaAccess.GetNodeRefs[reader].current], 0];
IF location.node = NIL THEN GOTO BadText;
IF color = NIL THEN GOTO BadColor;
formattedNode ← TiogaImager.FormatNodes[location, [data.bounds.w, data.bounds.h], TRUE];
x ← GetValue[data.x ! badButton => GOTO BadButton];
y ← Real.RoundI[data.bounds.h]-GetValue[data.y ! badButton => GOTO BadButton];
Imager.SetColor[data.context, color];
TiogaImager.Render[formattedNode.box, data.context, [x, y]];
EXITS
BadButton => Blink["Bad coordinates(s)"];
BadText => Blink["Bad selection"];
BadColor => Blink["Bad color (see ImagerColor.mesa)"];
};
CtInfo
CtInfoData: TYPE ~ REF CtInfoDataRec;
CtInfoDataRec:
TYPE ~
RECORD [
viewer: Viewer ← NIL,
colorDisplayChanged: BOOL ← FALSE,
out: STREAM ← NIL,
pm: PixelMapMisc,
cmap: Cmap ← NIL,
x, y: INTEGER ← 0
];
PixelInfo:
TYPE ~
RECORD [
pval: CARDINAL,
red: CARDINAL,
grn: CARDINAL,
blu: CARDINAL
];
SeColorDisplayInfo:
PROC [info: CtInfoData] ~ {
info.pm ← ColorTrixBasics.GetColorDisplayPmMisc[];
info.cmap ← IF info.pm.bpp = 8 THEN ColorTrixMap.Read[] ELSE NIL;
};
CtInfo: Commander.CommandProc ~ {
nArgs: INTEGER ← Args.NArgs[cmd];
IF nArgs # 0
AND nArgs # 2
THEN RETURN[$Failure, Rope.Concat["Bad argument(s); usage: ", ctInfoUsage]]
ELSE
SELECT nArgs
FROM
0 => {
info: CtInfoData ← NEW[CtInfoDataRec];
SeColorDisplayInfo[info];
info.viewer ← TypeScript.Create[info: [openHeight: 400, name: "CtInfo", data: info, scrollable: TRUE, column: right, iconic: TRUE]];
ViewerOps.OpenIcon[info.viewer];
info.out ← ViewerIO.CreateViewerStreams[NIL, info.viewer].out;
TRUSTED {Process.Detach[FORK Informer[info]]};
};
2 => {
x: Args.Arg ← Args.ArgInt[cmd, 0];
y: Args.Arg ← Args.ArgInt[cmd, 1];
pm: PixelMapMisc ← ColorTrixBasics.GetColorDisplayPmMisc[];
cmap: Cmap ← IF pm.bpp = 8 THEN ColorTrixMap.Read[] ELSE NIL;
IF NOT x.ok OR NOT y.ok THEN RETURN[$Failure, "Bad argument(s)."];
IF
NOT CoordinatesOK[pm, x.int, y.int]
THEN
RETURN[
$Failure,
IO.PutFR["(x, y) must be ([0..%g), [0..%g))", IO.int[pm.w], IO.int[pm.h]]];
APixel[cmd.out, pm, cmap, x.int, y.int];
};
ENDCASE => NULL;
};
CDNotifyProc: ColorDisplay.CDNotifyProc ~ {
IF old # new THEN NARROW[clientData, CtInfoData].colorDisplayChanged ← TRUE;
};
Informer:
PROC [info: CtInfoData] ~
TRUSTED {
report: BOOL ← FALSE;
key: TerminalDefs.KeyName;
action: ClassIncreek.ActionBody;
increek: ClassIncreek.Increek ← ClassIncreek.NewStdIncreek[];
viewPosition: ClassIncreek.ViewPosition ← ClassIncreek.GetPositionFrom[increek];
cdReg: ColorDisplay.CDRegistration ← ColorDisplay.RegisterCDNotifyProc[CDNotifyProc, info];
CedarProcess.SetPriority[background];
IO.PutRope[info.out, "\n"];
WHILE
NOT info.viewer.destroyed
DO
IF info.colorDisplayChanged
THEN {
SeColorDisplayInfo[info];
info.colorDisplayChanged ← FALSE;
};
action ← ClassIncreek.GetAction[self: increek, acceptance: clicksAndMotion];
IF viewPosition.mousePosition.color
THEN {
WITH ac: action
SELECT
FROM
keyDown => IF ac.value IN [Red..Yellow] THEN {key ← ac.value; report ← TRUE};
keyUp => IF ac.value IN [Red..Yellow] THEN {key ← ac.value; report ← FALSE};
ENDCASE;
IF report
THEN {
WITH ac: action
SELECT
FROM
keyDown, deltaMouse => {
info.x ← viewPosition.mousePosition.mouseX;
info.y ← info.pm.h-viewPosition.mousePosition.mouseY;
};
ENDCASE;
IF key = Blue
THEN
WITH ac: action
SELECT
FROM
keyDown => ManyPixels[info];
ENDCASE
ELSE
WITH ac: action
SELECT
FROM
keyDown, deltaMouse => APixel[info.out, info.pm, info.cmap, info.x, info.y];
ENDCASE;
};
};
ENDLOOP;
ColorDisplay.UnregisterCDNotifyProc[cdReg];
};
APixel:
PROC [out:
STREAM, pm: PixelMapMisc, cmap: Cmap, x, y:
INTEGER] ~ {
pix: PixelInfo ← GetPixelInfo[pm, cmap, x, y];
SELECT pm.bpp
FROM
8 =>
IO.PutRope[out, Rope.Concat[
IO.PutFR["8 bit pixel at (%g, %g): %g ", IO.int[x], IO.int[y], IO.card[pix.pval]],
IO.PutFR["(r: %g, g: %g, b: %g)\n",
IO.int[cmap[0][pix.pval]], IO.int[cmap[1][pix.pval]], IO.int[cmap[2][pix.pval]]]]];
24 =>
IO.PutRope[out,
IO.PutFR["24 bit pixel at (%g, %g), r: %g, g: %g, b: %g\n",
IO.int[x], IO.int[y], IO.card[pix.red], IO.card[pix.grn], IO.card[pix.blu]]];
ENDCASE => NULL;
};
ManyPixels:
PROC [info: CtInfoData] ~ {
pixs: ARRAY [0..5) OF ARRAY [0..5) OF PixelInfo;
Bar:
PROC ~ {
IF info.pm.bpp = 8
THEN IO.PutF[info.out, "——————————————————————————————————\n"]
ELSE IO.PutF[info.out, "——————————————————————\n"]
};
PrintLine:
PROC [j:
INTEGER, proc:
PROC [i, j:
INTEGER], report:
BOOL ←
FALSE] ~ {
IF proc # PrintX THEN IO.PutRope[info.out, "| "];
FOR i: NAT IN [0..5) DO proc[i, j]; ENDLOOP;
IF report THEN IO.PutF[info.out, " %g", IO.int[info.y-2+j]];
IO.PutRope[info.out, "\n"];
};
PrintX:
PROC [i, j:
INTEGER] ~ {
IF info.pm.bpp = 8
THEN IO.PutF[info.out, " %3g\t", IO.int[info.x-2+i]]
ELSE IO.PutF[info.out, " %3g\t", IO.int[info.x-2+i]];
};
PrintPval:
PROC [i, j:
INTEGER] ~ {
IO.PutF[info.out, " %-3g\t\t|", IO.card[pixs[i][j].pval]];
};
PrintRed: PROC [i, j: INTEGER] ~ {PrintCard["r", pixs[i][j].red]};
PrintGrn: PROC [i, j: INTEGER] ~ {PrintCard["g", pixs[i][j].grn]};
PrintBlu: PROC [i, j: INTEGER] ~ {PrintCard["b", pixs[i][j].blu]};
PrintCard:
PROC [rope:
ROPE, card:
CARDINAL] ~ {
IF info.pm.bpp = 8
THEN IO.PutF[info.out, " %g: %3g\t|", IO.rope[rope], IO.card[card]]
ELSE IO.PutF[info.out, " %3g\t|", IO.card[card]];
};
FOR j:
NAT
IN [0..5)
DO
y: INTEGER ← info.y-2+j;
FOR i:
NAT
IN [0..5)
DO
pixs[i][j] ← GetPixelInfo[info.pm, info.cmap, info.x-2+i, y];
ENDLOOP;
ENDLOOP;
IO.PutF[
info.out, "\n%g bit pixels centered at (%g, %g):\n",
IO.int[info.pm.bpp], IO.int[info.x], IO.int[info.y]];
Process.Pause[Process.MsecToTicks[100]];
[] ← info.viewer.class.scroll[info.viewer, thumb, 100];
PrintLine[0, PrintX];
Bar[];
FOR line:
NAT
IN [0..5)
DO
IF info.pm.bpp = 8 THEN PrintLine[line, PrintPval];
PrintLine[line, PrintRed];
PrintLine[line, PrintGrn, TRUE];
PrintLine[line, PrintBlu];
Bar[];
ENDLOOP
};
CoordinatesOK:
PROC [pm: PixelMapMisc, x, y:
INTEGER]
RETURNS [
BOOL] ~ {
RETURN[x IN [0..pm.w) AND y IN [0..pm.h)];
};
GetPixelInfo:
PROC [pm: PixelMapMisc, cmap: Cmap, x, y:
INTEGER]
RETURNS [PixelInfo] ~ {
pix: PixelInfo;
GetInner:
PROC ~ {
IF CoordinatesOK[pm, x, y]
THEN
SELECT pm.bpp
FROM
8 => {
pix.pval ← ImagerPixelMap.GetPixel[pm.bw, y, x];
pix.red ← cmap[0][pix.pval];
pix.grn ← cmap[1][pix.pval];
pix.blu ← cmap[2][pix.pval];
};
24 =>
[pix.red, pix.grn, pix.blu] ← ColorTrixBasics.GetRGBPixel[pm, x, y];
ENDCASE => NULL;
};
Terminal.ModifyColorFrame[Terminal.Current[], GetInner, x, y, x+1, y+1];
RETURN[pix];
};
Start Code
ctTextUsage:
ROPE ~
"\nCtText [x, y: INT, text: ROPE]
If arguments given, print text starting at pixel loaction (x, y).
Otherwise, create a viewer to print any selected text.";
ctInfoUsage: ROPE ~ "\nctInfo [x, y: INT]: Print the pixel value at (x, y).";
ctDifUsage: ROPE ~ "\nctDif <x0 y0 x1 y1 x2 y2 w h> Display |dif| between windows.";
ViewerOps.RegisterViewerClass[$Info,
NEW[ViewerClasses.ViewerClassRec]];
Commander.Register["///Commands/CtText", CtText, ctTextUsage];
Commander.Register["///Commands/CtInfo", CtInfo, ctInfoUsage];
Commander.Register["///Commands/CtDif", CtDif, ctDifUsage];
END.