One of the more interesting applications of WPFs powerful graphics capabilities, at least to me, is it’s use in creating a powerful image manipulation and general purpose drawing application. I have been working on an application like this myself. One of the first features I wanted to implement was a basic version of the paintbrush tool like that found in Photoshop. Microsoft has an example project that supports multi-touch painting on their website. One problem with this example, however, is that it is terribly, terribly slow. Eventually, the app slows to a crawl as the complexity of drawings on the screen increase. This was a huge problem when you’re trying to make a high performance application. So, I set about trying to see what I could do to fix it.
The answer itself lies in using a StreamGeometry instead of a PathGeometry. The PathGeometry actually contains a StreamGeometry inside, but it also has other bits that make it’s performance sub-par compared to a StreamGeometry. The problem with using a StreamGeometry is that it can’t render while you have it’s DrawingContext open. What this means is that you either can choose to wait until mouse / touch up to close the stroke and render the entire thing at once, or you can break the strokes down into much smaller pieces by creating a new one on mouse / touch move. I decided to go with the second option because I didn’t particularly like not knowing what I was drawing until I lifted my finger / mouse button.
At this point, I had a performant drawing application that suffered from no visual slowdowns no matter how much was drawn on the screen, but there was another issue. This issue is that there were gaps between the individual strokes and they looked awful. I didn’t right away know what was causing them, so I decided to try a few different things. My first course of action was to try adding multiple points to a list and draw all of the points in the list at once, rather than going by two points at a time. So I tested by storing five points at a time and drawing them. Now my strokes were longer, but the gap still existed between different strokes. This lead me to the conclusion that I needed to overlap the strokes a bit in order to remove the gap, as using a start point and end point wasn’t really working too well.
What I ended up doing was adding a variable to keep track of a midpoint. On mouse down, set the start point and mid point to the current mouse location. On mouse move, set the start point to the mid point, the mid point to the end point, and the end point to the new mouse location. Draw the line segment at that point.
This produces a smooth line and removes visible gaps. There is still some issue when using a semi-transparent color, but it’s not a big enough issue that I would worry about it.
I hope this is helpful.
As an aside, this is my first time writing a post from my TF300T (Asus Transformer Pad), so I apologize if I missed any grammar or spelling issues. I’ll hopefully remember to proofread this later. If necessary, I can provide some code examples to assist anyone who may be interested.
Until next time,
Also, since I can, I might as well include random images with my tablet-typed blog posts: