Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Advanced Color Imaging on the Mac OS /
Chapter 1 - Palette Manager / Using the Palette Manager


Using Palettes With Offscreen Graphics Worlds

You can attach a palette to an offscreen graphics world; however, the only Palette Manager color usage categories that you can use to specify the types of colors in such a case are pmCourteous and pmBlack and pmWhite. The other three color usage categories, pmTolerant, pmAnimated, and pmExplicit, are interpreted in an offscreen graphics world as pmCourteous, so they are of no use in this environment.

This section first explains why and how you might use pmCourteous, pmBlack, and pmWhite and then shows how to simulate the effects of the other usage modifiers that you cannot use with an offscreen graphics world.

After you've created a palette and assigned it to an offscreen graphics world, you can pass indexes from your palette to the PmForeColor and PmBackColor functions and then draw in the offscreen world. The advantage of using courteous colors for the offscreen graphics world is that otherwise you must hard-code colors into your code. If you or a software localizer wants to change the colors in the offscreen worlds, you can do so by changing the 'pltt' resource that defines the palette rather than making code changes and recompiling the application.

The pmBlack and pmWhite usage modifiers simply allow you to specify which colors map to white and which to black in a black-and-white environment. If your application is working with red and dark blue, for example, both might get mapped to black on a 1-bit device. By assigning pmWhite to one and pmBlack to the other, you assure that they are always distinct.

Explicit colors in a palette attached to an offscreen graphics world are interpreted as courteous. Therefore, instead of using a palette, you should convert your pixel value to an RGB color and use this as the foreground or background color. After setting the current graphics device to the offscreen graphics world to set the color environment, convert your pixel value to the corresponding RGB color using the IndexToColor function. Then you can draw by passing the RGB color to the RGBForeColor and RGBBackColor functions.

Both tolerant and animated colors are interpreted as courteous in an offscreen graphics world. To use these types of colors, you can change the color environment of the offscreen graphics world by assigning it a whole new color table. Listing 1-6 shows how to do this.

Listing 1-6 Changing the color environment of an offscreen graphics world

   #define  clutID   150
   #define  numcolor 256

   WindowPtr   myWindow;
   CTabHandle  mycolors;
   PaletteHandlesrcPalette

   GetGWorld (&SavePort, &SaveGD);
   mycolors = GetCTable (clutID);
   /* create a new window */
   myWindow = NewCWindow(nil, &BaseRect, "", TRUE, zoomDocProc, 
                     (WindowPtr) -1, TRUE, nil);
   SetGWorld((CGrafPtr)myWindow, SaveGD);
   DrawGrowIcon (myWindow);

   (*mycolors)->ctFlags |= 0x4000;

   /* create a 256-color palette */
   srcPalette = NewPalette (numcolor, mycolors, pmCourteous, 0);
   /* call DoSetInhibited to set color usage */
   DoSetInhibited(pmCourteous);
   SetPalette ((WindowPtr) myWindow, srcPalette, TRUE);
   
   GetGWorld (&SavePort, &SaveGD);
   err = NewGWorld (&offscreenGWorld, 8, &InitWindowSize, 
                mycolors, nil, nil);
   if (err)
      Debugger();
   SetGWorld (offscreenGWorld, nil);
   EraseRect (&InitWindowSize);
   DrawPicture (ThePict, &InitWindowSize);
   SetGWorld (SavePort, SaveGD);

After defining constants and declaring variables, the code in Listing 1-6 calls the QuickDraw GetGWorld function to get and save the current graphics port so that you can restore it later. The GetCTable function retrieves a handle to a color table--from a 'clut' resource with ID 150--and stores it in the mycolors variable. You will use this color table for the offscreen graphics world and to create a palette.

The NewCWindow function creates a new window and the SetGWorld function assigns the current graphics port to this newly created window. The DrawGrowIcon function draws the window's size box.

The next piece of code:

   (*mycolors)->ctFlags |= 0x4000;
sets bit 14 of the ctFlags field in the color table. Setting this bit synchronizes the color table to a palette. It does this by reinterpreting the ctTable field of the color table. Normally, this field contains an array of ColorSpec entries, each of which contains a pixel value and a color. After setting bit 14 of the ctFlags field, each array in the ctTable field contains an index value and a color.

The NewPalette function creates a new palette from the color table retrieved by the GetCTable function. It contains 256 colors. Initially, all the colors are courteous and must match exactly (have a zero tolerance value).

The DoSetInhibited function (whose code is not shown here) uses the Palette Manager SetEntryUsage function to change the usage categories of the palette when the usage of the palette changes. For example, it sets the colors in the palette to courteous, tolerant, explicit, or animated, depending on menu selections that a user makes. The DoSetInhibited function also inhibits certain colors in the palette depending on the bit-depth of the screen on which the window is currently displayed. In this way, the palette can contain entries for multiple screen bit-depths and will display properly on each type of screen. See "Selecting the Right Color Set" (page 1-25) for an example of how to create a palette that will display on screens with different bit-depths. The application calls DoSetInhibited at this point to set the palette for the appropriate screen depth. Since pmCourteous is passed to DoSetInhibited, the usage category is not being changed.

The SetPalette function assigns the newly created palette to the window created by NewCWindow. The GetGWorld function gets and saves the current graphics port so it can be restored later. The NewGWorld function creates an offscreen graphics world and the SetGWorld function sets the current graphics port to the newly created offscreen graphics world.

The EraseRect and DrawPicture functions erase and draw in the offscreen graphics world.

The final SetGWorld function restores the graphics port to the window created by the NewCWindow function. (To move the offscreen drawing to the screen, use the QuickDraw CopyBits function--see the chapter, "QuickDraw Drawing," in Inside Macintosh: Imaging With QuickDraw for an example of how to do this.) The colors from the offscreen world--which come from the color table--match the colors of the window--which are controlled by the palette--because the color table and the palette are identical and synchronized. The advantage of this synchronization is that your application doesn't have to use the offscreen world's color matching algorithm to synchronize the colors from the offscreen world with the colors of the palette. Having to do so would greatly slow down your application, and speed is one of the primary reasons to use an offscreen world for drawing in the first place.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
13 NOV 1996