DIRECTORY Buttons, ChoiceButtons, Convert, CtBasic, CtDispatch, CtViewer, ImagerSample, IO, KeyNames, KeyTypes, MessageWindow, Process, Rope, SF, ViewerClasses, ViewerOps, ViewerTools; CtPaintCommandImpl: CEDAR PROGRAM IMPORTS Buttons, ChoiceButtons, Convert, CtBasic, CtDispatch, CtViewer, ImagerSample, IO, KeyNames, MessageWindow, Process, SF, ViewerOps, ViewerTools ~ BEGIN ButtonProc: TYPE ~ Buttons.ButtonProc; IntegerPair: TYPE ~ CtBasic.IntegerPair; RGB: TYPE ~ CtBasic.RGB; ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; control: KeyTypes.KeySym ¬ KeyNames.KeySymFromName["LeftControl"]; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ cmd: CtDispatch.CmdHandle ¬ NIL, pval: CARDINAL ¬ 100, rgb: RGB ¬ [100, 100, 100], size: INTEGER ¬ 25, halfSize: INTEGER ¬ 12, paintViewer: Viewer ¬ NIL, parent: Viewer ¬ NIL, pvalViewer: Viewer ¬ NIL, sizeViewer: Viewer ¬ NIL, redViewer: Viewer ¬ NIL, greenViewer: Viewer ¬ NIL, blueViewer: Viewer ¬ NIL, functionViewer: Viewer ¬ NIL, function: {paint, blur, incr} ¬ paint ]; ctPaintUsage: ROPE ~ "Ct Paint: interactive painting on a viewer."; CtPaint: CtDispatch.CtProc ~ { v: Viewer ¬ ViewerOps.FindViewer["Ct Paint"]; p: Data ¬ IF v = NIL THEN NEW[DataRep] ELSE NARROW[v.data]; p.cmd ¬ cmd; IF v = NIL THEN TRUSTED {Process.Detach[FORK MakePainter[p]]}; affect ¬ [[0, 0], [0, 0]]; -- caveat painter! CtViewer.RegisterMouse[p.paintViewer ¬ viewer, MouseProc, p]; }; MakePainter: PROC [p: Data] ~ { TextButton: PROC [x, y, w: NAT, name, text: ROPE] RETURNS [v: Viewer] ~ { v ¬ ChoiceButtons.BuildTextPrompt[p.parent, x, y, name, text,, w, p].textViewer; }; ViewerOps.OpenIcon[p.parent ¬ ViewerOps.CreateViewer[ flavor: $CtPaint, info: [openHeight: 34, name: "Ct Paint", data: p, column: right, iconic: TRUE]]]; p.sizeViewer ¬ TextButton[0, 3, 40, "size:", "25"]; p.pvalViewer ¬ TextButton[85, 3, 40, "p:", "100"]; p.redViewer ¬ TextButton[150, 3, 40, "r:", "100"]; p.greenViewer ¬ TextButton[215, 3, 40, "g:", "100"]; p.blueViewer ¬ TextButton[280, 3, 40, "b:", "100"]; p.functionViewer ¬ Buttons.Create[ info: [parent: p.parent, name: "paint", wx: 360, wy: 3], proc: Toggle, clientData: p]; }; MouseProc: CtViewer.MouseProc ~ { p: Data ¬ NARROW[clientData]; IF mouse.state = down AND mouse.button = left THEN CtViewer.DoWithViewer[p.paintViewer, Paint, p]; }; Paint: CtViewer.ViewerProc ~ { GetVal: PROC [v: Viewer] RETURNS [i: CARDINAL] ~ { i ¬ Convert.IntFromRope[ViewerTools.GetContents[v] ! Convert.Error => GOTO Bad]; EXITS Bad=>{MessageWindow.Append["bad value",TRUE];MessageWindow.Blink[]}; }; Poll: CtViewer.PollProc ~ { IF p.parent.destroyed THEN RETURN[FALSE] ELSE { Blur: PROC ~ { PixelProc: SAFE PROC [x, y: NAT] ~ { sum, sumR, sumG, sumB: CARDINAL ¬ 0; FOR yy: INTEGER IN [y-1..y+1] DO FOR xx: INTEGER IN [x-1..x+1] DO IF maps.bpp = 24 THEN { rgb: RGB ¬ CtBasic.GetRGBPixel[maps, xx, yy]; sumR ¬ sumR+rgb.r; sumG ¬ sumG+rgb.g; sumB ¬ sumB+rgb.b; } ELSE sum ¬ sum+CtBasic.GetBWPixel[maps[0].map, xx, yy]; ENDLOOP; ENDLOOP; IF maps.bpp = 24 THEN CtBasic.PutRGBPixel[maps, x, y, [sumR/9, sumG/9, sumB/9]] ELSE CtBasic.PutBWPixel[maps[0].map, x, y, CARDINAL[sum/9]]; }; FOR y: NAT IN [y0..y1] DO FOR x: NAT IN [x0..x1] DO PixelProc[x, y]; ENDLOOP; ENDLOOP; }; Paint: PROC ~ { IF maps.bpp = 24 THEN CtBasic.PutRGBBox[maps, x0, y0, x1, y1, p.rgb] ELSE ImagerSample.Fill[maps[0].map, [[y0, x0], [y1, x1]], p.pval]; }; Incr: PROC ~ { IF maps.bpp = 24 THEN p.rgb ¬ [ BYTE[(NAT[p.rgb.r]+1) MOD 255], BYTE[(NAT[p.rgb.g]+2) MOD 255], BYTE[(NAT[p.rgb.b]+3) MOD 255]] ELSE SELECT dir FROM positive => IF p.pval = 254 THEN dir ¬ negative ELSE p.pval ¬ p.pval+1; negative => IF p.pval = 1 THEN dir ¬ positive ELSE p.pval ¬ p.pval-1; ENDCASE; Paint[]; }; x0: INTEGER ¬ MAX[maps.x, pos.x-p.halfSize]; y0: INTEGER ¬ MAX[maps.y, pos.y-p.halfSize]; x1: INTEGER ¬ MIN[maps.box.max.f, x0+p.size]; y1: INTEGER ¬ MIN[maps.box.max.s, y0+p.size]; IF x0 # prev.x OR y0 # prev.y THEN { affect ¬ [SF.Min[affect.min, [y0, x0]], SF.Max[affect.max, [y1, x1]]]; SELECT p.function FROM paint => Paint[]; blur => Blur[]; ENDCASE => Incr[]; prev ¬ [x0, y0]; }; }; }; p: Data ¬ NARROW[clientData]; affect: SF.Box ¬ [[0, 0], [0, 0]]; prev: CtBasic.IntegerPair ¬ [-1, -1]; dir: {positive, negative} ¬ positive; IF CtViewer.KeyDown[control] THEN { -- pick pos: IntegerPair ¬ CtViewer.GetMousePos[viewer]; IF maps.bpp = 24 THEN { rgb: RGB ¬ CtBasic.GetRGBPixel[maps, pos.x, pos.y]; ViewerTools.SetContents[p.redViewer, IO.PutFR1["%g", IO.card[rgb.r]]]; ViewerTools.SetContents[p.greenViewer, IO.PutFR1["%g", IO.card[rgb.g]]]; ViewerTools.SetContents[p.blueViewer, IO.PutFR1["%g", IO.card[rgb.b]]]; } ELSE { v: CARDINAL ¬ CtBasic.GetBWPixel[maps[0].map, pos.x, pos.y]; ViewerTools.SetContents[p.pvalViewer, IO.PutFR1["%g", IO.card[v]]]; }; }; p.rgb ¬ [GetVal[p.redViewer], GetVal[p.greenViewer], GetVal[p.blueViewer]]; p.halfSize ¬ (p.size ¬ GetVal[p.sizeViewer])/2; p.pval ¬ GetVal[p.pvalViewer]; CtViewer.DoWhileMouseDown[viewer, Poll]; CtViewer.PutBuffer[viewer, maps, affect]; }; Destroy: ViewerClasses.DestroyProc ~ { CtViewer.UnregisterMouse[NARROW[self.data, Data].paintViewer, MouseProc]; }; Toggle: Buttons.ButtonProc ~ { p: Data ¬ NARROW[clientData]; p.function ¬ SELECT p.function FROM paint => blur, blur => incr, ENDCASE => paint; Buttons.ReLabel[p.functionViewer, SELECT p.function FROM paint => "paint", blur => "blur", ENDCASE => "incr"]; }; ViewerOps.RegisterViewerClass[$CtPaint, NEW[ViewerClasses.ViewerClassRec¬[destroy:Destroy]]]; CtDispatch.RegisterCtOp["Painting:", NIL, NIL]; CtDispatch.RegisterCtOp["Paint", CtPaint, ctPaintUsage]; END. ΄ CtPaintCommandImpl.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, July 3, 1992 3:51 pm PDT Types and Globals Paint Command Start Code ΚΡ•NewlineDelimiter –"cedarcode" style™™Jšœ Οeœ6™BJ™%—J˜JšΟk œOžœ4žœ(˜ΈJ˜šΠblœžœž˜!JšžœOžœ$žœ˜–—J˜Jšœž˜headšΟl™Jšœ žœ˜'Jšœžœ˜)Jšžœžœ žœ˜Jšžœžœžœ˜šœ žœ˜&J˜—J˜DJ˜—š  ™ Jšœžœžœ ˜šœ žœžœ˜Jšœ!žœ˜%Jšœ žœ˜Jšœžœ˜ Jšœ ž œ˜Jšœ ž œ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜J˜)J˜J˜—šœ žœ1˜CJ˜—šΟnœ˜J˜-Jš œ žœžœžœžœ žœžœ ˜;J˜ Jš žœžœžœžœžœ˜>JšœΟc˜-J˜=J˜J˜—š‘ œžœ˜š ‘ œžœ žœžœžœ˜IJ˜PJ˜—˜5J˜JšœIžœ˜Q—J˜3J˜2J˜2J˜4J˜3˜"J˜W—J˜J˜—š‘ œ˜!Jšœ žœ ˜šžœžœ˜-Jšžœ0˜4—J˜J˜—š‘œ˜š‘œžœ žœžœ˜2JšœFžœ˜PJšžΟsœ'žœ˜JJ˜—š‘œ˜šžœ˜Jšžœžœžœ˜šžœ˜š‘œžœ˜š‘ œž œžœ˜$Jšœžœ˜$šžœžœžœ ž˜ šžœžœžœ ž˜ šžœ˜šžœ˜Jšœžœ%˜-J˜8J˜—Jšžœ3˜7—Jšžœ˜—Jšžœ˜—šžœ˜Jš žœ£œ£œ£œ£œ£œ˜>Jšžœ'žœ ˜<—J˜—š ž£œ£ž£ž£œ£ž˜Jšž£œ£ž£ž£œ£ž£œ £œΠksžœ˜3Jšžœ˜—J˜—š‘œžœ˜šžœ˜Jšžœ/˜3Jšžœ>˜B—J˜—š‘œžœ˜šžœ˜šžœ ˜Jšžœžœ žœ˜Jšžœžœ žœ˜Jšžœžœ žœ˜—šžœžœž˜Jšœ žœžœžœ˜GJšœ žœ žœžœ˜EJšžœ˜——J˜J˜—Jšœžœžœ˜,Jšœžœžœ˜,Jšœžœžœ˜-Jšœžœžœ˜-šžœ žœ žœ˜$Jšœ žœžœ˜FJšžœ žœ"žœ ˜KJ˜J˜—J˜——J˜—Jšœ žœ ˜Jšœžœ˜"J˜%J˜%šžœžœ’˜+J˜0šžœ˜šžœ˜Jšœžœ+˜3Jšœ%žœžœ˜FJšœ'žœžœ˜HJšœ&žœžœ˜GJ˜—šžœ˜Jšœžœ1˜