Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!thunder.mcrcim.mcgill.edu!snorkelwacker.mit.edu!apple!decwrl!adobe!hawley From: hawley@adobe.COM (Steve Hawley) Newsgroups: comp.sys.mac.programmer Subject: Re: An itsy bitsy question... Message-ID: <9700@adobe.UUCP> Date: 7 Jan 91 21:47:44 GMT References: <27725.2787e3d0@kuhub.cc.ukans.edu> Reply-To: hawley@adobe.UUCP (Steve Hawley) Organization: Adobe Systems Incorporated, Mountain View Lines: 101 In article <27725.2787e3d0@kuhub.cc.ukans.edu> mlab2@kuhub.cc.ukans.edu writes: >In article , aberno@questor.wimsey.bc.ca (Anthony Berno) writes: |> How is the "rubberbanding" done in programs like Superpaint when you are |> drawing a line on the screen? |> Anthony Berno. | |When in line-drawing-mode, a mouseDown event in the drawing window should call |a procedure similar to the below: |procedure RubberBand; | var | originalPt, lastPt, newPt : Point; |begin | GetMouse(originalPoint); | PenMode(patXOr); | GetMouse(lastPt); | MoveTo(originalPt.h, originalPt.v); | LineTo(lastPt.h, lastPt.v); | repeat | MoveTo(originalPt.h, originalPt.v); | LineTo(lastPt.h, lastPt); | GetMouse(newPt); | MoveTo(originalPt.h,originalPt.v); | LineTo(newPt.h, newPt.v); | lastPt:=newPt; | until (not Button); | PenNormal; |end; Problem: 1) If the mouse doesn't move, the line will be flickering very badly. 2) The MoveTo/LineTo pairs are separated by a GetMouse() which will increase the flicker. 3) Erasing the old line first increases the "apparent" flicker 4) The loop should be terminated by the StillDown() function, not Button() Solution: repeat GetMouse(newPt); MoveTo(originalPt.h, originalPt.v); { Do the new point first } LineTo(newPt.h, newPt.v); { This reduces apparent flicker } MoveTo(originalPt.h, originalPt.v); LineTo(lastPt.h, lastPt.v); lastPt := newPt; until (not StillDown(...I forget the args...)); Problem: 1) In such a tight loop, the overhead of the trap dispatcher is significant and contributes to the flicker in a bad way. Solution: Get the real function address from the GrafPorts QD procs in variables and execute them directly Problem: 1) When the new point differs from the old point by only a small amount, the line will still flicker because of the large amount of common area between the two lines, ie, drawing the new line will XOR over a large part of the old line leaving a big blank spot until the old line is re-drawn. Solution: Copy window contents into offscreen bitmap #1 (a paint program would have this as the actual image data) SetPort to your own GrafPort that you have already setup with offscreen bitmap #2 as its portBits Hide the cursor repeat Get the new mouse coordinates CopyBits the smallest rectangle that encloses the old line, the new line and the cursor from bitmap #1 to bitmap #2 Draw the new line in your port CopyBits the cursor mask onto bitmap #2 CopyBits the cursor data onto bitmap #2 CopyBits the smallest rectangle that encloses the old line, the new line and the cursor from bitmap #2 to the window until (not StillDown(...)); Show the cursor Can you say "Yuck"? I knew you could... The final method will give a minimal amount of flicker. The problem is that moving all that data around gets to be expensive in terms of response, escpecially on bit lines. For bonus points, you'd want the bitmaps to be word or long word aligned to speed up the transfer, and you'd want the last CopyBits (to the screen) to be in sync with the VBL rate. The method that uses the pre-fetched addresses for the functions is probably suitable for most needs, although probably not in a professional product. Good luck... Steve Hawley hawley@adobe.com Disclaimer: Adobe pays me to hack printers, not Macs. I hack Macs in my spare time -- "I'm sick and tired of being told that ordinary decent people are fed up with being sick and tired. I know I'm certainly not, and I'm sick and tired of begin told that I am." -Monty Python