Recent blog entries for Talin

New Millenium, new Job!

As of yesterday, I am an employee of Explorati, a company that is working on online social environments. I decided I was really tired of working on e-commerce. Also, about half the people working at Explorati are friends of mine. I really wanted to work at someplace where I could share a dream with the other members of the company.

Transfer modes are working in the paint widget! "Blend" and "Blur" painting work, with variable levels of transparency.Haven't done "colorize" or "rub-through" yet, but those should be pretty simple.

    Other things that got done include:
  • Optimized redrawing of images for various widgets when "imageChanged" signal is recieved
  • Finished scratchpad preview area
  • First cut at serialization of image sets

Here's a screenshot.

Got the flood fill working, I stole the algorithm from some other code I had lying around. Only took about an hour to get it working. One aspect that was a little tricky is that QPixmap doesn't have a "getPixel" method, I had to convert it into a QImage to actually test the pixel values. However, when actually drawing the pixels, I can draw onto the target pixel map directly rather than having to convert the image back to a pixel map. (Actually, I optimized it so that it draws in horizontal strips rather than one pixel at a time.)

I also made it so that you can render the flood filled pixels onto a stencil bitmap. This would allow you to "floodfill" various pixel effects, such as brighten, darken, etc.

I also added a bunch more tool buttons to the tool bar - magnify, clip brush, pen size, etc. About the only thing left to do on the paint pad is the transfer modes. Once I get that done, I can work on the rest of the application.

Qt's QPainter doesn't have a FloodFill primitive...oh well, it's not hard to write one, I have some code around here somewhere. That's somewhat surprising, I guess flood-filling isn't used much in modern apps except for paint programs.

The painting widget is looking better and better. I finished the "eyedropper" tool, and drew a bunch of icons for the various tool buttons.

I eventually want to make the paint pad widget a standalone component that other people can use. Icon editors, sprite editors, tile editors, etc...

After a frustrating day rebuilding my company's internal intranet server, I can have a relaxing evening programming... :-)

I am more and more impressed with Qt all the time. I've been writing a little mini "paint pad" widget for the Anima project. One of the primitives that I had hoped to implement eventually was rotated ellipses, in other words ellipses whose major axes are not aligned with the coordinate system. (These are especially useful in creating isometric tile sets.) Having struggled with this before, I know that there are basically three ways to draw a rotated ellipse:

  • Use a 2nd-order DDA, similar to Bresenham's algorithm, but for curves. Unfortunately, DDA's can get confused on very thin ellipses, and even go into an infinite loop.
  • Just compute the points directly using sin/cos. This works OK, but can have problems with quantization artifacts unless you get the spacing just right.
  • Approximate the ellipse with spline curves. This is probably the best overall solution.

So I noticed that Qt had a normal, axis-aligned ellipse primitive, like everyone else has. I also noticed that they also had a way to set up coordinate transformations (rotate, shear, etc.) into the QPainter object. "Big deal", I thought, "they're probably just running the input params through a transform matrix, the basic primitives are probably still axis aligned." Well, I had to check it out, and - surprise - the ellipse was actually rotated!

I've been leveraging the basic Qt drawing primitives to the max, and as a result I've been able to put together a complete painting widget in just a few days. It supports multiple brush sizes, can be extended with new stroke types and new transfer modes (such as colorize, brighten, etc.)

Since KIconEdit seems to be broken at the moment, I'm going to let the paint pad widget draw it's own icons. Gotta get that saving/loading function to work first...!

Well, I haven't touched Anima for a couple of weeks, but I'm planning on getting back to it. In the mean time I've been distracted by a number of things. First, I've been slowly working my way through my reading stack. I just finished Cryptonomicon (second reading), and the first Harry Potter novel. I've also been spending about one evening a week with Laura, someone I met at one of the Human Awareness Institute workshops.

Last weekend, I decided to finally break down and learn Python, so I spent most of Saturday and Sunday puttering around with my laptop. By the time I was finished, I had most of a working MUD (Multi-User Dungeon). This might seem like a really bad idea (there are so many MUDs out there already), but it's actually related to Anima, or more accurately it's related to Strattica, of which Anima is a prerequisite. (Strattica is my plan for an open-source 3-D strategy game engine). I suspected that working in Python would allow me to quickly prototype server implementations (more quickly than Java, in fact), and this turns out to be true. One of the basic concepts of Strattica is that the game will be massively customizable via scripts (similar to Quake-C) and embedding Python into the game engine seems like it could do the job really well.

MeV is also coming along quite nicely. I'm not directly involved in coding this, but the rest of the team has been quite busy. I've had about 4 Music-X inquiries in the last month, and I have redirected these to the MeV site.

At work, I have been learning Resin, which is a really advanced open-source/commercial servlet engine that has XSLT processing capabilities. I've created a prototype of a stylesheet which allows for special "text" tags that facilitate internationalization.

I've been working hard on Anima for the last several weeks, including a facelift on the home page. I'm working on the drag and drop stuff in the image thumbnail window, and also on the underlying undo mechanisms. I'm using the same undo strategy that I used in Deluxe Music Construction Set - a pair of bits for each deletable item, one that says that the item is "hidden" (because the user deleted it), and another which says to toggle the hidden bit when the user hits "undo". Thus, a newly added item will have hidden=false, toggle=true, which means that "undo" will cause the item to disappear. The hidden items are really deleted at the start of each new command.

I also took a day or two to learn about XSL stylesheets. Xalan is cool. I put together a little demo that generates Java source code from a DOM (similar to what JSP does), and then plugged that in to the output of Xalan. I'd like to do a JSP-style servlet engine, similar to Resin, but which runs together with Apache-JServ. If I had more time, I would do that. But I don't want to get distracted. It's very easy for me to get distracted, and when I do I tend to lose interest in a project.

I've been living a very hermit-like existence for the last month or so. The lack of interpersonal contact is really driving me nuts. Unfortunately, most of my friends seem to be out of contact much of the time (the dot-com lifestyle I guess.) I have very little in common with most of my co-workers in my day job, and I find it difficult to have a deep conversation with many of them.

I'm happy because last week I gave away two of my open source projects. Both of these projects had been languishing for a while because I had lost interest in them, and I'm glad that I have found competent people who are interested in maintaining them.

The first project was ScanDoc, which is a documentation generator, similar to JavaDoc, for C++ programs. The main difference between ScanDoc and other generators such as KDoc and Doc++ is that ScanDoc is themable. That is, there are template files which determine which output file are created and how they are formatted.

I realized that I was no longer interested in maintaining ScanDoc, because most of my programming these days is either in Java or Perl. The only C++ programming I do is for KDE, which has it's own doc generator. So I emailed all of the people who had sent me feedback recently and told them I was no longer interested in maintaining the program and that if any one of them wanted to take over, I would be happy to let them do so.

I got a response from James Dean Palmer offering to take over the project. I took a look at his web page and his projects, and I decided that he would be an excellent choice for the position, so I said "OK, it's yours". Within a day or two, James had created a SourceForge project for ScanDoc, including a beautiful web page and spiffy logo. In addition, he's been sending out updates every week or so as people send in bug fixes. I'm really happy to have the project in such capable hands.

The other project I gave away was MeV, a professional MIDI sequencer I had written for the BeOS, but had never released. I had been looking for someone to take this over for a while. I had recieved a number of offers, but in each case I didn't feel that the person was skilled enough to handle the project. There was a short period where it was actually being worked on by a couple of engineers from Be, but they found that they weren't able to make time to work on it with all of their other tasks.

I recently got an offer from a team or programmers who had worked on a number of other Be related applications. So after a bit of procrastinating, I sent them the code, which is now on SourceForge. You can find the MeV project here.

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!