Tuesday, April 28, 2009

Making GMime Even More Awesome

I've started working on GMime 2.6, which unfortunately will need to break API with 2.4 in order to achieve the next level of awesome.

If you use GMime (or are thinking of using it) in your project and have some suggestions on how GMime can improve, don't hesitate to fire an email off to gmime-devel-list@lists.gnome.org (preferably after subscribing to the mailing-list first).

These are my current plans:

  • Replace all uses of g_signals with my own event stuff. None of this needs to be public and my events are a lot more performant. [ DONE ]
  • Need to add a Changed event to GMimeHeaderList so that GMimeMessage can listen to changes in the toplevel mime_part's headers. When they change, we need to unset the cached header stream on the GMimeMessage. (see the "Note:" comments in message_write_to_stream and message_get_headers, while this hack works, it'd be nicer if we did it based on event callbacks)
  • Get rid of GMimeSession and replace it with GMimePassphraseRequestFunc or something. See GpgMe's passphrase request callback signature for ideas. [ DONE ]
  • Consider optionally using GpgMe so that we can support S/MIME?
  • Consider GCancellable and GError for GMimeStreams and GMimeParser
  • Add GIO-based GMimeStream and bump glib dep to 2.16 [ DONE ]
  • Add a g_mime_part_get_best_content_encoding()? [ DONE ]
  • Rename GMimeBestEncoding enum to GMimeEncodingConstraint? This might be a better name for the enum to reflect what it's actually meant for. Maybe also move it from gmime-filter-best.h to gmime-encodings.h?
  • How about a g_mime_part_get_best_charset()? This one could be awkward since it depends on the content being UTF-8 text
  • Should either rename g_mime_filter_best_encoding() to get_encoding() or else make sure that GMime.metadata 'fixes' the method name to be GetEncoding so that it will appear as a C# property getter.

Saturday, April 4, 2009

Follow me on twitter

Over the past few months I'm having an even harder time motivating myself to actually make blog posts due to the convenience of microblogging on twitter.com, so this is just a note to say that if you are interested in the things I do or say, you might want to consider following me on twitter.

Thursday, April 2, 2009

Building GMime in Visual Studio

Installing the Necessary Dependencies

First, install GNU's iconv library for Windows. You can get a nice msi installer from http://gnuwin32.sourceforge.net/packages/libiconv.htm. Unfortunately, they only offer a Win32 installer, so hopefully that's the platform you intend to target.

Next, you'll want to grab the GLib headers and libraries for Windows. The easiest way to do that is to go to http://www.gtk.org/download.html and download the All-in-One pre-built bundle for Win32. Once downloaded, extract the zip file (the docs suggest not using WinZip due to a bug) and place them wherever you want (I put mine into C:\Users\jeff\Documents).

Configuring Visual Studio

Now that the libiconv and glib headers/libraries are installed, you'll want to configure Visual Studio to know where to find those headers and libraries.

First, go to the Tools menu and select Options...:

In the Options dialog, expand the Projects and Solutions tree item and then select VC++ Directories.

Make sure Win32 is selected in the Platform option menu and then select Executable files under Show directories for:, like so:

Scroll to the bottom of the listbox and add the bin paths for your installed libiconv and Gtk+ bundle just like in the above screenshot.

After you've added the bin paths, you'll need to add the #include paths. Select Include files under Show directories for: and, like you did for the Executable paths you added above, add the paths to the include files.

Next, you'll need to ad the library paths. Under Show directories for:, select Library files and add the appropriate paths to the bottom of the list.

And that's it! You are now ready to start building GMime!

Note: I've been using Microsoft Visual C++ 2008 Express Edition which you can download for free from Microsoft.

Tuesday, March 31, 2009

GMime Ported to Windows

The other day someone asked me about GMime on Windows and I didn't have anything to tell her other than that I thought people had built it successfully on Windows but beyond that, I didn't have any sort of VS project files or anything.

Then, last night, she poked me again asking for advice about some of the problems she was having building on Windows (which were mostly removing extraneous unistd.h includes from files that didn't need them and dropping source files that required them).

After a short while of back and forth, I decided I'd just boot into Windows myself and she helped me get my system setup (installing GNU Libiconv, grabbing the Gtk+ Windows dev packages, configuring VS to know where to look for those headers/libs, etc) so that I could more easily get instant feedback as to whether my source changes fixed the compile errors.

After a few hours of #include fixage and slight reworkings of some unix-specific code, we had a successful build of GMime.dll, woohoo!

Wednesday, March 11, 2009

Taking Over the World

I've just been informed that Moonlight has made it into the following distributions: openSUSE (obviously), Mandriva, Ubuntu, Debian, Gentoo, and FreeBSD.

These are exciting times. One of the things that keeps me hacking on Free Software is the joy I feel when other people use my software because I know I'm helping to improve their Linux computing experience, even if only a little bit ;-)

On that note, Moonlight 1.0.1 has just been released the other day with fixes for the bugs people reported to us about the 1.0.0 release.

Jo Shields has also done the work to port Moonlight to ARM:

Update: Dieter has just informed me that Arch Linux also provides Moonlight packages in their distribution! Awesome, guys!

Saturday, February 28, 2009

Text Layout Engines

As many of my loyal followers know, I wrote a really fast text layout engine for Moonlight 1.0 which was able to layout text in more-or-less a single pass over the string. Hard to do better than that, especially with my superbly (I'm allowed to stroke my own ego, right?) designed font/glyph caches.

That said, the code had also been superbly disgusting and unmaintainable. Made worse when I had to add hacks to render text selection (Silverlight 1.0's TextBlock is like a GtkLabel in that it just renders text, but Silverlight 2.0's TextBox supports editing and selection and so is therefor more akin to a multi-line GtkEntry widget).

Well, Thursday night, as I was watching House on Hulu, I had one of those "House moments" where he suddenly realizes what the patient is suffering from and how to solve the problem (usually when his friend, Wilson, is talking to him about something random).

I spent all day yesterday (and I mean all day, until 11pm last night) putting together my thoughts for a new design and working out the details and I think I now have a vastly improved solution that not only uses less memory in all but the pathological cases (I now use a UTF-8 string instead of a UCS4 string), but also doesn't require:

  • a pass over the text to break on CR/LF to construct a list of text runs which were what the old TextLayout engine I wrote used instead of a char* (because the layout engine now handles CR/LFs)
  • a whole new set of text runs every time selection boundaries change in a TextBox (because selection is no longer represented by text runs)

Of course, the same brilliance of the old design still apply: no need to re-layout when most text properties (underline, foreground, background, etc) change (obviously we still have to re-layout if font properties change because they change the metrics).

With my new design, my TextLayout class has a Select() method which allows the consumer to change the selected region of text. When you change the selection, my new logic can simply clear the cached glyph clusters for the affected area(s).

A "glyph cluster" is a cached (sub)run of glyphs in a particular text run. A "text run" is a substring of text that share all the same text attributes which does not span across line boundaries.

To break it down, a layout contains a list of lines. Each line contains a list of runs. Each run contains a list of glyph clusters.

Normally, a run will consist of only a single glyph cluster unless it overlaps the selection.

For example, if the first half of the run is within the selection, then the run will contain 2 glyph clusters (one for the selected portion and one for the non-selected portion). However, if the selection is fully contained within a single run but doesn't span the entire run, then it's possible to have up to 3 glyph clusters for that run: pre-selection, selection, post-selection.

The brilliance of doing it this way is that it simplifies keeping track of kerning between selected regions, so that as you drag your selection across some text, the text following your mouse cursor doesn't appear to "jump" to the left or right as you move between characters that are kerned.

Saturday, February 14, 2009

More Exciting Updates on Mono/Android

Looks like Koushik Dutta has been kicking butt getting Mono onto Google's Android platform:

Keep up the awesome hacking, Koushik!

Also of interest is his article on why JNI sucks compared to doing the same thing in .NET: JNI in Android (and a foreword about why JNI sucks)

I never actually used JNI back when I was doing Java development in school, so when people told me it sucked I just took their word for it, but always wondered just how bad it was. Now I know. All I can say is: Ugh.

Hopefully the Java community replaces JNI with something as clean and elegant as what we find in .NET.

Code Snippet Licensing

All code posted to this blog is licensed under the MIT/X11 license unless otherwise stated in the post itself.