Re: Quickly drawing non-antialiased, discrete, pixels
Re: Quickly drawing non-antialiased, discrete, pixels
- Subject: Re: Quickly drawing non-antialiased, discrete, pixels
- From: Dietmar Planitzer <email@hidden>
- Date: Tue, 07 Jan 2003 00:10:16 +0100
>
From: Bill Bumgarner <email@hidden>
>
Date: Sat, 4 Jan 2003 09:19:23 -0500
>
>
Quick question: How does one quickly draw lots and lots of discrete,
>
non-contiguous, pixels into an NSView that is not anti-aliased?
I've found that the following technique seems to be the fasted possible one
if you want to use NSBezierPath:
- (void)drawRect: (NSRect)rect
{
int i,j;
double s, tx, y;
NSRect bounds = [self bounds];
NSBezierPath * path = [[NSBezierPath alloc] init];
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
[path setLineCapStyle: NSButtLineCapStyle];
[path setLineWidth: 1.0f];
for(i = 0; i < POINTS / 200; i++) {
for(j = 0; j < 200; j++) {
s = ((double) random()) / LONG_MAX;
t = ((double) random()) / LONG_MAX;
x = NSMinX(bounds) * s + (1.0 - s) * NSMaxX(bounds);
y = NSMinY(bounds) * t + (1.0 - t) * NSMaxY(bounds);
[path moveToPoint: NSMakePoint(x, y)];
[path lineToPoint: NSMakePoint(x+1.0, y)];
}
[path stroke];
[path removeAllPoints];
}
[path release];
}
Stroking 100.000 points takes approx. 1.2 seconds on my 450MHz G4.
Some notes:
a) Turning anti-aliasing off is important. Otherwise it nearly takes 2.5
seconds.
b) The way we get all that nice performance is by ensuring that our NSBP
instance never records more than a few hundred line segment as otherwise
performance will drop through the floor. That's why the second loop exists
which always appends 200 1 pixel long lines, which are then drawn.
Apparently, Quartz even takes independent line strips in the current path
into account when it checks for intersections. There may be a logic to this
- though it escapes me which one, because it introduces an asymmetry in the
libraries semantic. Compare independent line strips specified via a single
path to independent line strips specified as individual paths...
c) The reason why the above code always accumulates many line segments
before it draws the path is to ensure that the time it takes to lock/unlock
the window's back buffer won't hurd us. Note, the window back buffer is a
shared resource (window server vs. app) that's why it must be locked before
anything can be drawn and unlocked afterwards.
d) Always make sure that you have the geometrically simplest line capping
style selected.
e) Stay far, far away from NSBezierPath's class methods for drawing
rectangles or lines. They save the current gstate before each drawing
operation and establish a new gstate which gets then popped off the gstate
stack after the drawing operation has finished => kills drawing performance.
f) You could gain a little bit better performance if you could use Quartz'
new CGMutablePath object rather then NSBezierPath, though not much.
g) OpenGL will give you by far the best drawing performance :)
Regards,
Dietmar Planitzer
_______________________________________________
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.