[comp.sys.mac.programmer] Quickdraw efficiency question

sam@neoucom.UUCP (Scott A. Mason) (07/11/89)

Question:

Which would be faster when drawing multiple characters to a window?

  1) repeated calls to DrawChar
  2) building a string and calling DrawString.

Intuitively, I would think that DrawString would be faster, but then again,
doesn't DrawString make repeated calls to DrawChar?  BTW, I want to do this
for a terminal emulation program, and want maximum screen drawing speed.

While I'm at it, how does Mackermit achieve such speedy screen drawing??

Thanks for the info.
-- 
--------------------------------------------------------------------------------
"If it ain't broke, don't fix it," and certainly don't blame me.
UUCP:  {pitt,scooter,hal,cwjcc,aablue}!neoucom!sam   INTERNET:  sam@neoucom.UUCP
Scott A. Mason, Coordinator of Systems Operations, NEOUCOM

tim@hoptoad.uucp (Tim Maroney) (07/11/89)

In article <1681@neoucom.UUCP> sam@neoucom.UUCP (Scott A. Mason) writes:
>Question:
>
>Which would be faster when drawing multiple characters to a window?
>
>  1) repeated calls to DrawChar
>  2) building a string and calling DrawString.

DrawString.  Smaller trap overhead, fewer internal calls to the Font
Manager, some built-in heuristics to speed things up.  DrawText is
even better,m supposedly.

>While I'm at it, how does Mackermit achieve such speedy screen drawing??

I don't know for sure, but a lot of terminal emulators use a
reprehensible technique sometimes called "bit-blasting".  This involves
bypassing both Quickdraw and the Font manager and copying the bits of
characters directly into the screen.  It *is* fast, but there are
serious portability problems.  Drawing straight into the screen bitmap
is a major no-no these days, and of course when fonts change in System
7.0, there is a good chance many of these programs will break.  You
also have to figure your own clipping and visible regions usage, no
easy task to do correctly.  The early generation of bit-blasters were
mostly incompatible with MultiFinder, and the new generation will
probably be incopmpatible with some add-on screens and with System
7.0.  Caveat implementor, in Kari Dubbelman's clever phrase....
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com
Postal: 424 Tehama, SF CA 94103; Phone: (415) 495-2934

"When errors are found in old research, the relevant theories are
 re-examined.  When facts contradict theory, theory gets dumped.  Is
 that why the NLP people are unwilling to research their facts?"
	-- Jerry Hollombe on sci.psychology

earleh@eleazar.dartmouth.edu (Earle R. Horton) (07/11/89)

In article <1681@neoucom.UUCP> sam@neoucom.UUCP (Scott A. Mason) writes:
>Question:
>
>Which would be faster when drawing multiple characters to a window?
...
>Intuitively, I would think that DrawString would be faster, but then again,
>doesn't DrawString make repeated calls to DrawChar?  BTW, I want to do this
>for a terminal emulation program, and want maximum screen drawing speed.

     StdText works for me.  DrawString, DrawChar, and DrawText all
call StdText, so if you call StdText directly, then you save a layer
of procedure calls.  You could also make the grafProcs field of your
GrafPort point to a QDProcs record, call SetStdProcs on it, and then
call the textProc directly.  I think the big savings occurs when you
call either StdText or DrawText, and thereby draw text a line at a
time, rather than a character at a time.

>While I'm at it, how does Mackermit achieve such speedy screen drawing??

     MacKermit calls DrawText.  It owes a lot of its speed to
buffering, however.  Choice of buffering algorithm can make or break a
terminal emulator, speed-wise.

Earle R. Horton

"People forget how fast you did a job, but they remember how well you
did it."  Salada Tag Lines

jmunkki@kampi.hut.fi (Juri Munkki) (07/11/89)

In article <1681@neoucom.UUCP> sam@neoucom.UUCP (Scott A. Mason) writes:
>Question:
>
>Which would be faster when drawing multiple characters to a window?
>
>  1) repeated calls to DrawChar
>  2) building a string and calling DrawString.
>
>Intuitively, I would think that DrawString would be faster, but then again,
>doesn't DrawString make repeated calls to DrawChar?  BTW, I want to do this
>for a terminal emulation program, and want maximum screen drawing speed.

The answer is that calling DrawString is several times faster than calling
DrawChar (six times faster when I tested this on a Mac+). There are several
reasons for this. For every call to a text drawing routine, QuickDraw and
the Font Manager will have to figure out where the font is (maybe even call
the resource manager to read the font from a file).

Finally, when the font is ready, QuickDraw starts drawing the actual text.
The text is drawn one scan-line at a time. In addition to drawing the
characters, the clipping regions have to be accumulated. When you call
DrawChar, the regions are created for every character. When you call
DrawText or DrawString, the regions are interpreted only once.

Disclaimer: This article is based on educated guesses. I might be wrong.

Maybe you should get the communications manager from Apple. They should
know how to write a fast terminal. This would save you the trouble of
writing YATE (Yet Another Terminal Emulator).

A good VT100 emulator takes about 20 pages of C source code. Add another
10-15 pages for a scrollback buffer and copy/paste support. Add another
10 pages for a decent user interface with file save and maybe a dialog
to change the terminal settings. (The pages are in Courier-7 and about
25% of the lines are comments.)

_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
|     Juri Munkki jmunkki@hut.fi  jmunkki@fingate.bitnet        I Want   Ne   |
|     Helsinki University of Technology Computing Centre        My Own   XT   |
^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^

amanda@intercon.uu.net (Amanda Walker) (07/12/89)

In article <1681@neoucom.UUCP>, sam@neoucom.UUCP (Scott A. Mason) writes:
> Intuitively, I would think that DrawString would be faster, but then again,
> doesn't DrawString make repeated calls to DrawChar?  BTW, I want to do this
> for a terminal emulation program, and want maximum screen drawing speed.
> 
> While I'm at it, how does Mackermit achieve such speedy screen drawing??

Building a string and drawing it with DrawString (or DrawText) is *much*
faster.  This is what MacKermit does.  This is one case where your initial
intuition about which would be faster is wrong.  As it turns out, DrawChar
is done by drawing a string of 1 character...

One of the reasons for the speedup is that the font information is retrieved
once per string, so the fewer times this is done, the faster the text shows
up.

--
Amanda Walker
InterCon Systems Corporation
--
amanda@intercon.uu.net  |  ...!uunet!intercon!amanda

wdh@well.UUCP (Bill Hofmann) (07/13/89)

In article <7943@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>In article <1681@neoucom.UUCP> sam@neoucom.UUCP (Scott A. Mason) writes:
>>Question:
>>Which would be faster when drawing multiple characters to a window?
>>  1) repeated calls to DrawChar
>>  2) building a string and calling DrawString.
>DrawString.  Smaller trap overhead, fewer internal calls to the Font
>Manager, some built-in heuristics to speed things up.  DrawText is
>even better,m supposedly.
Only by a few instructions for each call, since what DrawString does
is pop the length byte and jump to the DrawText code.  If efficiency is
the object here, DrawText (or DrawString) is a very good candidate for
doing a GetTrapAddress at the beginning of your application and doing
a direct jump to it. I've clocked ~10% speed improvement in my app's
redraw just from this optimization.

-Bill

maxie@apple.com (Keith G. Nemitz) (07/13/89)

Another method for drawing characters to the screen (and quite legal) is 
to predraw the
the characterset into an offscreen buffer and use copybits to blast their 
images to screen.
This is what Red Ryder does. It is very fast because in the long run 
DrawString and DrawChar
both call copybits eventually. If your character set is a mono-spaced font 
you can use the
byte itself as an index into the offscreen bitmap.

keith

My hardware on Apple hardware, software flowing.

A9F4

tim@hoptoad.uucp (Tim Maroney) (07/14/89)

In article <7943@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>DrawString.  Smaller trap overhead, fewer internal calls to the Font
>Manager, some built-in heuristics to speed things up.  DrawText is
>even better, supposedly.

In article <12676@well.UUCP> wdh@well.UUCP (Bill Hofmann) writes:
>Only by a few instructions for each call, since what DrawString does
>is pop the length byte and jump to the DrawText code.

Interesting.  I disassembled DrawText and found that it's only about
a dozen instructions that check to see if there's a bottleneck, call
it if so, and otherwise get the address of StdText from a low memory
global and call it.  There really didn't seem to be enough code to
produce a significant performance difference from DrawText by using
StdText.  On the other hand, a source at Apple says that StdText is
the only waot handle double-height or half-height text, which is
required for a complete vt100 emulation.

>If efficiency is
>the object here, DrawText (or DrawString) is a very good candidate for
>doing a GetTrapAddress at the beginning of your application and doing
>a direct jump to it. I've clocked ~10% speed improvement in my app's
>redraw just from this optimization.

Very interesting, but this seems a little unclean to me.  I believe
there was a tech note or something which said people should stop using
this technique.  Probably a better approach is to do a SetStdProcs on
your grafport and then call through the address there.  This should
accomplish much the same thing and get you the same trap dispatch
savings, while retaining compatibility with future systems.  Thanks
for the tip.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"Every institution I've ever been associated with has tried to screw me."
	-- Stephen Wolfram

cep@apple.com (Christopher Pettus) (07/14/89)

In article <7988@hoptoad.uucp> tim@hoptoad.uucp (Tim Maroney) writes:
> On the other hand, a source at Apple says that StdText is
> the only waot handle double-height or half-height text, which is
> required for a complete vt100 emulation.

It's not really that esoteric.  StdText gives you access to the 'numer' 
and 'demon' parameters which are used to stretch and compress text.  I 
presume this is the mechanism that's used for the compressed and expanded 
styles, as well as replaying text in pictures where the destination 
rectangle differs in its dimensions from the original rectangle.  It's a 
very handy feature; I wish more applications took advantage of it.  Ref. 
IM I 198-199.

-- Christopher Pettus                   | "Ganesha Said: 'Done!  The very 
   Network Systems Development          | day I was born I made my first
   Apple Computer, Inc.                 | mistake, and by that path have
   cep@apple.com   {nsc, sun}!apple!cep | I sought wisdom ever since.'"
   AppleLink: PETTUS.C                  | - The Mahabharata
   (408) 974-0004                       |   I: A Mine of Jewels and Gems

jmunkki@kampi.hut.fi (Juri Munkki) (07/22/89)

In article <2803@internal.Apple.COM> maxie@apple.com (Keith G. Nemitz) writes:
>Another method for drawing characters to the screen (and quite legal)
>is to predraw the the characterset into an offscreen buffer and use
>copybits to blast their images to screen.  This is what Red Ryder
>does.

Yuk. I have never (ever) heard anyone calling Red Ryder fast. To make this
method really effective would require you to keep your whole terminal screen
in an offscreen bitmap.

>It is very fast because in the long run DrawString and DrawChar both
>call copybits eventually. If your character set is a mono-spaced font
>you can use the byte itself as an index into the offscreen bitmap.

I think DrawString & DrawChar never call CopyBits. They might call something
similar, but I think they do something much smarter. It is faster to process
a font a single scanline at a time. I would guess that QD draws a single
scanline into offscreen RAM and then blasts it onto the screen. It can then
forget that line even exists in the font bitmap and move onto the next one.
This saves you some indexing/registers when compared to the approach where
you write a character and then forget about it when you move onto the next.

P.S.	I would appreciate it if people would append informative signatures.
	A lot of people at apple.com are actually not working for Apple and
	even might not have any experience in programming Macs.

_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
|     Juri Munkki jmunkki@hut.fi  jmunkki@fingate.bitnet        I Want   Ne   |
|     Helsinki University of Technology Computing Centre        My Own   XT   |
^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^

amanda@intercon.uu.net (Amanda Walker) (07/25/89)

In article <2803@internal.Apple.COM>, maxie@apple.com (Keith G. Nemitz) writes:
> Another method for drawing characters to the screen (and quite legal) is 
> to predraw the
> the characterset into an offscreen buffer and use copybits to blast their 
> images to screen.

I tried this once.  I timed it, and on anything below a II, DrawText (or
actually, StdText...) was *faster* than CopyBitsing each character.  The
only way I got any faster was to stuff things into screenBits, which is
a major no-no.  Even so, on a full screen of text on a Plus, I was a whole
half a clock tick faster.  I decided it wasn't worth it...

For terminal emulators, anyway, you get much bigger wins by working on
the emulator and serial port  buffering code.  I suspect that one reason
that people like to claim that using the ROM to draw character is "too slow"
is so that they can claim that their program's lack of performance is
someone else's fault...

--
Amanda Walker
InterCon Systems Corporation
--
amanda@intercon.uu.net   |   ...!uunet!intercon!amanda

tim@hoptoad.uucp (Tim Maroney) (07/25/89)

In article <1304@intercon.UUCP> amanda@intercon.uu.net (Amanda Walker) writes:
>For terminal emulators, anyway, you get much bigger wins by working on
>the emulator and serial port  buffering code.  I suspect that one reason
>that people like to claim that using the ROM to draw character is "too slow"
>is so that they can claim that their program's lack of performance is
>someone else's fault...

Not me!  In my case, it was the Memory Manager that was too slow!  :-)
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"The above opinions and suggestions have absolutely nothing to do with
 the little, fat man putting crisp, $100 bills in my pocket."
    -- Alan Vymetalik