Monday, June 7, 2010

#8, Graphics Programming, Part 2

My objective this week is to explore the basic concepts in graphics programming on OSX. I continue to use Objective-C and Cocoa framework but this time using one of the underlying APIs, Quartz. In previous posts I talked about making a simple Notepad application using Cocoa, and introduced some fundamentals such as xCode and Interface Builder. Our Notepad used an existing library object that could take care of all the text operations and the application didn't really need to do anything except some simple UI like button-click to clear the view. For our simple graphics programming example, we use another library object, Custom View that allows us to do "custom" graphics. For the simple example I only draw coloured rectangles. But first let's review some basic concepts in Quartz.

Rectangle, presented by NSRect structure (remember that Cocoa classes and structs start with NS), is an area in which 2D graphics operations are performed. It has four basic members that are x, y, width, and height. The standard coordinate system in Quartz assumes bottom-left is the origin. Many other systems (including web and Windows) consider top-left as the origin. This is called "flipped" coordinate system in Quartz and can be set if preferred. Point, presented by NSPoint, is a set of x and y values and NSColor object is a system colour.

Here are some code examples:

// make a point at coordinate 20,20
NSPoint newPoint = NSMakePoint ( 20, 20 );

// use the previous point and size to make a rect
NSRect newRect = NSMakeRect ( newPoint.x,
newPoint.y,
newSize.width,
newSize.height );

// also can just do this
NSRect newRect = NSMakeRect ( 20, 20, 100, 100 );

//make a red colour object
//create a new object by calling redColor of NSColor class
NSColor * xColor = [NSColor redColor];

Notice how C-style functions like NSMakePoint are used and well as Objective-C method calls for NSColor. This is good and also confusing!

These variables are not objects. If you need an object (and you will in some cases), you can use NSValue:

//create an object by calling valueWithRect method of NSValue class
NSValue * rectObject = [NSValue valueWithRect: newRect];

Once you have a rectangle, you can perform operations on it, such as filling the area with a colour:

//set current colour
NSColor * white = [NSColor whiteColor];
[white set];

// fill a rect
NSRect rect1 = NSMakeRect ( 21,21,210,210 );
NSRectFill ( rect1 );

You see that the NSRectFill is another C-style function that uses a rectangle and "current colour" which has to be set in advance.

Now here is the steps we go through to create our simple application (see previous posts for details of the steps we have covered before):

1- Start Xcode and make an empty Cocoa application
2- Add a new file: Cocoa classes, Objective-C class, NSView
3- Double-click on .sib or .nib file to bring up Interface Builder
4- From Library/Objects find Custom View and add to application window
5- Choose Tools > Identity Inspector and then choose your newly created view class from the menu to associate the custom view to your class
6- Make other changes like size and attributes (optional)
7- Save and exit Interface Builder
8- Back in Xcode, go to your view class and notice three methods that have been created for you. initWithFrame and isFlipped don't need to be changed
9- In drawRect method, add the following code:
NSColor * xColor = [NSColor redColor];
[xColor setFill];
NSRect xRect = NSMakeRect(0,0,100,100);
NSRectFill(xRect);
10- You may add other graphics operation here. It will be done overtime the custom view is drawn.

This is relatively straight-forward. Now let's compare with C#.NET:

1- Create an empty C# project.
2- Add a pictureBox or another view object to your form
3- Add an event handler for Paint event for that object
4- Inside event handler write the following code:
Rectangle srcRect = new Rectangle(0, 0, 100,100);
e.Graphics.FillRectangle(new SolidBrush(Color.Red), srcRect);

As you can see the process is basically the same but the C# version has some advantages:

1- You need less code
2- The view class is more easily customizable if you have meow than one custom view. In Cocoa code, if you add two custom views they both do the same thing. In .NET example, each can have its own variable name and event handler. Of course these are possible in Cocoa too but they are not the default and require extra work which I will disuse in other posts.

So far I'm still feeling the same way as before that Windows programming is more intuitive and straight-forward than OSX. Next week, I'll show some example functionality provided by Quartz which demonstrate some of its advantages. As I mentioned before despite rather cumbersome programming style, Quartz provide programmers with more built-in 2D functions than DirectX or other Windows APIs.

Well, this is it for today.

I'LL BE BACK!

No comments:

Post a Comment