Showing posts with label Iconographer. Show all posts

Archiving Mscape Software on GitHub #

Mscape SoftwareMscape Software was the “label” that I used in my late teenage years for Mac shareware programs. While having such a fake company was (is?) a surprisingly common thing, it turned into a pretty real side-gig during 1999 to 2003. I spent a lot of my hobby programming time working on Iconographer, an icon editor for the new-at-the-time 32-bit icns icon format introduced with MacOS 8.5 (and extended more with the initial release of Mac OS X). The early entries of this blog describe its initial development in pretty high detail — the deal that I had with my computer class teacher was that I wouldn’t have to do any of the normal coursework as long as I documented my progress.

All of that wound down as I was finishing up college, and I officially decommissioned the site in 2008. I’ve been on a bit of a retro-computing kick lately, partially inspired by listening to some of the oral histories compiled by the Computer History Museum, and I was reminded of this phase of my programming career. Over the years I’ve migrated everything to GitHub, which has turned it into an effective archive of everything open source that I’ve done (it also makes for some good RetroGit emails), but this earliest period was missing.

I didn’t actually use version control at the time, but I did save periodic snapshots of my entire development directories, usually tied to public releases of the program. It’s possible to backdate commits, and thus with the help of a script and some custom tooling to make Git understand resource forks I set about recreating the history. The biggest time sink was coming up with reasonable commit messages — nothing like puzzling over diffs from 23 years ago to understand what the intent was. Luckily by the later stages I had started to keep more detailed release notes, which helped a lot.

github.com/mihaip/mscape is the result of the archiving efforts, and it’s showing up as expected on my profile:

GitHub commits from 1998

I tried to be comprehensive in what is committed, so there is a fair bit of noise with build output and intermediate files from CodeWarrior, manual test data, and the like. The goal was that a determined enough person (perhaps me in a few more years) would have everything needed to recompile (there are still toolchains for doing Classic mac development).

It’s been interesting to skim through some of this code with a more modern eye. Everything was much lower-level — the event loop was not something that you could only be vaguely aware of, it was literally a loop in your program (and all other programs). Similarly, you had initialize everything by hand, do (seemingly magical) incantations to request more master pointers, and make sure to lock (and unlock) your handles. If you want to learn more about Classic Mac Toolbox programming, this pair of blog posts provide more context. Had I been aware of patterns like RAII, there would have been a lot less boilerplate (and crashing).

Speaking of C++ patterns, there are a bunch of cringe-worthy things, especially abuse of (multiple) inheritance. Need to make a class that represents an icon editor? Have it subclass from both an icon class and a document window class. It was nice to see some progression over the years to better encapsulation and data-driven code instead of boilerplate.

Another difference in approach was that there was a much bigger focus on backwards compatibility. clip2cicn and clip2icns both had 68K versions, despite it being 4-5 years since the transition to PowerPC machines begun. clip2icns and Iconographer both used home-grown icon manipulation routines (including ones that reverse-engineered the compression format) so that they could run on MacOS 8.1 and earlier, despite the icon format they targeted being 8.5-only. Iconographer only dropped Classic Mac OS support in 2003, more than 2 years after the release of Mac OS X. If I had to guess, I would attribute that to at least my not making rational trade-offs: would people that were hanging on to 5-year-old hardware be spending money on an icon editor? But I would also assume that Mac users tended to hang on their hardware for quite a while, presumably due to the higher cost.

On the business side, Brent Simmons’s recent article on selling apps online in 2003 pretty much describes my approach. I too used Kagi for the storefront and credit card processing, and an automated system that would send out registration codes after purchase. Iconographer ended selling 3,500 copies (the bulk in 2000-2003), which was pretty nice pocket change for a college student. On a lark I recreated the purchasing flow for 2021 using Stripe and it appears to be even more painless now, so modulo gatekeepers, this would still be a feasible approach today.

Decommissioning Mscape Software #

Before I became enamored with web development, I used to be a Mac software developer under the Mscape Software moniker. My first public release (clip2cicn, a helper tool for making the icon resources necessary for Kaleidoscope schemes) was almost 10 years ago, on June 26, 1998. My flagship product was Iconographer, an icon editing tool.

I haven't had time for Mscape Software for about 4 years (the last Iconographer release was in July of 2003, and I last touched the code in early 2004). The site was still up, and I kept receiving registrations (Iconographer was a $15 shareware product). As time went on, I began to feel more and more guilty about not providing any support for (paying) customers. To this end, I have finally gotten around to dismantling Mscape Software, replacing the site with a placeholder with download links for all products. I've also put up a registration code for Iconographer so that the (annoying) registration reminder can be shut off.

I've gotten some requests to open-source Iconographer, but I'm not sure I'll have time even for that. I'm not 100% sure I can build the product given software on hand (it was built with CodeWarrior). Even then, the codebase shows its age (it was my first large-ish project and still uses many Classic constructs like a WaitNextEvent event loop).

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.

Iterations++ #

Members Palette Mockup 2Further tweaking of the revised members palette results in this design. First, the 4-bit depth is gone for sure, so that's one thing to cross off of my list. Additionally, as it can be seen the labeling is done by putting all members in a grid. The window is small enough that I can make it fixed size (well, except for the collapsing of the thumbnail and hints sections, though even that may be left out), and so the mini scrollbar was taken out. This frees me to use full-height buttons for the other commands (I'm also planning on adding support for icon states, as it can be seen). Finally, since I see this mode as being superior to the old members palette in every single aspect, there won't be any need for a toggle.

In some ways the new palette should be simpler to code up than the old one (since there's no scrolling to worry about, and inactive members will be drawn as disabled instead of being hidden). The expanding/collapsing of the thumbnail and hints sections may be tricker, but I'm planning on moving to Carbon Events and this should let me smoothly move controls during that operation (if the Finder can do it for its Get Info window, so can I). I think it's about time I switched to using HIViews for my custom controls, which means requiring Mac OS X 10.2 or later, but that's something I can live with (it's not like I have installs of 10.0 and 10.1 lying around to test against anyway).

The plan is to do a bit of refactoring, by keeping the MembersPalette interface the same, but completely rewriting its implementation. We'll see how good my object design and encapsulation really is.

Apple MockupThe funny thing about this design is that it bears a strong resemblance to the original one that Apple had sent me, back when the plan was to turn Iconographer into the quasi-official icon editor for Mac OS X (perhaps I was being subconsciously influenced by it, but I didn't make the connection until I was done). I rejected it back then due to its bulkiness, which perhaps isn't as much of an issue now (if nothing else, Mac OS X has acquainted people with interfaces that take up a lot of space).

Finally, in light of this pretty significant interface change, and because I'm adding support of icon states, the next version should really be 3.0 (I've been stingy with bumping version numbers anyway).

Photoshop, a man's best friend #

Members Palette Mockup One of the issues with Iconographer's UI in its current iteration is that it requires a lot scrolling to get from member to member (screenshot). With monitor aspect rations tending to the wider side lately, it makes sense to take advantage of extra horizontal space.

Therefore, as an alternative in Iconographer 2.6, I'd like to have a members palette that looks something like the one to the right (thanks go to Microsoft Word and OmniGraffle for inspiration). The palette is then twice as wide as it normally is, and so the preview and color ones can be put side by side underneath (since they're of unequal length - though I may tweak that too).

There's still a few issues:

  • I don't have enough room for the 4-bit member (in the Huge variety). Since support for them is deprecated anyway, it may not matter at all. I am considering dropping support for pre Mac OS 8.5 icons altogether in fact.
  • I'm still not sure how to label the different icon and mask depths. I can use mini icons (Icon Machine style), or some kind of clunky label (e.g. "32/8/1-bit icon") for each grouping.
  • How will this mode be activated? Is can be just a matter of resizing the window to be wider (but since intermediate values won't be allowed, how will it occur to the user to do that in the first place?). Or it can be another option in the preferences, along with the current "Display Scaled" setting. However, I have a feeling that's also not very discoverable.
  • The super-tiny "Add Member" and "Info" buttons are bugging me more than ever (though they also have key shortcuts and menu items). I may have to go back to using normal sized scrollbars, which would let me have regular sized grow-boxes, which in turn lets me make those buttons 16 pixel tall, better than the current 11.

Kills Bugs Dead #

Finally fixed annoying bug that made palettes show up as hidden at startup, but very sporadically. Turned out that it only happened when quitting Iconographer from the Dock context menu while it was placed in the background, because then the palettes were nominally hidden (but not really).

It's really that simple... #

Import/export done and tested on OS X, but crashes in Classic. Must investigate.

Match Me Up #

Match-up dialog work. Was initially too tall to fit even on 1600 x 1200 screen, went with two column layout and small controls to make it work at 800 x 600.

Get Me Out Of Here #

Multi-file (entire icon) exporting works too, with things getting named properly, enclosing folder being made, etc. Had idea for import matchup dialog.

Seinfeld Rocks #

Started to work on import/export (a.k.a. the Art Vandelay release). Got basic (single file) importing/export working.

Floating and Gloating #

Activity in this project is starting to resurge after a somewhat long break. Up until last week it was up to the point where I had started on several things, but hadn't finished them, and still had a bunch of stuff planned for version 1.1. First of all, there was the support for the 256 color Windows system palette. My main problem here was finding what the standard palette was. I downloaded three or four icon Windows icon editos, and looked at the palettes they used for their 256 color mode, and they were all different. This wasn't such a big issue as it would have been on the Mac, since Windows icons can include a custom palette, but there would have been no point if several of the supposedly standard colors were actually dithered when displayed in 256 colors. In the end I got that what the Eudora team used as the standard colors (at least according to Arlo), assuming that they knew what they were doing. Actually implementing this palette wasn't that hard, since I already had support for the 4-bit windows one, so it was a matter of marking the 8-bit depth as supporting the windows colors too, getting the color picker picture (my color picking function takes a picture as its parameter, it doesn't care what colors are actually contained and how they're arranged as long as they're divide by a special colors (0x01, 0x00, 0x00)) and making the Windows .ICO loading function use these new colors.

Then I worked on finishing up the new icon browser (the Finder-like list of all the icon resources contained within a file). I had started to allow it to use the arrow keys to scroll through the list, but I wasn't actually scrolling down when the user went below/above the icon visible at the current scrolling level. Also, if a user double-clicked on an icon that was already open, it would open up a new window instead of bringing to front the current one.

Then I worked on adding a Windows menu. I didn't really see it as being necessary, usually people edit one or two icons, and don't need a menu to toggle between them. The main reason I did this was to have a place from where the colors palette (see next paragraph) could be shown and hidden. I realized that I needed a way to attach a menu command to a certain editor that was open. I decided to assign each editor an ID when created (it would be released when closed), and then store the ID inside the menu (menu items can contain a user defined reference number), so that when a menu is selected I can get the ID, look up the editor and bring its window to the front. One of the more tricky things here was that I wanted the icon editors and icon browsers to be separated by a divider, and I didn't want any floating windows to be listed. In the end I used the the window type attribute of the window class to differentiate between them.

Afterwards I finally started to work on the floating color palette, since this is the last big thing before I can release version 1.1. Mac OS 8.5 and above include built-in support for floating windows (well, technically anyway, practically the implmentation in 8.5 is completely broken, and only 8.6 and above works), but that would have been too steep a requirement, since the rest of the program works with 8.0 and above. However implementing floating windows on older versions requires some kludging. The main problem is that you have to have more than one window active (all the floaters, and front most document window). The standard Mac OS Toolbox functions, such as SelectWindow automatically disable the other windows when they're called. You have to use lower level functions such as BringToFront, SendBehind, and HiliteWindow to perform window manipulation. Also, getting the front-most window can't be done with FrontWindow, since the floaters are above everything else. This is where it become very advantageous that I had decided to use classes for each window (I have a MWindow class, and the icon editor, icon browser and floaters are all derived from it). I added some static functions to the MWindow class (so that they didn't require an instance to be called) to replace all the standard Toolbox functions that I had used so far. I also had to add additional calls since the floaters have to be hidden when the application is put in the background. The current status is that I have a floater which can be hidden or shown at will, and actually behaves as a floater. It doesn't have anything in it yet (it just beeps when clicked on, as a simple test that it can handle events).

As I was testing the floater implementation, I discovered some positioning problems. For the icon info dialog that's displayed, I set the "Center on parent window" bit. The parent window is determined as the window that was previously in the front, but the system does this for me, so it has no way of knowing that I don't want the floater to be considered as the actual front-most window. I added a CenterOnParent function to the MWindow class, so I used that to manually align the info window. However then I discovered that this problem extended to the "Do you want to save" dialog too, but here I can't tweak the position by hand, since I use a system function, StandardAlert to generate it. In the end I guess I'll have to rewrite the function myself, to make it center properly. I kinda had to do this anyway, since I couldn't use it to display the "You don't have the Appearance Manager installed" alert (the function is a part of the Appearance Manager), so things should be quite beneficial.

On a separate note, it greatly amuses me to see that Icon Factory are finally releasing the Pro version of their IconBuilder product (competition to my earlier 32-bit icon insertion tool, theirs is a $49 Photoshop plug-in vs. my $10 one-shot utility), with supports 48 x 48 icons and Windows importing and exporting. They promised this in Q2 1999, so they're a bit behind :p And of course, Iconographer has had these features since it was released (mid September 1999), along with a $15 price tag (their Pro version will cost extra), Photoshop integration, Mac OS X Server importing, etc.

Revulsion #

I really, really want to rewrite the whole application. I was adding more generic support for multiple formats, and it got really ugly. In the first place, I didn't foresee that it'll support multiple formats (the Windows and Mac OS X Server import/export stuff was added over the summer), and now that I treat the pre and post Mac OS 8.5 icon formats differently too, things are even messier. On the surface things look fine, so I think I'll manage to get version 1.1 in a resonable state and release it. However, I'm not sure if the fancier stuff like the floating color palette windows (which are torn off from the color picker) will make it. I guess the best thing would be to use Meshroom and the Apple icon thing (I just wrote to them, the idea of doing what they want as a separate application was favorably received, it's just that they (well the lawyers) want a stupid name like Apple Icon Tool, I proposed Apple Icon Assembler, since that's pretty much what it does) to improve MFrame (e.g. add built-in support for controls, floating windows, and a new way to handle icons, since Mac OS X introduces a new format of it's own, and there's still the Windows one too (they want to discourage people from using the Mac OS X Server one, so I'll just have TIFF importing)) and then use it to do a new version of Iconographer (2.0? perhaps). The thing is, this will probaly end up taking a while, and I still want to do interim releases of Iconographer, because otherwise people will simply think I dropped it. I guess I'll try to make the new features as modular as possible, so that they can be dropped into either version. Now that I'm done with the college applications, doing all this seems actually feasible :p

Undo Tweaks #

I've been doing some tweaks lately to further polish Iconographer (this is what version 1.0 should have been, but I kind of rushed it in the end, as in 1.0a1 got turned into the final release). For example, towards the end of summer I added an option to use the Windows system palette (as opposed to the Mac one) when dealing with 4-bit icons (a user had requested this). However, after I implemented the basic functionality, I totally forgot about hooking it up to the rest of the interface (as in, the command couldn't be undone, icons weren't converted automatically when saving one with the windows colors in the mac format, etc.) A couple of weeks ago someone complained about the windows -> mac color issue, so I implemented a quick fix for it. However, this last week while I was trying to figure out why people were reporting crashes when converting icons, I discovered that the app would crash all the time now when converting between mac and windows 4-bit icons. As it turned out the quick-fix wasn't the root of my problems, it was just another thing that I had induced recently. That's also when I realized the problem that I had with not being to undo the command.

I realized that implementing the undo wasn't quite as easy, since I was creating a totally new PixMap with a new color table and disposing of the old one. Until now, each saved drawing state had stored with it the name, pointer to the GWorld and handle to the PixMap that were being saved (and thus should be eventually restored to). But now that I couldn't depend on the pointers and handles remaining unchanged, I had to figure out another way of deciding where to restore the saved data (which by the way is compressed, I realized that I could reuse the icon compression code to save space (e.g. a 6K blank canvas is now around 800 bytes, for fancier drawings the final size is usually still smaller than 3K)). I realized that the name could also give me pointer and handle, with a simple case statement. So I added a GetGWorldAndPixMap method to the icnsEditorClass and everything seemed to work (that is I could draw something in the 4-bit icon, convert it to windows colors, draw some more, and then undo all the way back to when it used the mac os colors). However, I ran into a very weird bug. If I undid it all the way back to the original blank canvas created when making a new icon, redo wouldn't work properly. When getting to the 4-bit icon, it would pause for a while, and eventually the canvas would be partially the color of the desktop, and otherwise empty. What was even more annoying was that I couldn't get this to happen all the time. After setting some breakpoints, I discovered that the GetGWorldAndPixMap function I had mentioned before was returning NULL. However, it covered all the possible cases of the names, and adding a default case didn't help (it didn't get called with it). After much annoyance, I finally discovered the source of the problem. When I was saving the initial state (the blank icon created at the beginning), the colors variable (which determined which palette to use, the mac or windows one) was uninitialized, and thus when attempting to restore the state the color conversion function would screw up, which would set into motion another weird chain of events. The fix simply required to swap the order of two lines. I'm not really sure what I could have done, I guess the CodeWarrior pre-processor isn't quite smart enough yet to discover usage of uninitialized variables when it happens across classes and files.

Files #

Nothing earth-shattering happening here, but I'm slowly making everything come together. In version 1.0, the open menu item had a sub-menu, with three choices for each of the formats that Iconographer could open (Mac OS, Windows and Mac OS X icons). This was messy, both code-wise (since I had three very similar sets of functions) and user interface-wise (since the user had to know in advance what kind of file s/he wanted to open). The reason why I did this in the first place is because the Mac OS open dialog had to allow you to open folders as well, since folders can have icons too. For some reason I thought that this variant of the open dialog (NavChooseObject) couldn't be customized, so I couldn't add a pop-up menu with the format selections. Now that I've realized this, I've ripped out the old code and now I have a much cleaner way of handling files. The only thing remaining is to do the same for the old-style file open dialog. This is rather annoying actually, since all the StandardFile code will be obsolete with Carbon, and it has a totally different way of customizing the dialogs.

Also on the topic of file-handling, some people are reporting crashes when saving, and I can't reproduce them. I might have to resort to a clean-install, or perhaps trying to open and save a bunch of files.

Ro-bust! #

I've been making Iconographer more robust in low-memory conditions. Until now, if the memory was filling up as the user was drawing (since I'm saving the drawing state for multiple-undo support), Iconographer would not notice unless there was a selection active. Also, the checking when creating a new editor wasn't working as expected, since I wasn't initializing certain variables to NULL (why it worked when I was doing the testing for the IB dossier I'm not sure, perhaps the older version of CodeWarrior (especially the debugger) intialized the variables for me).

So far, I have three separate menu commands for opening the three icon types that Iconographer supports (Mac OS, Windows and Mac OS X Server). However, I just realized that I can customize the open dialog, and put in an "Icon Format" pop-up so that a single dialog can be used for all the formats. The reason why I didn't think of this earlier was that the Mac OS Icon open dialog is slightly different (since I need to be able to open folders too) and I didn't think it could be customized.

Mock me up #

The only actual programming that I've done so far is to make sure that the menu titles are highlighted properly when hierarchical menus are selected. Until now, selecting something such as Edit: Select: All would not highlight the Edit title as expected. It turned out that the Menu Manager was trying to hilight the title of the Select menu, but since it wasn't in the menu bar (being a submenu of the Edit menu), nothing would be seen. Right now I hilight the title by hand, because I haven't been able to find a way to get the parent menu's ID.

Somewhat more interestingly, I finally got the mockups and plans for what the Apple people (which from now out I ought to refer to as Matt (the UI designer, altho at Apple's he's just a lowly icon designer) and Arnaud/Arno (programmer, he designed the Icon Services in Mac OS 8.5, and I guess he's in charge of the icon stuff in Mac OS X, the second spelling of his name is to give a clue to the non-French speakers on how to pronounce his name).

What Matt has in mind goes reasonably well with the ideas I had for the next major release of Iconographer. This mainly includes going to a palette based interface. However, while I had thought of splitting everything up into floaters, trying to mimic Photoshop as much as possible, he's decided to down-play Iconographer actual editing capabilities, and instead treat more as an icon assembly tool. The main window will now be the Worktable (as opposed to the Drawing Board, as it is now, BTW, these terms are his, not mine). In the Worktable, all of the icon/mask sizes and depths will be visible. Double-clicking on one would open it up in the editor app that the user has chosen. Whether this is Iconographer's internal editor, or Photoshop, it's up to the user. There is also a separate floater for the previews and the icon states (in Mac OS X the user will be able to determine exactly how the icon looks when it is selected, openened, when another file is dragged onto it, etc.)

A couple of days ago I realized that since he's separated the editing portion (which is pretty much the current functionality) from the rest of the features (which will be mostly new additions to the current app), I could do what he's proposing as a separate app, which could optionally integrate with Iconographer. I'm not sure if this how the final (i.e. publically released) version will be, but at least during the development process this would make sense. Then I could keep adding features and releasing new versions of Iconographer in it's current state, while at the same time doing what Apple wants without having to maintain two separate codebases. If I use a common base (which is really the point of MFrame), then merging the two later on shouldn't be that hard.

Smooth as a baby's bottom #

While fooling around with the dragging between the various sizes, I noticed that drawing a 3 pixel thick border in the 48 x 48 size, and then dragging it over to the 16 x 16 slot (this involved scaling it down) yielded some reasonable looking anti-aliasing (this is because of the way QuickDraw implements copying when the source and target rectangle are of different sizes). Actually I'd kinda noticed this before, but I hadn't really thought about using it to add anti-aliasing.

In any case, as a quick test, I wrote a quick FrameOvalAA (as opposed to the normal FrameOval) function which drew an oval with a 3 x 3 pen and then copied it down to size. Everything seemed to work all right, but it order to get it to look exactly as it was meant, a bit more tweaking was required. The problem is that not only does the oval have to be anti-aliased, but it has to blend in with the background as well. What I ended up doing was to create an 8 bit mask which had the anti-aliased shape in it, and using that to composite the current icon contents and the foreground color. I was originally creating a few scratch GWorlds, but then I realized that I had the canvas gworld used by all the icns editors, so now I'm using different areas of it for the 3x version, the mask and the foreground color. Since it involves 2 additional CopyBits/CopyDeepMask passes, the function probably isn't fast enough for real-time anti-aliasing, so I left in the old (non anti-aliased) code for the oval that is drawn while the user is dragging the mouse.

I figured that since this worked out pretty well, I should do the line tool next. The base idea here was the same too, but it required a little bit more tweaking. The problem was that since, when the line has a thickness greater than 1, it extends beyond the starting and ending points (at least with the line drawing method that QuickDraw uses). I had to add some extra padding, and make sure that vertical and horizontal lines were still being drawn (since they would "fit" in a zero width/height rectangle).

The polygon tool shares some aspects with the line tool, so I moved on to that one. This also required some padding, and since I was using the built-in Mac OS data-type for sotoring them, I had to use some different functions (MapPolygon) to enlarge the polygon to 3x the size.

Then, going back I realized that filled ovals weren't quite behaving as expected. The problem was that the frame wasn't quite covering the edges of the filled center, so most of the anti-aliasing was lost (this was most noticeable when the fill and the frame were of the same color). Some additional hacking was required (and the current code is rather ugly), but the ovals now look good whether they're filled or not.

This lead me to notice two things: 1) a somewhat similar anomaly seems to be happening with the filled polygons too. 2) I was getting frequent freezes when attempting to use the pattern pop-up (the ovals can be filled with patterns too). I'll try to determine if this is because of the beta drivers I'm using for my graphics card (the freeze seems to take place in a function called TerminateGraphicsAcceleration), or if it's my fault. In any case, I'll be dealing with both of these tomorrow.

Anti-aliasing will be even more useful when I add the simultaneous icon and mask drawing. Then I have to combine the anti-aliased mask with the icon mask, and then color with the icon. Rather hard to explain, but much easier to demonstrate visually. I'll see about drawing up some mockups to show what the intended effect is.

No mail from the Apple person (they said they'd contact me by the 15th). If there still isn't anything by tomorrow, I'll email them asking what's up. They haven't been specific at all as to what exactly they want changed in Iconographer, and I'm really curious :p

I think that alternating back and forth between Meshroom and Iconographer is a good idea, because they're really projects at opposite ends of the spectrum. Meshroom (in it's current state) is still in the planning stages (yes, I'm actually trying to have a pretty detailed plan before I start coding) while Iconographer has a complete base and a large amount of features, and now I'm just adding things on (although a big restructuring might come in the future).

IB Dossier Requirements #

I didn't have time to program today, but I can do the required 3 paragraphs on the required concepts for the IB dossier:

Dynamic data structures:

The main way in which I show this is through linked lists. Since there can be more than editor open at once, I keep track of them through a linked list. When a new editor is created, I add it onto the end of the list. When an editor is closed, I remove it from the list, and keep the links between the previous and the next element up to date. Also, within each editor I use a list to keep track of all the changes that user has done. When a drawing command is executed, the new state is saved to the end of the list. When the user wants to go back, I simply move to the previous stored state and restore it. If the user wants to go forward, I can move forward, and restore the state. If the user goes back, and then starts drawing again, the states that were ahead of it (if any) are disposed since they are not needed any more.

Advanced operations on data structures:

I'm not quite sure what they mean by this. I have a searching function, since I want to create a list of all the icons, sorted by ID (when I get them from the file, I get them in the order that they were stored in). So I insert into a sorted list.

Recursion:

See above.

The Usual Excuses #

Didn't have much time for work today, it was the second day of the JOs (swim meet). Only thing I did really was to fix a bug, I wasn't allocating the emergency memory chunk when the program was starting up, so the first dispose would cause weird things to happen since it wasn't allocated.

Stability Improvements & Future Plans #

Did some work on making Icon Mangler more stable (got distracted while I was commenting). Until now it was the icnsEditorClass's job to see if it was out of memory, and to deal with it (by calling delete this). However that was not a very good method, since the linked list was not nto maintained properly, and it was not a good separation between the main program and the class. The best solution would have been to use exceptions, but I don't have the time to learn them properly before the program is due. Instead I added another bit to the status field of the class (which was used to communicate with the main program anyway), outOfMemory. When that us set after the constructor has been called, we assume that the construction failed, and dispose of the editor. In places within the program too, we call this, when making temporary GWorlds and so on. Then in the DoIdle of the main program we check through all the editors if they're out of memory. If they are we dispose of their saved undo states (which can free up quite a bit of memory if the user has been working for a while). If we have already done that, and there still isn't enough memory then we must close the editor. We display an alert, and let the user save if they want to. In order to make sure that there is enough memory to display the error message and the save dialog (even though we are supposedly out of memory), I allocate a chunk in the beginning of the program (for emergencies like this) and dispose of it in order to free up memory, then when I'm done I allocate it again for future use.

So far this is working pretty well, except that the save dialog when using the Navigation Services wants about 100K of temporary memory, and making the emergency chunk that big is kind of a waste. This isn't an issue for the IB, but in the final program I think I can pre-load the Navigation Services library at the beginning of the program, and unload it at the end.

Also, I'm still not checking whether I have enough memory to save the drawing state, so I need to do some work there too.

On another note, I've thought about the future of Icon Mangler (post IB). I want to make it into a decent icon editor. One of the things that is lacking right now is the option to make only certain sizes/depths available. Right now if you add a 48 x 48 icon at a single depth, then when saving all the other depths are saved too, even though they are not used (so they are white). Also, when making a new icon, all the sizes/depths are allocated, even though they are not used. My solution for this (actually this would go in the base icnsClass, but it'll affect Icon Mangler too) is to have an array of pointers to the icon depth/sizes combinations. When the user adds a new size/depth then the respective pointer is allocated, and when saving only the ones that are used are actually saved. Deletion of depths/sizes should be easy too, since it's a simple matter of calling DisposePtr.

For the actual editor, I think I might have a separate editorClass, from which I make a derived class called icnsEditorClass (which also has as its parent the icnsClass, so we have multiple inheritance :p). The editor class would do its drawing actions on a pixmap/gworld called drawingPix/drawingGWorld. Then in the icnsEditorClass its simply a matter of setting the pixmaphandle/gworldptr to the current size/depth. I'm not doing this just because it sounds fancy, but because it could be useful in the future. For example I could make an editor for other graphical resource types too, and then I wouldn't have to rip out the editor out of the icnsEditorClass and replace the icns specific parts with something else (this would also be a headache when adding features). Or conceivably I could spin off the editorClass as a program of its own, to edit simple pictures (or complicated ones, if I get to that level :p).

Finally, I think that I could release the icnsClass (the newer version, not the current one) to the public as a library. Then developers interested in using the new 32 bit icons could use it without having to worry about learning the whole Icon Services API. In addition I already have my own functions for dealing with 32 bit icons under 8.1, so my class would provide compatibility there too (I could use a conditional statement to use the system functions on 8.5+ and my own functions for older systems, for maxium forward compatibility). Of course it would be free, perhaps even open source (although I doubt that I'd get much of a following).