Posts Tagged ‘OSX’

SVGQuartzRenderer: A basic iPhone SDK compatible SVG renderer

Tuesday, September 28th, 2010

I’m working on a game for the iPhone platform. The levels will be quite big, and on top of that I need them in 2 different resolutions (because of the iPhone 4 retina display). Having them in the bundle in a bitmap based format would make the final bundle several hundred megabytes big, which is unacceptable. So I figured that it would be better to store them in a vector based format instead, since I create the levels in InkScape anyway.

At first I was thinking about the PDF format. But then I realized that I could use the same vector data to construct the physics world in Box2D. And for this task, the SVG format is brilliant. It’s an easy-to-parse XML format and it can have arbitrary text-based data associated with each object. That means I can put implementation specific data in the file directly from InkScape (like if an object should be static or dynamic in Box2D for example).

As it turns out, though, CoreGraphics does not support the SVG format. Bummer. Sure, UIWebView can render SVG’s, but I could not find a good way to use that for off-screen rendering. So I went and started looking for an open source library that could render an SVG into a pixel buffer. I found only one; librsvg. And then a few others, but they all seemed to depend on librsvg.

There are two problems with librsvg:
1. It’s LGPL, which if I’ve understood correctly will require me to release my game under a compatible licence unless I link librsvg dynamically. Unfortunatly, this cannot be done in the iPhone SDK.
2. After hours of trying, I could not get librsvg to compile for the iPhone.

So I gave up on 3rd party libs and began writing my own SVG renderer in Obj-c. Turns out it wasn’t very hard to get the most basic stuff up and running.

And this is it. SVGQuartzRender. It’s by no means a complete implementation of the SVG specification, but it can render the most basic stuff found in an SVG, and it can conveniently render it to a CGImageRef.

This is how to use it, in a nutshell:
Somewhere in your class, the init method for example:

SVGQuartzRenderer *svgRenderer = [[SVGQuartzRenderer alloc] init];
// A delegate must be specified
[svgRenderer setDelegate:self];

You also need to implement the <SVGQuartzRendererDelegate> protocol:

// This is called before rendering begins. Here you need to supply the CGContext where you want the
//rendering to be done. If you just want an empty, off-screen bitmap context, you can use the
//convenience method  -(CGContextRef)createBitmapContext
- (CGContextRef)svgRenderer:(id)renderer
	requestedCGContextWithSize:(CGSize)size
{
	return [renderer createBitmapContext];;
}

// Will be called when rendering is complete
- (void)svgRenderer:(id)renderer
	didFinnishRenderingFile:(NSString *)file
	inCGContext:(CGContextRef)context
{
	// Here's your CGImageRef!
	CGImageRef svgDrawing = CGBitmapContextCreateImage(context);
}

In the XCode project, there is a simple Cocoa app that demostrates more thoroughly how it is used.

I’ve put up a GitHub repo for SVGQuartzRenderer. If you want it, you should get it from there.

SVGQuartzRenderer on GitHub

Feel free to use this code how ever you like, commercially or non-commercially. Should you make any improvements I’d love to get a patch! :)

Mouse tracking in NSView

Saturday, February 13th, 2010

Tracking the position of the mouse does seem like a trivial task. At a first glance it seemed like it would be a matter to override the -mouseMoved: selector in my NSView subclass and make sure the window accepts mouseMoved events by calling [[self window] setAcceptsMouseMovedEvents:YES]; when the view had loaded. Well, not exactly. I tried every conceivable combination of placements of these peices of code, including making the view the first responder, but I could never manage to intercept the mouseMoved event.

Then I found out about NSTrackingArea. Perhaps I was being overly ignorant, but from reading the event handling docs, it was not clear to me that I would need to use a tracking area to be able to recieve mouseMoved events.

Using NSTrackingArea is pretty straight forward, although at first I got a cryptic error message in the console:

trackingArea options 0x2 do not specify when the tracking area is active

As it turns out, NSTrackingArea requires a combination of several options to work properly. In this case I needed to supply “NSTrackingMouseMoved+NSTrackingActiveInKeyWindow” in the options: attribute.

Putting the following code in the -viewDidMoveToWindow method in my NSView subclass finally managed to get the view to recieve mouseMoved events:

NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame]
	options:NSTrackingMouseMoved+NSTrackingActiveInKeyWindow
	owner:self
	userInfo:nil];
[self addTrackingArea:trackingArea];
[self becomeFirstResponder];

ImageSplitter.app

Friday, January 29th, 2010

Did you ever feel the need to split a big image into a bunch of equally sized slices? Well, I do sometimes, so I decided to make a permanent solution to the problem. I prestent to you: ImageSplitter.app

ImageSplitter a very simple Cocoa application that does one thing. Can you guess it? Correct, it splits images :)

I needed a simple way to split large background images into smaller chunks for an iPhone game that I’m currently working on. Im sure there are a lot of apps out there that could do this for me, but none that I could find that did only that, and in the specific way that I needed.

Well, now there is!

Screen shot 2010-01-29 at 13.15.24

Simply drag the image onto the image well, set the slice size and format, and hit Split. The image will split up into a series of files named mySplittedImage_0.png, mySplittedImage_1.png etc.

Happy splitting!