December 93 - GRAPHICAL TRUFFLES
REMEDIES FOR COMMON QUICKDRAW PROBLEMS
During the past two years alone, the Developer Support Center has answered more than 1000
QuickDraw-related questions. The answers to most of these questions are now available in Apple's
plentiful "one-to-many" sources of support for developers, includingInside Macintosh , Technical
Notes, Q&As, sample code, and of coursedevelop. But you might
find it helpful to look here first if you're having a QuickDraw problem. The symptoms of some
common problems are listed in this column along with Dr. John's suggested remedies.
These are the symptoms that we'll suggest remedies for:
- CopyBits is too slow.
- You have a palette created with a tolerance of 0, but the colors in your graphics port don't match
- You're using palettes stored in 'pltt' resources and they don't seem to have any effect.
- Strange colors get drawn when you do a CopyBits between different graphics ports.
- The pen pattern isn't being used when PaintRect is called with hilite penmode.
- NewGWorld doesn't return an error and the GWorldPtr it returns is unchanged.
- QuickDraw routines aren't working on your GWorld.
- Your complement procedure isn't being called for InvertRect.
CopyBits is too slow.
Remedy: There's little doubt that CopyBits is a complex piece of code, so there aremany factors that
can affect its execution speed. In fact, there's a long Technical Note dedicated to this topic, called
"Of Time and Space and _CopyBits" (QuickDraw 21). But here are a couple of quick hints for
possible ways to speed up CopyBits:
- If your source and destination graphics ports have matching color tables, set the ctSeed field in the
color tables of the source and destination to be the same. This removes the overhead of comparing
the entries in the color tables to determine whether color mapping is necessary.
- Use GWorlds when copying the entire off-screen buffer to the screen. GWorlds will properly
align your pixel data so that CopyBits calls don't require byte and bit shifting. (You must create
the GWorld with a depth of 0 and pass the rectangle in global coordinates.)
You have a palette created with a tolerance of 0, but the colors in your graphics port don't match the
Remedy: The colors in the graphics port may appear to be different, but remember that only the high
eight bits of an RGB color component are important. The lower eight bits aren't significant because
they're ignored by the hardware. Consequently, for optimization and implementation reasons,
NewPalette creates a palette of colors by copying the high byte of each color in the input color table
to both the high byte and the low byte of the palette. For example, if the color table has the color
($ff00, $75fe, $0080), the equivalent palette entry would be ($ffff, $7575, $0000).
You're using palettes stored in 'pltt' resources and they don't seem to have any effect.
You're having this problem because GetNewPalette doesn't work as documented inInside
MacintoshVolume VI. The description of this routine in Volume VI states that a palette will be
loaded and attached to the current window, and if the palette requested isn't available, the default
application palette is used instead. The actual implementation of GetNewPalette is much simpler: it
only loads the specified 'pltt' resource with GetResource and detaches it with DetachResource to
make it a handle; if the specified 'pltt' resource isn't found, GetNewPalette doesn't load the default
Strange colors get drawn when you do a CopyBits between different graphics ports. Remedy:More than likely,
your graphics port and device are incorrectly set. The current port and
device must always be set to the destination port and device. So if you're copying from a window to
an off-screen GWorld, you must call SetGWorld to set the GWorld as the current port and device.
When you do a CopyBits from a GWorld to a window, you must set the port to the window and the
graphics device to the MainGDevice. This rule actually applies to all QuickDraw drawing.
The pen pattern isn't being used when PaintRect is called with hilite penmode.
A bug in QuickDraw causes the pen pattern to be ignored when used with hilite penmode in
the following calls:
- FrameRect, PaintRect, and FillRect
- LineTo (vertical and horizontal lines only)
- FrameRgn, PaintRgn, and FillRgn (rectangular regions only)
- FramePoly, PaintPoly, and FillPoly (rectangular polygons only)
A simple workaround for PaintRect is to call PaintRoundRect instead; that is, call
PaintRoundRect(&myRect, 0, 0);
NewGWorld doesn't return an error and the GWorldPtr it returns is unchanged.
The cause of this problem is typically memory movement. Many object-oriented languages,
such as MacApp, store data in handles. If the GWorldPtr pointer variable you pass to NewGWorld is
stored in a relocatable block of memory, and if that block moves during execution of NewGWorld,
NewGWorld will store the GWorldPtr in the old dereferenced storage location. Instead, pass a local
GWorldPtr to NewGWorld and copy the local GWorldPtr to the relocatable memory block
QuickDraw routines aren't working on your
Remedy: Although some routines in QuickDraw will work when LockPixels isn't called, most routines
will have unexpected results. Always call LockPixels if you want to access or draw into your GWorld.
To prevent memory fragmentation, the GWorld image should be unlocked when you're not
accessing the pixel data so that it can move in memory.
Your complement procedure isn't being called for InvertRect.
Remedy: Complement procedures are called from InvertColor only. All other Invert calls simply
invert bits, as in QuickDraw's original design.
NEED A REAL DOCTOR?
The next time a QuickDraw problem is giving you a headache, look here first for help. Dr. John's list
of remedies may provide just what you need to solve your problem. If you don't find a solution here,
check as usual in Inside Macintosh and the many other available sources of help.
JOHN WANG (AppleLink WANG.JY) of Apple's Developer Support Center has a new addition to his family, named
Pepper. The four-month-old baby girl weighs in at a healthy nine pounds. She has big brown eyes, baby teeth, and a
generous amount of hair. She sleeps all day and makes almost no noise at night. And she's nearly toilet trained already!
Pepper even gets along well with her older brother Skate; they like to nibble playfully on each other's ears. But when it
comes to food, they're fearless; they fight, kick, and howl -- all for just a bone. *
Thanks to Don Moccia and Brigham Stevens for reviewing this column.*