March 94 - MACINTOSH Q & A
MACINTOSH Q & A
MACINTOSH DEVELOPER TECHNICAL SUPPORT
Q In QuickDraw GX, if the QuickDraw clipping region of a window (set by
SetClip(aRgn)) is not rectangular, the shapes drawn to the window's viewPort are
sometimes clipped incorrectly. Is this a bug?
A This is not a bug. QuickDraw GX doesn't honor any of the QuickDraw clipping regions
except the one that's connected to a viewPort, created by calling the
GXNewWindowViewPort routine.
Here's why: So that QuickDraw GX can draw into viewPorts associated with windows,
it patches the Window Manager. When the user moves a window, or when your
application calls BeginUpdate and EndUpdate, QuickDraw GX updates the viewPort
caches and clip shape. The clip shape is set to the visRgn of the window. However, all
other QuickDraw regions are ignored.
If you want to do some smart window clipping, you can. But you can't play directly
with the viewPort attached to the window: that viewPort is maintained by the
QuickDraw GX system and is therefore off limits to the application. (If you do try to
manipulate it, you'll receive an error.) You need to attach a child viewPort to the
window's viewPort; then you can convert the QuickDraw region you want to clip to into
a GX shape (with the GX Translator) and set the child viewPort's clip shape to this new
shape. Your QuickDraw GX shapes will then be clipped correctly.
Q Calling GXSetStyleRunControls on a layout shape with the "track" field set doesn't
always have any visible effect, although the track value is always safely stored in the
layout shape and can be retrieved with GXGetStyleRunControls. You can see this in
GXWrite by adjusting the track kerning of some Tekton text: that works fine. If you
switch to the Hoefler font, however, no track kerning is performed. Can you explain
this?
A When a track kerning value is specified, QuickDraw GX looks to the tables in the font
to see how the kerning should be performed. A narrow text face with a large x-height,
like Avant Garde, can probably take much tighter track kerning than something like
Hoefler Italic can; only the font designer really knows how the kerning should behave.
The font designer tells QuickDraw GX how to do track kerning by setting values in the
'trak' table of the font. This table contains one or more "reference points" -- values
between -2 and 2 -- each of which tells how much to adjust space between the glyphs
for any number of point sizes. If the specified track kerning value lies between
reference points, QuickDraw GX interpolates accordingly.
Hoefler Italic contains only one reference point -- "normal" kerning (value 0). It
does contain values for several different point sizes, but the font designer doesn't want
the face more tightly or loosely kerned than in his original design. Since there's only
one 'trak' point, QuickDraw GX winds up interpolating those entries with themselves
and nothing really happens for the values you specify in the run controls. As you've
noted, those values are still there, and they would be used if you switched those runs to
a different text face, but they're having exactly the effect Jonathan Hoefler wanted --
none at all.
Q We're developing a QuickDraw GX printer driver for a 24-bit continuous-tone
device. First, what should halftone fields be set to for a continuous-tone device (are
they ignored?). Second, do we have to override GXDefaultPrinter and GXDefaultJob?
The ImageWriter example shows building a default colorset inside GXDefaultPrinter.
A The answer to your first question is that you can stop QuickDraw GX from using the
halftone information by setting the gxDontSetHalftone flag in the plane flags field of
each plane in the 'rdip' resource. That's it -- the halftone fields will be ignored.
The messages GXDefaultPrinter, GXDefaultDesktopPrinter, GXDefaultJob,
GXDefaultPaperType, and GXDefaultFormat may be appropriate for your driver to
override in order to modify default objects. You don't need to override these messages
unless you have a reason to change the default object.
The ImageWriter driver with QuickDraw GX adds a list of view devices that are
appropriate for the printer that's being used. Specifically, it adds a 144-dpi
black-and-white view device and, if color is available, a 144-dpi color view device. If
the driver didn't add these, the default printer view device (24-bit at 72 dpi) would
be used. Overrides of a GXDefaultxxx message typically forward the message first to
obtain the default object, and then modify that object as needed. So if you want more
than one view device to be installed by your driver, you should override
GXDefaultPrinter. That's what the ImageWriter driver is doing.
Q What is the correct way to recognize PowerTalk letters? Is it by checking for the
file type 'lttr' or by looking at Finder flag bit 0x0200? Should I be saving letters as
type 'lttr' or as my own file type, and should I be setting the bit?
A The correct way of checking whether a particular document is a letter is to check the
isLetter bit of the Finder info field. It's bit 9, mask 0x0200, and occupies the space
formerly used by the "changed" bit.
Checking for file type 'lttr' doesn't work, since letters may have whatever file type
the sending application desires. In fact, an application may support multiple letter
types, and may have a different file type and icon for each type. This allows additional
flexibility, since an application may have some idea what content the letter contains by
checking its type, even before opening the letter.
Note that when your application saves a letter to disk, nothing special needs to be done
with either the Finder flags or the file type to ensure that the Finder notices that the
file created is a letter. SMPBeginSave and SMPEndSave will automatically set the
isLetter bit for you, and the Finder will realize from this bit that your file is indeed a
letter.
One final piece of information: Since letters may have a file type other than 'lttr', an
additional hook was added to the Finder drag and drop mechanism to allow applications
to have any letter drop-opened on them, regardless of the letter's file type. If you add a
BNDL/FREF pair with the type 'ltr*' to your application, the Finder will highlight
your icon whenever any letter is dragged over it. This mechanism works in the same
way that '****' does for the universal drag and drop wildcard.
Q Can we use a different A5 world with QuickTime? Our plug-in architecture uses A5
for global access, but we allow the A5 world to move. QuickTime doesn't seem to
appreciate this and doesn't think that EnterMovies has been called after the A5 world
moves. We currently work around this by locking down our A5 world but would rather
not. Is locking down the A5 world even good enough?
A You can use a different A5 world with QuickTime. QuickTime allocates a new set of
state variables for each A5 world that's active when EnterMovies is called. However,
since QuickTime uses A5 to identify each QuickTime client, if you move your plug-in's
A5 world QuickTime will no longer recognize that you've called EnterMovies for that
client. So you can use a different A5 world, but you'll have to lock it down.
Q We're trying to display a QuickTime movie in a frame that can be panned, cropped,
and overlaid by other objects. The movie controller doesn't seem to understand that the
badge may lie entirely outside the frame. Is there some way to tell the movie
controller where to place the badge?
A Unfortunately, QuickTime isn't flexible about this. The code that positions the badge
calculates it from the bounding box of the movie region, and insets it six pixels from
the left and bottom. There's no sane way to work around this, other than not to use the
standard badge, but instead use your own badge and perform your own badge tracking.
Q I've noticed some interesting behavior using the standard compression dialog and was
wondering if someone could explain it to me. I'm trying to provide session-wide
defaults for compressing sequences of images. If I don't prime the dialog by doing an
SCRequestSequenceSettings, then when I do an SCCompressSequenceBegin the dialog is
displayed. Is there any way to prevent this, and to use some set of defaults (without
using an image to derive the defaults)?
A The compression dialog components allow you to get settings with the SCGetInfo call,
and to set them with SCSetInfo. The first time, you should display the dialog with
SCRequestSequenceSettings, and then use SCGetInfo to retrieve the settings. After that,
you can apply the same parameters before starting a compression sequence by using
SCSetInfo. If you provide settings before calling SCCompressSequenceBegin, the dialog
won't be displayed; otherwise it will be. See Inside Macintosh: QuickTime Components,
page 3-8 and pages 3-15 through 3-25, for details about the format of the settings.
Also, as you may know, you can generate default parameters that also avoid the dialog
by using the SCDefaultPixMapSettings, SCDefaultPictHandleSettings, and
SCDefaultPictFileSettings routines. But these do require an image. This way you can
avoid displaying the dialog for the first sequence, and still generate valid settings. See
Inside Macintosh: QuickTime Components, pages 3-26 through 3-28, for more
information about these routines.
Q When a user pastes a movie into a movie-controller movie, the added movie is
inserted in the top left corner of the movie. Is there a way for the user to choose where
the movie is pasted, and if not, how can I give the movie controller or Movie Toolbox an
offset to use rather than have the editing operations use the top left corner?
A When you paste a movie into a movie-controller movie, the movie controller is
simply calling PasteMovieSelection to insert the source movie. All the characteristics
of the movie are inserted, and therefore the movie is inserted in the top left corner of
the movie. There's no easy way to specify an offset directly to the movie controller. If
you want to change the offset of the pasted movie, you'll have to modify the movie
yourself after the paste using Movie Toolbox commands. Once you're done changing the
movie, be sure to call MCMovieChanged so that the movie controller updates correctly.
The actual modification is simple: call GetTrackMatrix, add your offset to the matrix,
and call SetTrackMatrix. The difficulty is in determining which tracks to modify, since
the paste may either create a new track or use an existing one. We recommend doing
this by gathering all track indexes before the paste, and then comparing with the track
indexes after the paste. Since most movies these days have just a few tracks, this
shouldn't require much overhead. (But be warned: some movies do have a lot of
tracks!) To get the track information, you can call GetMovieTrackCount and