Re: Cocoa graphics speed
Re: Cocoa graphics speed
- Subject: Re: Cocoa graphics speed
- From: Chris Hanson <email@hidden>
- Date: Mon, 29 Sep 2003 17:18:09 -0500
There are substantial differences in the graphics architectures between
QuickDraw and CoreGraphics.
In QuickDraw, you're always working in pixel coordinates. In the worst
case, your coordinates have to be translated from port to global
coordinates, and then your rectangle can be filled.
In CoreGraphics, you're always working in an abstract "user space."
Coordinates in user space are mapped to device space via the
concatenation of two translation matrices; they're mapped from user
space to ideal space (with 72 points per inch) by the current
transformation matrix (CTM) and from ideal space to device space via
another matrix. Right now, in CoreGraphics, when drawing to the screen
ideal and device space are the same thing. But they don't have to be,
and aren't when printing.
OK, so instead of one simple addition per coordinate for your
rectangle, you have a matrix multiply. That costs a bit right there,
but it gets you a *lot* of flexibility.
There's even more to filling a "simple" rectangle in CoreGraphics
though. QuickDraw will fill your rectangle with a simple pattern.
CoreGraphics patterns are much more complex -- there's a lot more they
can do. CoreGraphics cares about And in QuickDraw, you're
fundamentally just setting bits; in CoreGraphics, you aren't, you're
creating paths, filling them, and then throwing them away.
Essentially, an implementation of NSRectFill looks something like this:
void NSRectFill(NSRect rect) {
NSBezierPath *path = [NSBezierPath bezierPathWithRect:rect];
[path fill];
}
It's creating a path, filling it, and then tossing it out. That's
expensive.
One way to speed up your code would be to create a real NSBezierPath
for the rectangle, and keep the path itself around. You can then
replace your NSRectFill(ptRect) with something like this:
[cachedPath removeAllPoints];
[cachedPath appendBezierPathWithRect:ptRect];
[cachedPath fill];
Another thing you could do is keep a unit square path around, and then
just scale & translate the coordinate system as necessary before
filling your unit square path. That's what's happening behind the
scenes anyway; you could "cut out the middleman" and only do the work
you really need to do by going that route. I'm not sure whether or not
that'd be faster, but it might since all you'd be doing is manipulating
the CTM.
Another thing you should definitely do to speed up your code is only
draw those portions of your view that actually need to be redrawn. Do
an intersection test with the rectangle passed to your view's
-drawRect: method, and only draw those that intersect with it. Also,
be careful not to use -setNeedsDisplay: but rather
-setNeedsDisplayInRect: to tell the AppKit that a view needs to be
refreshed. That will let the AppKit determine the optimal rectangle to
update; it won't try to update everything all the time. This would
probably require that your elements keep track of their own radius,
rather than asking the sender of -stroke:; either that, or the sender
of -stroke: should also keep track of the current rectangle passed to
-drawRect: and allow your elements to look at it to determine whether
they need to be drawn.
I hope this gives you some idea as to why what you're doing has
different performance characteristics with Cocoa/CoreGraphics and
QuickDraw, and gives you some strategies for ways you can optimize your
drawing.
CoreGraphics does a *lot* more than QuickDraw and is quite a nice
architecture, but it's not without its costs.
-- Chris
PS - To the CG-experienced Cocoa developers out there, is there a
lower-level CoreGraphics equivalent to the -[NSBezierPath bounds]
method that only gets the path's bounds, rather than its bounds
including control points (which one can get by using -[NSBezierPath
controlPointBounds])? Some developers were asking how to do this over
on Apple's Carbon-Development mailing list.
--
Chris Hanson, bDistributed.com, Inc. | Email: email@hidden
Custom Mac OS X Development | Phone: +1-847-372-3955
http://bdistributed.com/ | Fax: +1-847-589-3738
http://bdistributed.com/Articles/ | Personal Email: email@hidden
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.