On the joys of grotty code #

Today, for the n-th time (for n > 10) I received a bug report about Iconographer sometimes clipping the right-side third of the 48 x 48 (huge) icon member 1-bit mask. In a fit of constructive procrastination, I decided to look into it. What followed was several hours of delving into code that I had started writing more than 5 years ago. The problem seemed to reduce to something like this: when using CopyBits in srcCopy into a 1-bit 48 x 48 GWorld with the destination rectangle encompassing all of it, the right-side 16 pixels (of the full height of the image) would get set to white, regardless of what the source was. Changing the mode to srcXor, shifting the destination rectangle or changing the with of the image all made the problem go away.

Obviously I wouldn't have shipped something like this, so the problem must have materialized in the meantime. Sure enough, this wasn't reproducible on a machine that was still running 10.2. I figured that QuickDraw, especially when operating on 1-bit GWorlds must not be very high up in Apple's list of priorities, and so this was something that had gotten past their regression tests. The workaround seemed to be to use srcXor mode, and first clearing the destination area (i.e. setting it to white). This had the same effect as a normal srcCopy CopyBits with only a slight performance/complexity hit. It worked as expected, and I figured I could leave it that and begin preparing for a 2.5.1 release in a few days.

However, I wanted to make sure that this was really the case, and perhaps even report the bug to Apple. I made a simple test case app, and discovered that the problem wasn't exhibited there. After much digging around, I traced it to the way I was creating my GWorlds. Normally this is done with NewGWorld, however at some point in the distant past I had my my own wrapper for it. The reason was the padding that QuickDraw adds to each row, presumably so that each one can be aligned to a 16-byte boundary in order to speed up memory accesses. However, icon data is stored unpadded in the 'icns' resources and .icns files, and the back and forth conversion seemed rather tedious to me. I therefore created a wrapper called NewGWorldUnpadded that would allocate a GWorld with a slightly smaller width, so that the final allocated size would correspond to the unpadded final desired width. I then had to fix back the GWorld, changing its bounding rect, clipping region, row bytes field, etc. so that it was consistent with my desired size. This required a lot of twiddling with the GWorld and PixMap data structures, something I feel isn't very encouraged today. I was in fact very proud of this back in the day, since not only did it make loading/saving easier, but it also cut down on memory use of saved drawing states. I should have realized this tradeoff perhaps wasn't worth it, since two days after releasing Iconographer 1.0 I had to do a 1.0.1 release, fixing a bug caused by this wrapper (since I was using it for selections, which weren't always a multiple of 16 in width, a case I hadn't accounted for).

The problem seemed to be with the manual changing of the rowBytes field of the GWorld's PixMap. Part of this was because there is now a PixMapExtension struct linked from the PixMap's pmExt field, and this struct has a longRowBytes field that needs to be kept in sync (I believe that 10.2 was more lax about this, since the regular rowBytes field is enough for smaller values). There are now functions such as QTSetPixMapHandleRowBytes that would perhaps take care of this, but the solution is very simple. It is now 2004, not 1998, therefore wasting 3K of memory is not a big deal. I can scrap NewGWorldUnpadded entirely, and just use regular GWorlds, dealing with the padding as appropriate. This will hopefully fix not only this problem, but also others that I have seen (e.g. rotations sometimes causing crashes). The only downside is that there are 15 places where the wrapper is used, with presumably many more pieces of code that rely on GWorlds having no padding. It will probably take a while to fix.

4 Comments

Just wondering if you've officially abandoned Iconographer?
Yes me too, I really like IconGrapher and haven't found any symaler software.

When will the much talked about version 3.0 hit the shelves?
Sorry to bleat on about Iconographer as you may of abandoned it, but if that is the case is there any chance of making it open source so someone else can carry on this fantastic piece of software?

We would all love to see Iconographer move another step forward, especially after 3 years!

Kind regards,
Tom.
After almost 4 years since the last blog entry about this, I guess you've truly abandoned it... can anyone recommend an alternative program?

Post a Comment