Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!mit-eddie!bloom-beacon!eru!hagbard!sunic!fuug!kth.se!cyklop.nada.kth.se!news From: d88-jwa@dront.nada.kth.se (Jon W{tte) Newsgroups: comp.sys.mac.programmer Subject: Re: An itsy bitsy question... Message-ID: <1991Jan8.170744.24848@nada.kth.se> Date: 8 Jan 91 17:07:44 GMT References: <27725.2787e3d0@kuhub.cc.ukans.edu> <9700@adobe.UUCP> Organization: Royal Institute of Technology, Stockholm, Sweden Lines: 110 In article <9700@adobe.UUCP> hawley@adobe.UUCP (Steve Hawley) writes: >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? >|When in line-drawing-mode, a mouseDown event in the drawing window >|should call a procedure similar to the below: >| GetMouse(originalPoint); This is not a good way to do it, You should assign originalPoint from the where field of the event ! >Problem: >1) If the mouse doesn't move, the line will be flickering very badly. Yup ! >3) Erasing the old line first increases the "apparent" flicker Yup... >4) The loop should be terminated by the StillDown() function, not Button() Yup ! >Solution: > > repeat > until (not StillDown(...I forget the args...)); No 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 NO ! This is NOT a recommended way anymore ! >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 >Solution: > Copy window contents into offscreen bitmap #1 (a paint program would have > this as the actual image data) [ lots of bitmap stuff deleted ] >Can you say "Yuck"? I knew you could... Fortunately, the solution is MUCH simpler ! >The method that uses the pre-fetched addresses for the functions is probably >suitable for most needs, although probably not in a professional product. It may break some exotic systems, too (like, the 8.24GC maybe ? Or some other stuff ? Don't know about A/UX, for example) >Good luck... I recommend the following function: Point RubberBand ( Point start ) { Point end , tmp ; PenPat ( gray ) ; PenMode ( patXor ) ; PenSize ( 1 , 1 ) ; GetMouse ( & end ) ; if ( ! StillDown ( ) ) return start ; MoveTo ( start . h , start . v ) ; LineTo ( end . h , end . v ) ; while ( StillDown ( ) ) { tmp = end ; GetMouse ( & end ) ; if ( end . v != tmp . v || end . h != tmp . h ) { LineTo ( start . h , start . v ) ; LineTo ( end . h , end . v ) ; } } return end ; } This routine looks very nice. One might argue that you should draw the new line first and erase the old later, but that's a matter of taste. Try it and see what you like best. Change the innermost LineTos to: MoveTo ( end . h , end . v ) ; LineTo ( start . h , start . v ) ; LineTo ( tmp . h , tmp . v ) ; The base of this approach is not to draw anything unless the pointer has moved, and then only redraw what's necessary once. No messing with offscreen bitmaps, and no messing with JSRs to long ints (shudder) or call of function pointers. Any problem can be solved easily and elegantly using some pure thought ;-) Happy hacking, H+ Jon W{tte, Stockholm, Sweden, h+@nada.kth.se