sam@neoucom.UUCP (Scott A. Mason) (05/08/89)
I need some help from some of you more experienced Mac programmers. Although I am well versed in C, I am just starting to program in the Macintosh environment. I have a window which I use QuickDraw routines to draw characters. (Not a text edit window, that is) I am have difficulties responding to an update event. I have IM volumes and several different books, but none of them sufficiently covers the use of an offscreen buffer to store window info for updating. How does one set up an offscreen buffer so that CopyBits may be used to refresh the window when responding to an update event? -- -------------------------------------------------------------------------------- "If it ain't broke, don't fix it," and certainly don't blame me. UUCP: {pitt, scooter, hal, cwjcc}!neoucom!sam INTERNET: sam@neoucom.UUCP Scott A. Mason, Coordinator of Systems Operations, NEOUCOM
ksitze@nmsu.edu (Kevin Sitze) (05/10/89)
In article <sam@neoucom.UUCP's message of 8 May 89 04:17:52 GMT> >I have a window which I use QuickDraw routines to draw characters. (Not >a text edit window, that is) I am have difficulties responding to an >update event. I have IM volumes and several different books, but none of >them sufficiently covers the use of an offscreen buffer to store window >info for updating. > >How does one set up an offscreen buffer so that CopyBits may be used to >refresh the window when responding to an update event? This is really a rather simple procedure. The idea is to draw into an offscreen port and then CopyBits the wanted information to the desired window. To setup an offscreen port for drawing, you can do something like this... In Pascal (LSP): Function SetupPort : GrafPtr; var tmpPort, myPort : GrafPtr; begin GetPort(tmpPort); { Need to allocate memory for the port } myPort := GrafPtr(NewPtr(sizeof(GrafPort)); { -- Error checking for nil pointer goes here -- } { Create the internal structures for the port } OpenPort(myPort); { Now we need to set aside enough memory to draw into } with myPort^.portBits do begin baseAddr := NewPtr(rowBytes * (bounds.bottom - bounds.top)); { -- Error checking for nil pointer goes here -- } { Don't need to initialize any of the rest of the fields in } { the port because Quickdraw has done all we need already. } end; { And return the resulting port, voila, an offscreen graph port! } SetPort(tmpPort); SetupPort := myPort; end; or, for them (LS)C buffs... #define myBM myPort->portBits GrafPtr SetupPort() { GrafPtr tmpPort; register GrafPtr myPort; GetPort(&tmpPort); myPort = (GrafPtr) NewPtr(sizeof(GrafPort)); /* -- Error checking for nil pointer goes here -- */ /* Create the internal structures for the port */ OpenPort(myPort); /* Now we need to set aside enough memory to draw into */ myBM.baseAddr = NewPtr(myBM.rowBytes * (myBM.bounds.bottom - myBM.bounds.top)); /* -- Error checking for nil pointer goes here -- */ /* And return the resulting port, voila, an offscreen graph port! */ SetPort(tmpPort); return myPort; } #undef myBM There are several problems with the program as it stands above. 1) it does not have any error conditions. 2) It eats up about 6K of the heap everytime it's called (or more if your doing color, but if that's the case, you'll _need_ to look at Macintosh Technote #120) Notice that I saved the current port on entry, this is because I didn't really want SetupPort to change my current graph port. If you don't care, you can remove these lines (but you may never know when you may need them, I spent several hours tracking down a single missing SetPort once...not a pleasant experience.) You can save memory by passing a window to the procedure and then resizing the port to the window size. If you do this though, you have to resize the port everytime you resize the window, something of a bother. Enough of this, let's describe how to draw, etc. The procedure to draw into the newly created port may look something like this (in Pascal): Procedure DrawInMyPort( port : GrafPtr ); var tmpPort : GrafPtr; begin GetPort(tmpPort); SetPort(port); { various Quickdraw calls here } SetPort(tmpPort); end; And in C... DrawInMyPort(port) GrafPtr port; { GrafPtr tmpPort; GetPort(&tmpPort); SetPort(port); /* various Quickdraw calls here */ SetPort(tmpPort); } Pretty easy huh? The way the port is setup, you have the entire 'screen' to draw into, we'd have to do a few more calls if the window are 'larger' than the screen (e.g. paint programs). Finally, we want to do an update event, drawing from the offscreen port to a window: Procedure UpdateWind( wind : WindowPtr; port : GrafPtr ); var tmpPort; begin GetPort(tmpPort); SetPort(wind); BeginUpdate(wind); CopyBits(port^.portBits, wind^.portBits, port^.portRect, wind^.portRect, srcCopy, nil); EndUpdate(wind); SetPort(tmpPort); end; or #define NIL (0L) UpdateWind(wind, port); WindowPtr wind; GrafPtr port; { GrafPtr tmpPort; GetPort(&tmpPort); SetPort(wind); BeginUpdate(wind); CopyBits(&port->portBits, &wind->portBits, &port->portRect, &wind->portRect, srcCopy, NIL); EndUpdate(wind); SetPort(tmpPort); } These are all pretty much basic routines here but they should work. If you have any more questions, you might refer to the Macintosh technical notes. (You might be able to find the most recently distributed tn's on comp.mac.sources (comp.sources.mac?)) Specifically, TN#120 (which I know was uploaded recently) Hope this helps! -Kelesi -- ------------------------------------+------------------------------- From the Macintosh of: Kevin Sitze | Disclamer: Who the heck needs | a disclamer? After all, Dan EMail: ksitze%NMSU.edu | Quayle doesn't. SMail: 601 S. Melendres +------------------------------- Las Cruces, NM 88005 | "We have the answers, the ------------------------------------+ trouble lies in finding the "The difference between intelligence| questions..." and stupidity is that intelligence | "The information is there, has a limit." - anonymous | finding it is another story." The dolt confuses you -- more -- | - Any consultant ------------------------------------+-------------------------------
tim@hoptoad.uucp (Tim Maroney) (05/12/89)
Maybe I'm being dense, but what is the advantage to keeping an offscreen bitmap in a terminal emulator and using it for updates? Individual updates will go faster. However, you will spend more time overall in QuickDraw, because what would ordinarily be a one-step process has a new step added. The alternative to using an offscreen bitmap is to draw the characters directly into the window. This takes a time we'll call Td. The time Td is going to be about the same whether you're drawing to the screen or to an offscreen bitmap. However, when drawing offscreen, you need another step, a CopyBits to the screen, which takes time Tc. So the overall drawing time using the offscreen bitmap approach is Td+Tc, while drawing directly to the window is Td only. If a dialog box or something comes up in front of your window, then goes away, then the offscreen bitmap approach will lead to a faster update of the covered region, because Tc < Td. However, this seems to be the only case where you'd get a speedup. (And related cases like going to the back in MultiFinder then coming back to the front.) Most of the time in a terminal emulator in real life, you're likely to be writing to the front window. And I haven't even mentioned that the 20K or so for the offscreen bitmap is likely to impose a speed hit on your software because there's less free space in the heap.... -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Prisons are built with stones of Law, Brothels with bricks of Religion." - Blake, "The Marriage of Heaven and Hell"
jmunkki@kampi.hut.fi (Juri Munkki) (05/12/89)
In article <7254@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >Maybe I'm being dense, but what is the advantage to keeping an >offscreen bitmap in a terminal emulator and using it for updates? >Individual updates will go faster. However, you will spend more time >overall in QuickDraw, because what would ordinarily be a one-step >process has a new step added. I used to think this way too. Then I started working on a new terminal emulator and I wanted this one to have really easy updates. The surprising thing is that most users think that the program is better than others because it is faster than any other program they have used...and my program uses an offscreen bitmap. Using the bitmap doesn't seem to matter too much. I keep the bitmap always long-word aligned so that copybits can just blast the bits from the buffer to the screen without shifting them. DrawText always has to do this anyway, so calling DrawText takes much more time than the CopyBits for the same area. I had a very good reason why using the offscreen bitmap might be even faster than drawing directly (in some special cases), but I can't remember it right now. I'll post the reasoning, if I remember it again. Summary: In theory it might be slow, but in practise it doesn't seem to matter. _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
sam@neoucom.UUCP (Scott A. Mason) (05/12/89)
In article <7254@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: > >The alternative to using an offscreen bitmap is to draw the characters >directly into the window... > I am already using the DrawChar to draw the character directly into the window, and that works fine. >If a dialog box or something comes up in front of your window, then >goes away, then the offscreen bitmap approach will lead to a faster >update of the covered region... This is exactly my problem. How does one update the screen if it has not been stored in an offscreen bitmap?? -- -------------------------------------------------------------------------------- "If it ain't broke, don't fix it," and certainly don't blame me. UUCP: {pitt, scooter, hal, cwjcc}!neoucom!sam INTERNET: sam@neoucom.UUCP Scott A. Mason, Coordinator of Systems Operations, NEOUCOM
kk@mcnc.org (Krzysztof Kozminski) (05/12/89)
In article <21931@santra.UUCP> jmunkki@kampi.hut.fi (Juri Munkki) writes: >In article <7254@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >>Maybe I'm being dense, but what is the advantage to keeping an >>offscreen bitmap in a terminal emulator and using it for updates? > >I had a very good reason why using the offscreen bitmap might be even faster >than drawing directly (in some special cases), but I can't remember it right >now. I'll post the reasoning, if I remember it again. How about this: sometimes the visible and/or clipping regions on the screen are not rectangular => drawing to the screen is slower than drawing to an offscreen *rectangular* PixMap due to the extra effort necessary for the proper clipping of each object drawn. KK
lippin@ronzoni.berkeley.edu (The Apathist) (05/13/89)
Recently tim@hoptoad.UUCP (Tim Maroney) wrote: >Maybe I'm being dense, but what is the advantage to keeping an >offscreen bitmap in a terminal emulator and using it for updates? >Individual updates will go faster. However, you will spend more time >overall in QuickDraw, because what would ordinarily be a one-step >process has a new step added. It's a matter of trading time (and memory) now for time later. Since the amount of time spent in CopyBits is generally small, this is often a good trade, particularly if the drawing is complex. But, in a terminal program, the time to draw is also small, so I imagine there would be little advantage. A further advantage of CopyBits is that it avoids the flicker of doing erase and redraw on the screen. But for text, this is more simply avoided by using srcCopy mode. --Tom Lippincott lippin@math.berkeley.edu "Ask a fish head anything you want to -- It won't answer you; they can't talk."
tim@hoptoad.uucp (Tim Maroney) (05/14/89)
In article <1203@speedy.mcnc.org> kk@mcnc.org.UUCP (Krzysztof Kozminski) writes: >How about this: sometimes the visible and/or clipping regions on the >screen are not rectangular => drawing to the screen is slower than >drawing to an offscreen *rectangular* PixMap due to the extra effort >necessary for the proper clipping of each object drawn. I'm pretty sure the opposite is true. If part of your window is covered, then the reduced Font Manager overhead from not drawing the clipped-out characters makes drawing much faster. Clipping resolution seems to be more than fast enough to make this a win. I have observed this empirically with TOPS Terminal. However, with an offscreen bitmap, every character must be drawn. -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "The government of the United States is not, in any sense, founded on the Christian religion." -- George Washington
jmunkki@kampi.hut.fi (Juri Munkki) (05/14/89)
In article <7287@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >In article <1203@speedy.mcnc.org> kk@mcnc.org.UUCP (Krzysztof Kozminski) writes: >>How about this: sometimes the visible and/or clipping regions on the >>screen are not rectangular => drawing to the screen is slower than >>drawing to an offscreen *rectangular* PixMap due to the extra effort >>necessary for the proper clipping of each object drawn. > >I'm pretty sure the opposite is true. If part of your window is >covered, then the reduced Font Manager overhead from not drawing the >clipped-out characters makes drawing much faster. Clipping resolution >seems to be more than fast enough to make this a win. I have observed >this empirically with TOPS Terminal. However, with an offscreen >bitmap, every character must be drawn. According to IM-I the whole string is drawn into an offscreen buffer and only clipped after that. A complex clipping region will slow down the copybits from this buffer to the screen. I still think you don't loose any significant time. (Especially if you keep the screen and your own offscreen bitmap aligned.) From IM-I 172: [ Warning: QuickDraw temporarily stores on the stack all of the text you ask it to draw, even if the text will be clipped. When drawing large font sizes or complex style variations, it's best to draw only what will be visible on the screen. You can determine how many characters will actually fit on the screen by calling the StringWidth function before calling DrawString. ] None of this will be relevant if you use DrawChar for every character you draw. (Why this is not a good idea was discussed a few months ago.) It's somewhat easier to implement scrolling (or insert/delete) functions if you keep an offscreen bitmap. Imagine that you have the calculator DA in front of your terminal window. You update region after the operation will most probably not be a rectangle. To update, you have to call DrawString several times. QuickDraw will have to regenerate the mask from the region every time you call DrawText. It only has to generate the mask once, when you call copybits. For operation as the front window, you probably have a small speed advantage if you don't use the offscreen bitmap. My reason for using the offscreen bitmap was that updating the screen was a lot faster & easier. Now that the VT100 is ready, I find that it wouldn't take too much work to remove the offscreen bitmap. I might have to do this, if I start writing YATI (Yet Another Telnet Implementation). Right now (with only one offscreen buffer) I don't think it's worth changing the program. Even with the bitmap, I can run the program in a 160KB multifinder partition. _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
alain@atr-la.atr.junet (Alain de Cheveigne) (05/14/89)
Recently tim@hoptoad.UUCP (Tim Maroney) wrote: >Maybe I'm being dense, but what is the advantage to keeping an >offscreen bitmap in a terminal emulator and using it for updates? >Individual updates will go faster. However, you will spend more time >overall in QuickDraw, because what would ordinarily be a one-step >process has a new step added. There is one advantage in using an offscreen bitmap that has nothing to do with speed. Suppose you want your terminal emulator to print and scroll when it isn't frontmost. For example it's in the background, or you brought up a DA. Suppose the front window leaves an unmasked space at the top of the emulator window. If you just print to the window and scroll, then this portion will remain blank: text will appear to "slide under" the masking window, but won't come out at the top. However, if you print both to the screen and to an offscreen bitmap, and copy the bitmap back to the window at each newline, then the emulator will appear to scroll ok. Of course it's a bit slow on a Mac+. For speed you want to clip the CopyBits to the part that "slid out" from under the masker(s). You might also make special cases for when the drawing point is completely masked (draw only to the offscreen bitmap) or completely visible (draw only to the screen, and transfer each line to the offscreen buffer at newlines and each time something is about to mask it). I tried to send a mail to tim@hoptoad.UUCP, but the mailer doesn't know of domain UUCP. Alain de Cheveigne, alain@atr-la.atr.junet
tim@hoptoad.uucp (Tim Maroney) (05/17/89)
In article <7254@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >If a dialog box or something comes up in front of your window, then >goes away, then the offscreen bitmap approach will lead to a faster >update of the covered region... In article <1625@neoucom.UUCP> sam@neoucom.UUCP (Scott A. Mason) writes: >This is exactly my problem. How does one update the screen if it has not >been stored in an offscreen bitmap?? Store the characters in an array or a linked list or some cognate structure. When you get an update, determine which lines need to be redrawn, then call DrawText on each line after moving to the appropriate place on the screen. Sorry that I didn't understand your problem earlier or I'd have said this right away. -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Conversion, fastidious Goddess, loves blood better than brick, and feasts most subtly on the human will." - Virginia Woolf, "Mrs. Dalloway"
tim@hoptoad.uucp (Tim Maroney) (05/17/89)
In article <21965@santra.UUCP> jmunkki@kampi.hut.fi (Juri Munkki) writes: >According to IM-I the whole string is drawn into an offscreen buffer >and only clipped after that. A complex clipping region will slow >down the copybits from this buffer to the screen. I still think you >don't loose any significant time. (Especially if you keep the screen >and your own offscreen bitmap aligned.) Is this still true in the Mac Plus and later ROMs? I doubt it. Like I said, I've seen that the contrary is true. If I have a terminal window open in TOPS Terminal and another window overlaps it, covering from some point right of the left margin all the way to the right margin, the lines go by significantly faster. Remember that one of the things they did in the Mac Plus ROMs was to speed up most QuickDraw operations. >It's somewhat easier to implement scrolling (or insert/delete) functions >if you keep an offscreen bitmap. Imagine that you have the calculator DA >in front of your terminal window. You update region after the operation >will most probably not be a rectangle. To update, you have to call DrawString >several times. QuickDraw will have to regenerate the mask from the region >every time you call DrawText. It only has to generate the mask once, when >you call copybits. Yes, I already said that this kind of update would be faster using an offscreen bitmap, and this may create an illusion of overall better speed to a naive user. That may be good enough, but for me, I prefer to work with the actual speed. And I still believe that overall, using an offscreen bitmap will be slower for every other operation. -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Americans will buy anything, as long as it doesn't cross the thin line between cute and demonic." -- Ian Shoales