Development Zone Home Platform Advantages Business Relationship Getting Started Palm Solution Provider Program Development Resources Development Support Provider Pavilion Platinum Test Palm Computing Home
★ wanayoo — archive 1999 http://www.palm.com/devzone/docs/seeinggray.htmlNouvelle recherche | Portail wanayoo
Palm Computing(R) Development Zone3Com



Development Support

Seeing Gray

by Bob Ebert, Palm Engineering

Q: I heard a rumor that the Palm III had grayscale support. How do I use grayscale in PalmOS 3.0?

A: In general, you don't. Just like in 1.0 and 2.0, there isn't any official support for drawing in gray in the 3.0 release of the Palm OS.

Q: Okay, so officially I don't use grayscale. But how about if I really want to?

A: Just like in 1.0 and 2.0, you can hack. If you're going to do that, we have some advice.

First and foremost, you can and should use the one new supported grayscale routine, ScrDisplayMode, to query or set the current depth of the display before you do any hacking. You used to do this by setting the Dragonball registers yourself, and we'd really prefer it if you stopped that and used ScrDisplayMode instead. By doing this you avoid three potential problems: 1) switching to gray but assuming the device needs to be set to 1-bit mode for system UI, 2) writing to screen memory assuming that it's 1-bit deep, and 3) assuming the CPU in the device has a register layout like the Dragonball.

Here's how to make sure the screen is what you expect at app startup. The code is PalmOS 3.0 (and later) only, so you'll have to do something else for 1.0 and 2.0 releases.

PilotMain()
{
   if (normalLaunch)
      {
      DWord requiredDepth = 2;      // Apps needing B/W should use 1, grayscale apps use 2
      err = ScrDisplayMode(scrDisplayModeSet, NULL, NULL, &requiredDepth, NULL);
      if (err)
         {
         Alert("This app is not designed to work with this device's screen.")
         return err;
         }

      DoApp();

      err = ScrDisplayMode(scrDisplayModeSetToDefaults, NULL, NULL, NULL, NULL);
      }
}

At some point, we may have devices that run in other than 1-bit deep mode by default. On those machines, if you "reset" the device to 1-bit, you'll either annoy the user or crash the system. Also, if you write 1-bit data directly to screen memory, you'll either annoy the user or crash the system.

You can experiment with running the whole OS in 2-bit mode on Palm III devices (and in the Mac Simulator with the 3.0 SDK and PalmOS Emulator with 3.0 ROM), by using the following code to set the default depth to 2.

From PalmOS 3.0 SystemMgr.h:

#define   sysFtrNumDisplayDepth   7               // Display depth
         // Result is the "default" display depth for the screen.
         // This value is used by ScrDisplayMode when setting the default display depth.

In your app:
//-----------------------------------------------------------------------
// FUNCTION:   SetDefaultDepth
// DESCRIPTION:   Set the default depth for the system
// PARAMETERS:   New default depth, pass 1 or 2 for that depth.
//-----------------------------------------------------------------------
static Err SetDefaultDepth(DWord newDefaultDepth)
{
   Err err = FtrSet(sysFtrCreator, sysFtrNumDisplayDepth, newDefaultDepth);
   if (!err)
      err = ScrDisplayMode(scrDisplayModeSetToDefaults, NULL, NULL, NULL, NULL);
   return err ;
}


There isn't any supported API to draw to the screen in gray. You can do that by using the current hacks that write screen memory. Once again, when you do this we'd prefer you use the new API to verify that the screen is as expected before you mess with it.

Q: Okay, thanks, that's cool. But I see some stuff in the headers that kind of looks like API to draw in gray. Can I use it?

A: It's not supported.

Q: Oh, OK. ... But can I use it?

A: Well, you can jump to any address or call any trap and pass in any data you want, so we can't really stop you, can we? However, one reason you might not want to write code that uses these APIs is that the traps and structures may change, maybe even as soon as the next release, breaking your code. Are you willing to live with the fact that you might have to throw your code away?

Q: Um, well... maybe. Would it be worth it?

A: Probably not.

Q: Tell me anyway.

A: Well, since you insist.

Grayscale Bitmaps:

If you look in the WindowNew.h header file, you'll see some changes to the BitmapType struct. In particular, notice that there is a pixelSize and version field in the structure, and the nextDepthOffset field.

Also notice the hasColorTable field in the flags structure, and the new ColorTableType struct. For starters, ignore the ColorTable stuff. The PalmOS 3.0 ignores it. Please leave the 'hasColorTable' flag set to 0. Also, the comment about colorTable data being present if pixelSize is 2 is wrong. The hasColorTable field in flags is used as a test, and if that flag is 0, then it's assumed there is no colorTable data.

Anyway, the OS now attempts to draw bitmaps that are 1- or 2-bits deep. Bitmap families can be created by using the nextDepthOffset field to indicate that starting after the bits in the current bitmap there will be another BitmapType struct with a greater depth. (Bitmaps must be in order of increasing depth, and you shouldn't try to include 2 bitmaps of the same depth, unpredictable things will happen.)

The color table for 2-bit deep bitmaps is the obvious one. 0 = white, 1 = light gray, 2 = dark gray, and 3 = black.

When one of these structs is passed to WinDrawBitmap, the OS will attempt to use the image that most closely matches the depth of the display. If a matching image is not found, the largest depth less than or equal to the current depth will be used. If there isn't one, the smallest depth will be used. Said another way, the OS tries to use 1-bit images on 1-bit displays and 2-bit images on 2-bit displays, but if it can't find them it will draw 1-bit bitmaps to 2-bit displays and 2-bit bitmaps to 1-bit displays, albeit more slowly. Don't bother experimenting with bitmaps greater than 2 bits deep.

Q: Are there any tools for creating these bitmaps?

A: None that are released or distributed, sorry.

Q: But what if I really want to?

A: Well, you could always create the tBMP resources yourself, using the definitions in WindowNew.h.

Q: Yuck, what a pain. You guys must have done something to test the APIs, right?

A: While neither confirming nor denying that we tested these APIs, I do notice that the grayscale drawing code works pretty well...

Q: So what did you do?

A: We updated our internal tools.

Q: Don't make me work so hard! Can I get these updated tools?

A: Actually, odds are good you already have them, since they seem to have crept into the latest MW release. The problem is, they're not supported so you can't actually use them.

Q: You keep saying that, but what if I really want to use them?

A: You still can't. ...unless... are you willing to do the work necessary to change your app later when the tools change? That is, do you accept that by doing this stuff, you're writing a very tool-dependent application, which probably won't build the same way on future releases.

Q: Yes! I'll do anything for gray.

A: Well, since you're so enthusiastic... welcome to hackerdom.

PilotRez looks for "flags" embedded within the NAME of the Mac PICT resource, and these flags control what kind of tBMP the PICT is translated into. (I have no idea what the Windows tools do--sorry.)

The flags must be delimited by "/" characters at the beginning and end, and must appear first in the name.

Read this next section carefully, the meaning of the flags is non-intuitive. The flags are:

	-1	Include a 1-bit deep image
	-2	Include a 2-bit deep image
	-c	Disable compression

"/-1/" is the default setting, and produces a 1-bit deep compressed tBMP. This applies if no flags are specified.

Note that if you include the -2 flag, you DO NOT get a 1-bit deep image in the tBMP unless you ALSO include the -1 flag.

Note that the sense of the -c flag is reversed. Including the flag turns compression OFF.

For example, a PICT with the name "/-2/foo" produces ONLY a 2-bit deep, compressed bitmap. A PICT with the name "/-1 -2/bar" produces a tBMP with both a 1-bit and 2-bit deep compressed bitmap. A PICT with the name "/-c/baz" produces an uncompressed, 1-bit deep bitmap.

For now, you always want your bitmaps to include a 1-bit deep image, so that they will render properly on earlier releases of the OS. This means you should always include the -1 flag.

Q: Okay, well, it's worth a try anyway. You said this probably wouldn't work in the future, can you say more about that?

A: Yes. This approach has some drawbacks. For one thing, it's not possible to specify different bitmaps for the 1-bit and 2-bit deep images in a single tBMP resource. That means your 1-bit deep image will be a down-resolution rendered version of your 2-bit deep image. Also, there's no way to "mix" compressions among the image depths in a single tBMP. (Though that's of dubious utility.)

We will almost certainly be updating the tools to eliminate these drawbacks if and when grayscale drawing becomes a supported part of the Palm OS. We almost certainly will not continue to use flags in the name of a resource to control these settings.

Q: Well, that's neat anyway, and I might even be able to use it. But what's this stuff about foreground and background colors, and what's RGBColorType for?

A: Aren't you persistent! Well, for starters that's even more likely to change than the gray bitmap stuff. In fact, using these routines is almost certainly a complete waste of time.

Q: Well, I just have an insatiable curiousity about this stuff, and I think it'd be really neat to draw in gray, and honestly I've got way too much time on my hands anyway, so will you tell me more?

A: Wow, you sure are persistent. Okay, you've talked me into it.

When drawing text, lines and rectangles, and 1-bit deep bitmaps, the OS will occasionally attempt to use the current foreColor and backColor. These colors are set calling WinSetColors and passing in an RGB value represented as an RGBColorType. For 2-bit grayscale, only white, black, and 2 shades of gray are available, so a 24-bit RGB value is definitely overkill, but that's what you pass. Only these values are really useful:

static const RGBColorType black = {0x00, 0x00, 0x00, 0x00};
static const RGBColorType dkGray = {0x00, 0x55, 0x55, 0x55};
static const RGBColorType ltGray = {0x00, 0xAA, 0xAA, 0xAA};
static const RGBColorType white = {0x00, 0xFF, 0xFF, 0xFF};

Anyway, when you call WinSetColors, you get back the old foreground and background colors. Make sure you save these values, and restore them when you're done drawing. If you leave the colors in a state other than they were when you started, unpredictable things will happen.

Once you've set the foreground and background color the way you want, you just draw using the same routines you're used to. Some of them will do what you expect, and some won't. In particular, transfer modes other than scrCopy will probably not do what you expect.

Q: Hey, thanks! I can't wait to add some grayed out buttons and menu items to my app!

A: No no no! That would look ugly and waste space. Please try to stick to the current style guidelines, and don't make me regret sharing this info with you!

Q: Good point. But I can't wait to port my grayscale game to the new APIs!

A: You should probably think twice about that. You currently have hacks to draw in gray that work on all the PalmOS devices. Why would you change them so they only work on one? Future compatibility isn't a concern, because there's just as much chance that above APIs will break on the next device as there is that your hacks will break. Writing to screen memory is relatively efficient, it's actually slower to mess with RGB values and system traps, so your hack will even perform better.

Q: Oh, well, thanks anyway. I always like to know as much as I can about the PalmOS!

A: You're welcome. Happy hacking!

 

Development Information | Software Development | Hardware Development
FAQs | Technical Questions | Other Resources | Development Support Home

© 1999 3Com Corporation. All rights reserved. Terms of Use.