PDF->PS is SLOW in Gutsy

February 14th, 2008

Dear Lazyweb,

I've been having a problem on my Ubuntu Gutsy systems (lock it up, peanut gallery). Basically, if trying to print a PDF that contains any images at all, either from evince or using pdf2ps, it takes forever. I'm talking on the order of 10 minutes per copy; even if it's multiple copies of a single page, one will come out around every 10 minutes. Granted, this is a parallel printer as opposed to USB, but even it shouldn't be so slow.

Now, I don't print a lot, but when I need to, it's definitely annoying. I've confirmed with friends that this happens on other Ubuntu Gutsy systems as well.

I did some basic testing, and I suspect that Ghostscript (gs) is, in the conversion process, making any images just too high of resolution in the PS file. Behold:
jtickle@jtickle-ess:~/Desktop$ pdf2ps python_flier.pdf python_flier.ps
jtickle@jtickle-ess:~/Desktop$ ls -lh |grep python
-rw-r--r--  1 jtickle jtickle 242K 2007-10-16 10:15 python_flier.pdf
-rw-r--r--  1 jtickle jtickle  15M 2008-02-14 10:02 python_flier.ps

Wow, a 242K PDF becomes a 15M PS? That can't be right!

I'm pretty sure both 'pdf2ps' and 'evince' use 'gs' to convert PDF to PS. A quick look over the man page for 'gs' reveals a resolution option. Let's try 72x72:

jtickle@jtickle-ess:~/Desktop$ pdf2ps -r72xz72 python_flier.pdf python_flier.ps
jtickle@jtickle-ess:~/Desktop$ ls -lh |grep python
-rw-r--r--  1 jtickle jtickle 242K 2007-10-16 10:15 python_flier.pdf
-rw-r--r--  1 jtickle jtickle 864K 2008-02-14 10:11 python_flier.ps

Still not optimal, but much better, and only takes ~1 minute to come out of the printer. On the other hand, the print looks TERRIBLE. At least when it takes 10 minutes, the print doesn't look bad.

There's a bunch of fun-looking stuff in /usr/share/ghostscript/8.61/ that I don't understand a word of but looks like it could have something to do with the problem.

Does anyone have any idea what sort of options should be passed to gs to not make a ridiculously huge PS file but also have it not look like butt? Or if different resources should be in /usr/share/ghostscript?

Top 10 Reasons why Virtual Paper Lives

January 20th, 2008

So every now and then, I hit up Digg for a few minutes worth of brain cell slaughter. That's truly all it is, because for the most part, it's silly pictures, dumb videos (except for the one where a guy makes his own vacuum tubes), and of course, top N lists, where N is {3, 5, 10, 20, 21, and pretty much the set of all natural numbers}. I don't have any dumb videos to show, and the picture isn't all that silly, but it does show the Handwriting widget embedded inside a Tomboy note. And as for the top 10 list...

10. I'd like to apologize to everyone that I haven't spoken to already involved with the Mono Project and the 2007 Google Summer of Code. I recently looked through the blog and realized that a WHOLE LOT of work was done *before* the Summer of Code even started. And then, the day it starts... nothing, until now. This certainly wasn't on purpose, and what it comes down to is that a lot of stuff came down on me at exactly the same time. I was able to get a little hacking done over the course of the summer, but not much.

9. I now work full time for Appalachian State University, home of the 3-time NCAA FCS National Champion Mountaineers. But my job has absolutely nothing to do with football (their website isn't even hosted on campus). I am now the Operations and Systems Analyst for Electronic Student Services, and take care of servers that host around 60% of campus web traffic and our student medical records, in addition to taking care of our home-grown Housing Management and Extra-Curricular Transcript softwares. We also develop and maintain the phpWebSite Content Management System, which is Free software. Check it out. The only reason I'm still on WordPress is that I haven't gotten around to writing the WP->phpWS importer yet.

8. Having a full-time position has taught me one thing: Despite loving what I do, when I get home from work, I'm usually quite ready to go out and do something else. Hence, the apparent death of Virtual Paper. It's really not a bad gig, though. I get to work on Free software all day, and all of our office machines in the department and the most of the servers themselves are Linux. As a professional sysadmin who does unfortunately have to deal with one Windows server... seriously, don't use Windows as a server. On the desktop... eh... but as a server, what a load of crap. PS, the views expressed in this blog do not necessarily reflect the views held by Appalachian State University or its employees, or the State of North Carolina.

7. I don't have a degree, but am still working on a BS in CS. Staff get a free class per semester (and one summer class), and so long as the supervisor approves (he does), we can take that time out of work without making it up. Pretty sweet gig. Was going to graduate this December, but it looks like another 3-4 years. Honestly, the one class per semester works a lot better for me anyway.

6. My new boss apparently reads my blog, or rather, read it through once and bugged me about why the hell I hadn't touched it in months. He's pretty much the most amazing boss anyone could have, and if I hadn't already known him and that I would have enjoyed being his peon, I don't think I would have taken the job. Also, he has little control over what I get paid, so this is all genuine. ;-)

5. The idea for Virtual Paper came to me after the 2006 Boston GNOME Summit. There, I met Boyd Timothy and a few other Tomboy hackers. I also hadn't owned a Tablet PC for very long at that time, and was enjoying getting to know about all the cool stuff it could do. I had a thought... what if you could draw a quick sketch or diagram right inline with your note about something?

4. At the 2007 Boston GNOME Summit, I met up with Boyd again. I pretty much spent the whole time trying to get what I had done on Virtual Paper embedded into a Tomboy note. Boyd helped significantly, and we were able to solve some more general problems in Tomboy with embedding images and widgets in the notes' TextView widget. I was all excited for a few days even after I got back in town, and then work took over my life again.

3. I think I'm finally starting to find a sort of balance and get used to the new lifestyle. Also, I've had an urge building up inside me as well as encouragement from friends to finish what I started. Not that software is ever finished, mind you, but at least work on it and be proud of it.

2. Virtual Paper is now in GNOME SVN as part of the Tomboy project, the Sketching Add-in. You will notice a severe regression in features; they're all still there, but they're not exposed in the UI yet. Any ideas? Also, at the moment, sketches do not save or reload as you close and open notes, thereby making them pretty useless. I need to talk to Boyd tomorrow about where they should be saved. But anyway, look at the pretty screenshot:

Tomboy Sketching Addin

Also, you can check it out for yourself:

svn co http://svn.gnome.org/svn/tomboy/trunk tomboy

Sketching is not enabled by default; you will need to tell configure that you want it:

./autogen.sh --prefix=/usr --enable-sketching=yes

Update 2007-01-21: Forgot to mention; to add the widget into a note, from within any open note, click the Tools button and mash 'Add a sketch'. There is a default sized hard-coded, and you can't change that yet without recompiling. Perhaps I should add this to configure:

./configure --enable-sketching=yes --sketch-height=100 --sketch-width=100

Ok, seriously, just kidding there. We'll figure something out; like I said, it's pretty rough at the moment.

1. YOU can now benefit from it and contribute to it! The code is out there and public and readily accessible (see above). When I work on it, I'm working on it out of Tomboy's checkout, so any changes I make should make it in pretty quickly. Bugs should be filed against Tomboy in GNOME Bugzilla. I do still plan to release a standalone version, but for now I'm focusing on making the Tomboy addin useful, since I feel that it will benefit more people more quickly than focusing on a separate application.

Carelessness Kills

June 4th, 2007

Carelessness can kill efficiency. I mentioned in my last post that a Undo or Redo operation, after you get more than a few strokes on the page, takes quite a long time, upwards of a second or so. I immediately knew what the problem was: when I implemented Undo and Redo, they turned out to be so ridiculously simple that when they just worked I said "beer time" and that was that. They needed some more work, though.

Whenever Virtual Paper has to redraw the entire screen, it has to cycle through all of the strokes that have been drawn, and then re-draw them in order, including (now) any gradients[1] involved. Here's the old, simple Undo code, and I won't post Redo since it's in SVN and is the same thing with a -- instead of a ++:

public void Undo()
{
    if(CanUndo) {
        undo++;
        QueueDraw();
    }
}

QueueDraw causes the entire canvas to be redrawn. This is inefficient because you don't need to draw the whole thing. The first problem I had to solve, and I haven't yet blogged on the intricacies of this problem that became very complex, was the fact that drawing the entire canvas each time a new stroke was drawn just took way too long after more than a very few strokes. Anyway, because that had already been solved, fixing Undo's inefficiency was still very simple:

public void Undo()
{
    if(CanUndo) {
        undo++;
 
        Stroke undoneStroke = strokes[strokes.Count - undo];
        QueuePaddedDrawArea(undoneStroke);
    }
}

A few more lines of code, and now you can write on that paper all day, click "undo," and it immediately deletes the last continuous stroke that you drew. Redo is almost identical in terms of code and performance improvement.

Other New Things

QueuePaddedDrawArea: There used to be some tiny glitches when drawing a stroke that were eluding me. It didn't always happen, but sometimes there would be a pixel or so missing out of the side of a stroke, and any total redraw would fix them, so I figured it had to do with clipping. Because there is a default line width of 3 pixels and because the boundaries of the stroke passed to Undo and Redo are in the middle of that 3px line, clicking Undo and *not* redrawing the whole window caused certain edges to remain, at least until the entire thing was redrawn. QueuePaddedDrawArea adds a padding of the current line width to the requested QueueDrawArea operation, which simultaneously solved the undo problem and the weird little glitches.

Paper Styles: are what I'm currently working on. It's turning out to take longer than expected, since I hard-coded a lot of reliance on the one style of notebook paper. Abstracting the background drawing out is looking to be time-consuming, but overall better for the quality of the code anyway. More on this as it's available.

Summer of Code: It officially started last week, so you should start to see more updates than usual on Virtual Paper. If you don't, please give me a swift kick in my ass to get me back on it so's I can get my much-needed dollars.

Subversion: Virtual Paper is being temporarily moved out of Ticklish SVN, partly so it can live with the other Mono SoC projects, and partly so I don't have to bother with WebDAV, which unfortunately doesn't play so nicely with Lighttpd. Anyway, if you want to get a more-or-less up-to-date copy of Virtual Paper, it is available from the mono-soc-207 project on Google Code. Here's a direct checout command you can use:

svn checkout http://mono-soc-2007.googlecode.com/svn/trunk/jeff/ virtual-paper-soc

Toshiba Tablet in Playboy June 2007: I indeed get it for the pretty girls, but also enjoy the articles, plus they give a great deal to college kids in hopes of getting us hooked for life. Anyway, on page 44 of this month's issue, they mention the Toshiba Portege R400, which is way nicer than my Portege M200. Somehow, in the description, they missed over the fact that the amazing Virtual Paper is being developed on a much older model of this fine hybrid tablet. I shall have to write them a letter.

[1]: That reminds me, I sort of hacked around my gradient problem. I was talking to Brad on IRC about it, just fleshing the problem out to another person and lamenting on how there doesn't seem to be a solution, when suddenly it hit me. I already have to apply a different color to each stroke section anyway to get the current non-gradient transition between colors. I also know that if you apply a linear gradient to a single line in Cairo, it works like you'd expect. So, for each line segment of a stroke, it takes the starting color and the ending color and makes a new gradient on that line. I haven't done any specific performance testing, but a quick bit of writing didn't feel any slower, and that's what's important. Also, Aaron is amazing at finding ways to break your software, and he only found a few small issues last time I saw him, none of which had to do with the new gradient code. So, that problem is more or less solved, although I feel like Cairo should have a better internal way to take care of that.

Which Device is Really a Pen?!

May 24th, 2007

Seriously, this makes my hand hurt like whoa.

[1]: http://abock.org/2007/05/23/surfing-the-tubes/

So, this is annoying. Ever since I figured out how to get extended data from a stylus (pressure, tilt, etc) and actually implemented it, Virtual Paper has crashed due to an IndexOutOfRangeException if I try to use the actual mouse on it. At first I thought this had something to do with a button press event happening when using the mouse and not happening when using the stylus, or something. Whatever it was, I was more excited about getting pressure data than fixing this little bug, which seemed straightforward at the time.

This morning I decided to solve the problem real quick before heading over to my part time job at the university. As I should have expected, the problem has turned out to not be "real quick" at all. Now that I've gotten around to disabling that damned javascript rich text editor thing on WordPress, I can post some appropriately formatted code. This code is what decides to do with motion notification. If the motion comes from an InputSource.Pen, it makes a black Cairo.Color using the Pressure axis for an alpha channel. If it's not from a pen but is from a Button1, then we just put down 1.0 for the alpha, which is totally opaque. And finally, if it's either an InputSource.Eraser or from Button3, we make a big ol' mark that's the color of the current paper.

if(ev.Device.Source == InputSource.Pen) {
    strokeContinue(axes[0], axes[1], new Cairo.Color(0.0,0.0,0.0,axes[2]));
} else if(mask == ModifierType.Button1Mask) {
    strokeContinue(axes[0], axes[1], new Cairo.Color(0.0,0.0,0.0,1.0));
} else if(ev.Device.Source == InputSource.Eraser ||
          mask == ModifierType.Button3Mask) {
    strokeContinue(axes[0], axes[1], paperColor);
} else {
    // Unknown Button
}

Turns out, the problem is on line two above. If you click on the Handwriting widget with the regular mouse, ev.Device.Source is, in fact, InputSource.Pen! WTF? What's causing the IndexOutOfRangeException is the fact that the regular mouse does not have an axis[2], even though it is an InputSource.Pen.

Here's my new-and-improved device configuration code that picks which devices I want to hear from, with a Console.WriteLine added to help me get to the bottom of this:

foreach(Device d in GdkWindow.Display.ListDevices()) {
    Console.WriteLine("Device: {0}tSource: {1}t" +
            "Axes: {2}", d.Name, d.Source, d.NumAxes);
    if(((d.Source == InputSource.Pen ||
         d.Source == InputSource.Eraser) &&
        d.NumAxes > 2) ||
       d.Source == InputSource.Mouse) {
        d.SetMode(InputMode.Screen);
    }
}

And here is the output:

Device: eraser          Source: Eraser  Axes: 6
Device: stylus          Source: Pen     Axes: 6
Device: cursor          Source: Cursor  Axes: 6
Device: Synaptics       Source: Pen     Axes: 2
Device: Core Pointer    Source: Mouse   Axes: 2

I added some spaces in there to make it look nicer. As you can see: Synaptics, my touchpad device, shows up as a Pen. So, the other changes in the above configuration code are there to make sure any Pen or Eraser has more than two axes, and accept a mouse regardless.

Now drawing with the mouse doesn't crash it... it just doesn't work!! Yep, the Core Pointer now refuses to send a Motion Notify event. I tried hooking up a USB mouse and found an even more puzzling bug; it doesn't show up at all. It doesn't add anything to the above list of devices (didn't figure it would), and more bizaarely, it does not send any motion notify or button events to the widget, even if all the conditionals are removed and every device is configured as screen relative. Am I looking in the wrong place here? I think this issue requires a better understanding of X, which I do not have much of. Any input would be appreciated.

For now, this code in the motion notify handler does a good enough job, but it still doesn't solve the problem of an external mouse, and it feels kind of hackish:

if(ev.Device.Source == InputSource.Pen) {
    if(ev.Device.NumAxes > 2) {
        strokeContinue(axes[0], axes[1], new Cairo.Color(0.0,0.0,0.0,axes[2]));
    } else {
        strokeContinue(axes[0], axes[1], new Cairo.Color(0.0,0.0,0.0,1.0));
    }
} else if(ev.Device.Source == InputSource.Eraser ||
          mask == ModifierType.Button3Mask) {
    strokeContinue(axes[0], axes[1], paperColor);
} else {
    // Unknown Button
}

Cairo: Stroke Gradients

May 23rd, 2007

My last post was written rather hastily, and the Lazy Web indeed noticed some silly mistakes; for one thing, the || operator makes 'if' statements much smaller, and the code that configures your GdkWindow.Devices should be handled on Realize, not on Configure.

I was also rather ambiguous as to what I meant about applying a gradient to a stroke (as opposed to a fill). Yes, it is possible, and quite straightforward:

Linear Gradient on Four Line Segments

Code for that is available here.

Cairo gives you a radial gradient and a linear gradient for free. The gradient, however, is applied to the image as a whole. What I want to be able to do is draw a stroke and have the gradient be applied along the path of the stroke itself, rather than what you see in the above screenshot. So, if I set a black color stop at 0.0 and a red color stop at 1.0 (as I did above), I would want the black to start at the top-left corner of the square, and change to red along the path itself, ending as red back where it started in the top-left. If I fill that square using the same linear gradient, you can see what is actually happening:

Linear Gradient on a Square

Anyway, just because I wanted to see pressure-sensitive results in Virtual Paper, I reworked the stroke drawing code to stroke for each line segment with the color (pressure) of that line segment. It actually looks really nice, and doesn't slow down like I was afraid it would:

Virtual Paper: Now, with Pressure Sensitivity!

This screenshot shows why I'd like to be able to apply a gradient to a stroke. Fortunately, it also shows that the results without a gradient are still pretty spectacular:

Why I want Stroke Gradients and Bezier Curves

Since it looks decent without gradients and the performance doesn't take any noticeable hit with extra calls to Stroke() (and am I insane for thinking there would be a noticeable hit?), this one will be on the back burner for a little while.  It'll become important again for things like SVG export, since you want to actually have a scalable vector graphic and not a bunch of line segments that don't flow with each other.

XInput VI: Return of the Jedi

May 20th, 2007

That was easy enough, just not very well documented. You have to, for your Gdk.Window, tell it what devices to listen from. By default you get the CorePointer, you have to do more work if you want Pen and Eraser. Also, this is how you specify Screen-relative or Window-relative.

For those not familiar with Wacom devices: if you are working in a program such as The GIMP, what you probably want is the ability to use the full range of your wacom device as a canvas, instead of being limited to the area where your drawing window would be. So, you set the device to be window-relative instead of screen relative, and bam. That's not useful for a TabletPC where you're literally drawing with your display in the background, so we'll assume screen-relative for Virtual Paper.

Here's the code that makes it work, and it's executed upon Configure event. DEAR LAZYWEB: is there a better place I should put this code instead of the confgure event? It has to happen *after* the window is shown, but I don't think it needs to happen more than once.

protected void Configured(object o, ConfigureEventArgs args)
{
foreach(Device d in GdkWindow.Display.ListDevices()) {
if(d.Source == InputSource.Pen) {
d.SetMode(InputMode.Screen);
} else if(d.Source == InputSource.Eraser) {
d.SetMode(InputMode.Screen);
}
}
}

So, now my stroke data has proper pressure information stored. The next problem is that there doesn't seem to be a way to do gradients on strokes in Cairo. This isn't so much a problem as an inconvenience; I'd like to have a nice smooth transition between pressures, and I'd like to use "MoveTo" and "LineTo" appropriately instead of stroking for each little segment of a line.

Fun with XInput

May 1st, 2007

I was sick all last night and didn't sleep well, so I ended up sleeping most of the morning and now it's 2:30 AM and I can't get to sleep.

Hooray Summer!!!

So anyway, I decided to tackle a bit of GDK stuff tonight, that is to say, detecting pressure from a movement event. I wrote up a quick little program that is basically just a widget and a button; the widget happens to be a Gtk.DrawingArea because it is what I was thinking about. Here is the juicy, testing part of the code:

public void HandleMotionNotify(object o, MotionNotifyEventArgs args)
{
double[] axes;
ModifierType mask;
int i = 0;

if(args.Event.IsHint) {
args.Event.Device.GetState(GdkWindow, out axes, out mask);
} else {
axes = args.Event.Axes;
mask = args.Event.State;
}

Console.WriteLine("mask: {0}", mask);
if(axes == null) {  // For some reason, it is sometimes.
Console.WriteLine("axes: null");
} else {
foreach(double axis in axes) {
Console.WriteLine("axes[{0}]: {1}", i++, axis);
}
}
}

Update: Sorry for the formatting there... I can't seem to get WordPress to shut up about it, so sorry, no indents. Download the code if you'd like to see it a little cleaner.

What's really important here is that double[] axes. That is where all detected axis information SHOULD go... and indeed, X and Y show up as expected, but only if hinting is on. If EventMask.PointerMotionHintMask is NOT set, the line axes = args.Event.Axes returns null instead of an array of double. In either case, axes[2] is never set, which should be pressure. 3 and 4, I believe, are tilt, and there is more than that available depending on the device.

I tested this out on both my Synaptics touchpad and the Wacom tablet device; both returned identical results, which makes me think either I'm doing something wrong in code, or my X configuration is wrong. I doubt it's the X configuration, simply because pressure sensitivity works like a champ in The Gimp:

Pressure Sensitivity Working in the Gimp

Which leaves us with my code for the test program, and I'm a little stuck here. Earlier, I mentioned a button in my GUI, and I added it because the scribble-xinput demo in the gtk+ sources had it. Clicking it opens a Gtk.InputDialog. It would seem that this dialog allows you to configure your X inputs, including reassigning which index of the double[] axes relates to which axis. Unfortunately, it doesn't work; not in the Gimp, not in the scribble-xinput demo, and not in my GTK#/GDK# test program. I haven't been able to try it out on any box other than my tablet; on the desktop, it just brings up a dialog that says "No extended input devices," which is true. Here's what I get when I try to change any of the settings on my tablet:

(XinputTesting.exe:20903): Gtk-CRITICAL **: gtk_scrolled_window_add: assertion `bin->child == NULL' failed
(XinputTesting.exe:20903): Gtk-CRITICAL **: gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
(XinputTesting.exe:20903): Gdk-CRITICAL **: gdk_drawable_get_colormap: assertion `GDK_IS_DRAWABLE (drawable)' failed
(XinputTesting.exe:20903): Gdk-CRITICAL **: gdk_window_set_background: assertion `GDK_IS_WINDOW (window)' failed
(XinputTesting.exe:20903): Gtk-CRITICAL **: gtk_scrolled_window_add: assertion `bin->child == NULL' failed
(XinputTesting.exe:20903): Gtk-CRITICAL **: gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
(XinputTesting.exe:20903): Gdk-CRITICAL **: gdk_drawable_get_colormap: assertion `GDK_IS_DRAWABLE (drawable)' failed
(XinputTesting.exe:20903): Gdk-CRITICAL **: gdk_window_set_background: assertion `GDK_IS_WINDOW (window)' failed

So, the problem isn't actually with the widget's functionality, since if it actually opens on one of the Tablet devices, it shows all of the axes as I would expect them to be shown; the problem is just something internally about how it updates the interface. I suspect I should be able to get configuration information from this and use it in the test program to say "Yes, I actually want Pressure data, and Tilt data if available, etc." I don't know how to do that. Anyone? This is what the dialog looks like:

Gtk.InputDialog
In other news, I leaned back in my cheap office chair the other day and this happened, and now it lives under the kitchen table until I convince myself I'm not going to find someone to weld it back together:

Broken Office Chair

Fortunately the fold-out that I've found to replace it isn't all that uncomfortable and tends to support posture surprisingly well at the ol' desk:

New Office Chair

Virtual Paper Accepted as SoC Project!

April 12th, 2007

Woot! I was planning to dabble on it a bit over the summer anyway, but this just seals the deal, and for more than just dabbling. Expect, in the next few months, to see:

  • A cleaned-up, bug-fixed, fully-featured Virtual Paper widget for GTK#
  • A Tomboy plugin that utilizes this widget as intuitively as possible

If there's any extra time, I'll start hacking on handwriting recognition, but I'm leaving that off of the list of expected deliverables for now.

Mike Kestner has been assigned as my mentor, and I'm looking forward to working with him.

So, a big thank you to Google and the Mono project! Congrats to all the other accepted applicants!

More Info

Virtual Paper for Your GNOME Tablet!

February 28th, 2007

That's right... Just download VirtualPaper 0.1 and install it on your Tablet PC, and you'll never have to buy those $0.50 packs of notebook paper at Wal-Mart again!

Virtual Paper Smaller Screenshot

So here's the story. Around Christmas time, over break, I found out that you can get pressure information from your Wacom tablet (which is the device used in the Toshiba m200's tablet display). After hand-drawing pretty pressure-sensitive strokes in The GIMP, I became fascinated and started trying to capture this information myself in a handwriting program. Also, as mentioned before, I'm interested in adding handwriting support to Tomboy for embedded hand-drawn diagrams, such as would be useful when taking notes in a class or jotting down a rough map or something like that.

I previously mentioned that Tomboy could use a handwriting feature. It's something I'm working on, among other things. There's a big gaping hole in the Linux desktop where Tablet PC support should be, and I'm quite interested in filling this gap. Things like nonintrusive and integrated handwriting support in common applications. Windows Tablet XP absolutely has us beat at usability when the keyboard is inconvenient.

Ironically, I never did figure out how to get pressure information from managed code, and the priority on this has been knocked back a bit as I've found myself more interested in actually making this package useful as a common tablet tool. I didn't at first intend for this to compete with projects such as Gournal, but after making the widget, putting a front-end around it just seemed obvious, and one thing lead to another. But honestly that's not the end goal of this project; I'd rather make a compact widget that can be used in other applications for simple handwriting integration.

Full Screen Virtual Paper

Software Requirements

There aren't really any special hardware requirements, but if you don't have either a Tablet PC or some other method of handwriting input (such as a Wacom tablet), then there really isn't much point. I certainly won't stop you from downloading it anyway and having a look-see; it works with your mouse too!

Download

I've been putting off releasing it due to some little issues it has, documented below. But, "release early and often", right? So without further ado, here's the release! Let me know what you think. It's my first autotools application, so in addition to program bugs, also let me know if you find something wrong building it on your distro. It builds fine on my Ubuntu Edgy and Feisty boxen.

Download virtualpaper-0.1.tar.gz

Known Bugs

  • While erasing with the "eraser" end of your stylus (or your right mouse button) works, it acts more like white-out, erasing the rulings on the page as well. This has to do with how strokes are stored internally, and I am working on a fix for it.
  • If you erase on "white" paper and then change the paper color to "yellow" or vice verca, your previous eraser marks remain the same color, so you'll have white erasings on a yellow paper. Again, much like white-out (and yellow-out).
  • Paper and Pen colors are not at all versatile. This is just a UI issue I haven't worked on yet.
  • The UI is a little less than perfect. The "paper" options are going to be abstracted out because I want to be able to have different paper modes, which may correspond to types of handwriting recognition. Imagine notebook paper recognizing letters and numbers, graph paper recognizing straight lines and basic shapes, and music paper recognizing hand-drawn music notes. That sort of thing. The current background options are sort of just for fun, and will be replaced by something better.
  • The code needs some cleaning up. I'm not making proper use of namespaces, and could probably stand to stare at the .NET style guide for a few weeks.
  • Battery life is a big issue. Virtual Paper doesn't, as far as I can tell, strain your battery more than any other average application, but it does require X and probably a backlight on your LCD. So if anyone out there has a bugfix that will give my laptop unlimited power without being plugged in, I'm all ears.

Thanks for checking this out! I hope you enjoy!

It's Over! and, Music!

December 5th, 2006

Whew. That was the most stressful semester ever. Once again, however, rounded off by a pair of awesome Higher Ground concerts.

Food for thought, provided to us by Jerry Holkins, whom you may know better as Tycho, regarding portable music devices:

"These devices are just repositories for stolen music, and they all know it," UMG chairman/CEO Doug Morris says. "So it's time to get paid for it."

The other quote from them (that I'm having trouble finding, now) talks about how, since the Zune is based on "a foundation of music," they deserve to get pizaid. So you need to understand that these people are really and truly crazy. They imagine that their industry is not, as you might have thought previously, merely a conduit for a specific type of product. Rather, they believe that their industry is the avatar of music itself, and flush with this knowledge they gesture from their litter, seeking tribute.

So, that means since I'm a musician, I should be getting a check from UMG any day now, right? :-D

/me sues for not being properly represented by my avatar.