DIRECTORY ForkOps, Imager, ImagerSample, Process, Rope, SF, Xl, XlBitmap, XlBWFriends, XlColorAccess, XlDetails, XlShmPixmaps, XTk, XTkFriends, XTkBitmapWidgets, XTkBitmapWidgetsExtras, XTkShellWidgets; XTkBitmapWidgetsImpl: CEDAR MONITOR LOCKS bmRef USING bmRef: REF BMRec IMPORTS ForkOps, ImagerSample, Process, Rope, SF, Xl, XlBitmap, XlBWFriends, XlColorAccess, XlDetails, XlShmPixmaps, XTk, XTkFriends, XTkShellWidgets EXPORTS XTkBitmapWidgets, XTkBitmapWidgetsExtras SHARES XlBWFriends = BEGIN OPEN Xl, XTk, XTkBitmapWidgets; bmClass: ImplementorClass ¬ XTkFriends.CreateClass[[ key: $bitmapWidget, wDataNum: 1, configureLR: BMConfigureLR, destroyWindowLR: BMDestroyWindowLR, preStopFastAccess: BMPreStopFastAccess, fullStopFastAccessLR: BMFullStopFastAccessLR, destroyWidget: BMDestroyWidget, initInstPart: InitInstPart, eventMask: [exposure: TRUE, structureNotify: TRUE], backgroundKey: $white ]]; BMRec: TYPE = MONITORED RECORD [ wAsUsed: XlBWFriends.WRef ¬ NIL, wInternal: XlBWFriends.WRef ¬ NIL, bm: XlBitmap.Bitmap ¬ NIL, origin: Xl.Point ¬ [0, 0], restrict: SF.Box ¬ SF.maxBox, notify: BitmapEventProc, mapped: BOOL ¬ FALSE, data: REF ¬ NIL, ownedBitmap: XlBitmap.Bitmap ¬ NIL, support8: BOOL ¬ FALSE, support4: BOOL ¬ FALSE, support2: BOOL ¬ FALSE, shmData: REF ShmData ¬ NIL, gc: Xl.GContext ]; ShmData: TYPE = RECORD [ shmPixmap: Xl.Pixmap ¬ Xl.nullPixmap, c: Xl.Connection ¬ NIL, bm: XlBitmap.Bitmap ¬ NIL ]; noErrors: Xl.Details ~ XlDetails.ignoreErrors; NoOp: Xl.EventProcType ~ {}; mPadNoErrors: Xl.Details ~ NEW[Xl.DetailsRec ¬ [ errorMatch: NEW[Xl.MatchRep ¬ [proc: NoOp]], specific: $ZPixmap ]]; MPadBugActualPaint1: PROC[b: SF.Box, ref: REF] = { w: XlBWFriends.WRef ~ NARROW[ref]; bpp: INT ~ 1; dirtyFix: INT ¬ b.min.f MOD 32; IF w.offset.x+b.min.f { bmRef.mapped ¬ TRUE; SetBM[bmRef, widget, FALSE, FALSE]; bmRef.notify[widget, map, bmRef.data]; }; unmapNotify => { bmRef.mapped ¬ FALSE; Stop[bmRef]; bmRef.notify[widget, unmap, bmRef.data]; }; expose => { e: Xl.ExposeEvent ~ NARROW[event]; s: XlBWFriends.SRef; w: XlBWFriends.WRef ~ bmRef.wAsUsed; IF w=NIL OR (s ¬ w.s)=NIL THEN RETURN; XlBWFriends.IncludeRect[s, w, [ min: [s: e.pos.y-w.offset.y, f: e.pos.x-w.offset.x], max: [s: e.pos.y+e.size.height-w.offset.y, f: e.pos.x+e.size.width-w.offset.x] ], e.count#0]; }; ENDCASE => {}; }; }; FreeShmData: PROC [x: REF] = { WITH x SELECT FROM sd: REF ShmData => { pm: Xl.Pixmap ¬ sd.shmPixmap; sd.shmPixmap ¬ Xl.nullPixmap; IF Xl.Alive[sd.c] AND pm#Xl.nullPixmap THEN Xl.FreePixmap[sd.c, pm, noErrors]; }; ENDCASE => {} }; DelayedDestroyShmData: PROC [sd: REF ShmData] = { IF sd#NIL THEN ForkOps.ForkDelayed[100, FreeShmData, sd] }; BMDestroyWindowLR: TerminateProc = { bmRef: REF BMRec ~ GetInstData[widget]; sd: REF ShmData ~ bmRef.shmData; bmRef.shmData ¬ NIL; IF bmRef.notify#NIL THEN bmRef.notify[widget, destroyWindow, bmRef.data]; XTkFriends.SimpleDestroyWindowLR[widget, reason]; Stop[bmRef]; IF sd#NIL THEN DelayedDestroyShmData[sd]; }; BMConfigureLR: ConfigureProc = { bmRef: REF BMRec ~ GetInstData[widget]; existW, createW: BOOL; reason: BitmapEventReason ¬ resize; existW ¬ widget.actualMapping NULL; --always works 8 => IF ~bmRef.support8 THEN RETURN; --it wouldn't work 4 => IF ~bmRef.support4 THEN RETURN; --it wouldn't work 2 => IF ~bmRef.support2 THEN RETURN; --it wouldn't work ENDCASE => { }; Stop[bmRef]; w ¬ NEW[XlBWFriends.WRec]; w.c ¬ widget.connection; w.d ¬ widget.window; w.bm ¬ bm; w.base ¬ LOOPHOLE[ImagerSample.GetBase[rsm].word]; w.offset ¬ origin; sd ¬ bmRef.shmData; IF sd#NIL AND sd.c=w.c AND sd.bm=bm AND sd.shmPixmap#Xl.nullPixmap THEN shmP ¬ sd.shmPixmap --reuse it ELSE { IF XlShmPixmaps.ConnectionSupportsPixmaps[w.c] AND XlShmPixmaps.SampleMapSupportsThis[rsm] THEN { shmP ¬ XlShmPixmaps.UnsafeCreatePixmap[c: w.c, drawable: w.d, sm: rsm ! Xl.XError => { shmP ¬ Xl.nullPixmap; CONTINUE } ]; IF shmP=Xl.nullPixmap THEN bmRef.shmData ¬ NIL ELSE bmRef.shmData ¬ NEW[ShmData ¬ [shmPixmap: shmP, c: w.c, bm: bm]]; IF sd#NIL THEN DelayedDestroyShmData[sd]; }; }; w.clip ¬ SF.Intersect[clip, SF.Intersect[pseudoInfinitBox, XlBitmap.GetBox[bm]]]; w.scanLineBytes ¬ ImagerSample.GetBitsPerLine[rsm]/8; w.gc ¬ bmRef.gc; IF shmP=Xl.nullPixmap THEN { SELECT ImagerSample.GetBitsPerSample[rsm] FROM 1 => { IF widget.screenDepth.depth=4 THEN {paintProc ¬ IBMBugActualPaint1; currentCase ¬ "ibm 6000 bug fix"} ELSE {paintProc ¬ ActualPaint1; currentCase ¬ "1 bpp, remote"}; w.overheadCost ¬ 48+40 }; 8 => { paintProc ¬ ActualPaint8; w.overheadCost ¬ 6+10; currentCase ¬ "8 bpp, remote"; }; 2 => { paintProc ¬ ActualPaint2; w.overheadCost ¬ 24+20; currentCase ¬ "2 bpp, remote"; }; 4 => { paintProc ¬ ActualPaint4; w.overheadCost ¬ 12+20; currentCase ¬ "4 bpp, remote"; }; 24 => { paintProc ¬ ActualPaint24; w.overheadCost ¬ 0+4; currentCase ¬ "24 bpp, remote"; }; ENDCASE => {RETURN}; } ELSE { w.sharedD ¬ shmP; IF ImagerSample.GetBitsPerSample[rsm]=1 THEN { paintProc ¬ ShmPaintCopyPlane; w.overheadCost ¬ 40000; currentCase ¬ "1 bpp, shm"; } ELSE { paintProc ¬ ShmPaintCopyArea; w.overheadCost ¬ 20000; currentCase ¬ "multi bpp, shm"; } }; vendor ¬ Xl.Info[w.c].vendor; IF Rope.Equal[vendor, "Xerox Split MPAD"] THEN { w.overheadCost ¬ 2; w.serverQueueLimit ¬ 10; paintProc ¬ MPadBugActualPaint1; currentCase ¬ Rope.Concat[currentCase, " MPAD"]; }; WITH XTk.GetWidgetProp[widget, $OverheadCost] SELECT FROM ri: REF INT => { w.overheadCost ¬ ri­; WITH XTk.GetWidgetProp[widget, $ServerQueueLimit] SELECT FROM ri: REF INT => w.serverQueueLimit ¬ ri­; ENDCASE => {}; }; ENDCASE => {}; w.report ¬ LIST[[paintProc, w]]; XTk.PutWidgetProp[widget, $XTkBitmapWidgetsImpl, currentCase]; bmRef.wInternal ¬ w; IF bmRef.mapped THEN { XlBWFriends.StartWRef[w]; Set[bmRef, w]; ClearOutsideAreas[widget]; IF immediateRefresh OR retainRefreshs THEN XlBWFriends.IncludeRect[w.s, w, clip, FALSE]; }; } }; ClearOutsideAreas: PROC [w: XTk.Widget] = { ENABLE ANY => GOTO Oops; Clear: PROC [pos: Point, size: Size] = { Xl.ClearArea[c, win, pos, size, FALSE, noErrors]; }; Fill: PROC [pos: Point, size: Size] = { Xl.FillRectangle[c, win, bmRef.gc, pos, size, noErrors]; }; infinite: INT = 9999; bmRef: REF BMRec ~ GetInstData[w]; c: Xl.Connection ¬ w.connection; win: Xl.Window ¬ w.window; r: SF.Box ¬ SF.Displace[bmRef.restrict, [bmRef.origin.y, bmRef.origin.x]]; IF win=Xl.nullWindow OR w.fastAccessAllowed#ok THEN RETURN; IF r.min.f>0 THEN Clear[[0, 0], [r.min.f, infinite]]; IF r.min.s>0 THEN Clear[[r.min.f, 0], [infinite, r.min.s]]; Clear[[r.max.f, 0], [infinite, infinite]]; Clear[[0, r.max.s], [infinite, infinite]]; IF XTk.GetWidgetProp[w, $BitmapBorder]#NIL THEN { <> Fill[[r.min.f-1, r.min.s-1], [1, r.max.s-r.min.s+2]]; <> Fill[[r.max.f, r.min.s-1], [1, r.max.s-r.min.s+2]]; <> Fill[[r.min.f-1, r.min.s-1], [r.max.f-r.min.f+2, 1]]; <> Fill[[r.min.f-1, r.max.s], [r.max.f-r.min.f+2, 1]]; }; EXITS Oops => {}; }; pseudoInfinitBox: SF.Box ~ [min: [-8000, -8000], max: [8000, 8000]]; --artificial clip region used to prevent arithmetic overflow GetImplData: PUBLIC PROC [widget: BitmapWidget] RETURNS [REF] = { bmRef: REF BMRec ~ GetInstData[widget]; RETURN [bmRef.wAsUsed]; }; Wait: PUBLIC PROC [widget: BitmapWidget, server: BOOL ¬ FALSE] = { bmRef: REF BMRec ~ GetInstData[widget]; w: XlBWFriends.WRef ¬ bmRef.wAsUsed; IF w#NIL THEN { timedOut: BOOL ¬ XlBWFriends.WaitLocal[w.s, w].timedOut; IF timedOut AND server THEN { WHILE XlBWFriends.WaitLocal[w.s, w].timedOut DO ENDLOOP; }; IF server AND Xl.Alive[w.c] THEN Xl.RoundTrip[w.c]; } ELSE Process.Yield[]; }; noWhereBM: XlBitmap.Bitmap ~ XlBitmap.Create[[1, 1], 1, FALSE]; CreateContext: PUBLIC PROC [widget: BitmapWidget, surfaceUnitsPerPixel: NAT ¬ 1] RETURNS [context: Imager.Context] = { bmRef: REF BMRec ~ GetInstData[widget]; bm: XlBitmap.Bitmap ¬ bmRef.bm; IF bm=NIL THEN bm ¬ noWhereBM; context ¬ XlBitmap.CreateContext[bm, surfaceUnitsPerPixel]; }; CreateAndSetBitmap: PUBLIC PROC [widget: BitmapWidget, size: SF.Vec, bpp: NAT ¬ 1, origin: Xl.Point ¬ [0, 0]] = { bmRef: REF BMRec ~ GetInstData[widget]; bm: XlBitmap.Bitmap; IF bpp=0 AND widget.screenDepth#NIL THEN { IF XlColorAccess.FindVisualType[widget.screenDepth.screen, 8, Xl.VisualClass.pseudoColor]#NIL THEN bpp ¬ 8 ELSE IF XlColorAccess.FindVisualType[widget.screenDepth.screen, 4, Xl.VisualClass.pseudoColor]#NIL THEN bpp ¬ 4 ELSE bpp ¬ 1; }; IF bpp=0 THEN bpp ¬ 1; bm ¬ XlBitmap.Create[size, bpp]; SetBitmap[widget: widget, bitmap: bm, origin: origin]; FollowColors[widget, bm]; }; FollowColors: PUBLIC PROC [widget: XTk.Widget, bitmap: XlBitmap.Bitmap] = { bmRef: REF BMRec ~ GetInstData[widget]; bmRef.ownedBitmap ¬ bitmap; FollowColorsOnce[widget, bitmap]; }; FollowColorsOnce: PUBLIC PROC [widget: XTk.Widget, bitmap: XlBitmap.Bitmap] = { screenDepth: Xl.ScreenDepth ¬ widget.screenDepth; IF bitmap#NIL AND screenDepth#NIL THEN { sm: ImagerSample.RasterSampleMap ~ XlBitmap.GetSM[bitmap]; bbp: NAT ¬ ImagerSample.GetBitsPerSample[sm]; IF bbp>1 THEN { cd: XlColorAccess.ColorData ¬ XlColorAccess.Access[screenDepth.screen, bbp, Xl.VisualClass.pseudoColor]; IF cd#NIL AND cd.hasColors THEN { XlBitmap.SetColormap[bitmap, cd.entries]; IF cd.hasPrivateColormap AND widget.attributes.colorMap#cd.colormap AND widget.fastAccessAllowed=ok THEN { attributes: Xl.Attributes ¬ []; widget.attributes.colorMap ¬ attributes.colorMap ¬ cd.colormap; XlBitmap.SetColormap[bitmap, cd.entries]; XTkShellWidgets.TrackColorMap[shell: NIL, w: widget]; Xl.ChangeWindowAttributes[widget.connection, widget.window, attributes, noErrors]; }; }; }; }; }; END. FXTkBitmapWidgetsImpl.mesa Copyright Σ 1988, 1989, 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Christian Jacobi, October 21, 1988 1:13:59 pm PDT Christian Jacobi, August 16, 1993 2:11 pm PDT --window relative --Prevent raising an error on negative dest.x. --However, some pixels will be missing --Prevent raising an error on negative dest.x. --However, some pixels will be missing --X protocol says left-pad must be 0 for zPixmap format --Horrible case of unfriendly alignments --Prevent raising an error on negative dest.x. --However, some pixels will be missing --X protocol says left-pad must be 0 for zPixmap format --Horrible case of unfriendly alignments --Prevent raising an error on negative dest.x. --However, some pixels will be missing --X protocol says left-pad must be 0 for zPixmap format --Horrible case of unfriendly alignments --Prevent raising an error on negative dest.x. --However, some pixels will be missing --X protocol says left-pad must be 0 for zPixmap format --Horrible case of unfriendly alignments --Prevent raising an error on negative dest.x. --However, some pixels will be missing --Because we do not stop the painters immediately --Very short delay so bitmap will be finalized soon In bitmap format 1 delivers foreGround; compensate for zPixmap format --No test yet developped; --Take your chance that it works or crashes --we wrongly believed shared memory would work --overhead cost compensates for transferring request overhead (PutImage=6 words) --it is scaled to compensate for cost function strictly assuming 8 bits per pixel --is sligtly increased for a wild guess of per request overhead --overhead is wild guess on how much unification is justified --This server uses slow radio communication in spite of possible presence of shared memory --for experimenting to find out reasonable overheadCost --remember: paints [0, 0] of bitmap at point "origin" in window --clear left half space --clear direct upper and upper right quarter space --clear direct right and right lower quarter space --clear direct under and right lower quarter space Κ'–(cedarcode) style•NewlineDelimiter ˜code™Kšœ ΟeœO™ZK™1K™-—K˜šΟk œ˜ K˜K˜Kšœ ž˜ K˜Kšœž˜Kšžœ˜K˜K˜ K˜ K˜K˜ K˜ K˜K˜ K˜K˜Kšœ˜K˜—šΟnœžœžœ˜$Kšžœžœžœ˜"Kšžœžœžœžœe˜•Kšžœ)˜0Kšžœ˜—Kšžœžœ˜%K˜šœ4˜4Kšœ!˜!Kšœ˜Kšœ$˜$Kšœ(˜(Kšœ.˜.Kšœ ˜ Kšœ˜Kšœžœžœ˜4Kšœ˜Kšœ˜—K˜šœžœž œžœ˜ Kšœžœ˜ Kšœžœ˜"Kšœžœ˜Kšœ˜Kšœ žœžœ˜K˜Kšœžœžœ˜Kšœžœžœ˜Kšœž˜#K™Kšœ žœžœ˜Kšœ žœžœ˜Kšœ žœžœ˜Kšœ žœ žœ˜K˜K˜K˜—šœ žœžœ˜K˜%Kšœžœ˜Kšœž˜K˜—K˜K˜.KšŸœ˜šœžœ˜0Kšœ žœ˜,K˜K˜—K˜šŸœžœžœ žœ˜2Kšœžœ˜"Kšœžœ˜ Kšœ žœ žœ˜šžœžœ˜%Kšœ/™/Kšœ&™&K˜K˜—K˜K˜K˜—šŸœžœžœ žœ˜1Kšœžœ˜"Kšœžœ˜ Kšœ žœ žœ˜šžœžœ˜%Kšœ/™/Kšœ&™&K˜K˜—K˜™K˜K˜—šŸ œžœžœ žœ˜+Kšœžœ˜"Kšœžœ˜ Kšœ žœ˜K˜™K˜K˜—šŸ œžœžœ žœ˜+Kšœžœ˜"Kšœžœ˜ Kšœ žœ Οc*˜Cšœ žœ žœ ˜%K™7—šžœžœ˜%K™(Kšœ/™/Kšœ&™&K˜K˜—K˜™K˜K˜—šŸ œžœžœ žœ˜+Kšœžœ˜"Kšœžœ˜ Kšœ žœ  *˜Cšœ žœ žœ ˜%K™7—šžœžœ˜%K™(Kšœ/™/Kšœ&™&K˜K˜—K˜™K˜K˜—šŸ œžœžœ žœ˜+Kšœžœ˜"Kšœžœ˜ Kšœ žœ  *˜Cšœ žœ žœ ˜%K™7—šžœžœ˜%K™(Kšœ/™/Kšœ&™&K˜K˜—K˜™K˜K˜—šŸ œžœžœ žœ˜,Kšœžœ˜"Kšœžœ˜šœ žœ žœ˜K™7Kš *˜*—šžœžœ˜%K™(Kšœ/™/Kšœ&™&K˜K˜—K˜™K˜K˜—šŸœžœžœ žœ˜0Kšœžœ˜"K˜ΠK˜K˜—šŸœžœžœ žœ˜/Kšœžœ˜"K˜ΒK˜—K˜š Ÿ œžœ žœžœ žœ˜K˜šžœžœ˜K˜K˜K˜šžœžœžœ˜+Kšœ&žœ˜-—K˜—K˜—K˜K˜—šŸœžœ˜+Kšžœžœžœ˜šŸœžœ˜(Kšœ žœ ˜1K˜—šŸœžœ˜'K˜8K˜—Kšœ žœ˜Kšœžœ˜"K˜ K˜Kšœžœžœ<˜JKšžœžœžœžœ˜;K™?K™Kšžœ žœ$˜5K™2Kšžœ žœ*˜;K™2K˜*K™2K˜*šžœ%žœžœ˜1K˜>K˜=K˜=K˜>K˜—Kšžœ ˜K˜K˜—Kšœžœ1 <˜K˜š Ÿ œžœžœžœžœ˜AKšœžœ˜'Kšžœ˜K˜—K˜š Ÿœžœžœ žœžœ˜BKšœžœ˜'K˜$šžœžœ˜ šžœ˜Kšœ žœ*˜8šžœ žœžœ˜Kšžœ(žœžœ˜8K˜—Kšžœžœžœ˜3K˜—Kšžœ˜—K˜K˜—Kšœ8žœ˜?K˜š Ÿ œžœžœ.žœžœ˜vKšœžœ˜'K˜Kšžœžœžœ˜K˜;K˜K˜—š Ÿœžœžœžœ žœ$˜qKšœžœ˜'K˜šžœžœžžœ˜*KšžœXžœžœ ˜kKšžœXžœžœœ˜oKšžœ ˜ K˜—Kšžœžœ ˜K˜ K˜6K˜K˜K˜—šŸ œžœžœ2˜KKšœžœ˜'K˜K˜!K˜K˜—šŸœžœžœ2˜OK˜1š žœžœžœ žœžœ˜(K˜:Kšœžœ%˜-šžœžœ˜K˜hšžœžœžœžœ˜!K˜)šžœžœ(žœžœ˜jKšœ˜K˜?K˜)Kšœ%žœ ˜5K˜RK˜—K˜—K˜—K˜—K˜—K˜Kšžœ˜K˜—…—I2dŸ