2006/03/01

Quartz Musings: Recap

At first, I just wanted to play again with multi-agent systems, and build a small simulator. But soon, it diverged and the project became an excuse to play with several areas of CoreGraphics (aka Quartz) and use it for a series of post explaining some (in my opinion) interesting aspects of the OS X graphics system, a humble mini Quartz tutorial.

Here is the compiled application, and a source archive. As I'm using CoreImage and CGLayer, this application is 10.4 only, although the source code is probably still interesting for the PDF, GLContext and raw CoreGraphics snippets for older systems. Note also that the Core Image, OpenGL, or GLContext might give bogus results on some graphic cards, as I'm playing with unusually big textures (I tested with a GeForce6800 - I know there are issues with a 4MX for instance, and it won't work with a Rage128). These examples are provided on an as-is basis, so use at your own risk. In some cases, the code has been simplified to be a better example, and is probably not of production quality. Please let me know if you find this useful or if you spot any error or omission!


Comments:
I looked at your PDF generation code. I am working with PDFs in cocoa, and I wanted to do something similar to what you did this example. Only, of course mine didn't work. Turns out I was using cocoa drawing methods inside my drawing, and setting the cocoa drawing context with graphicsContextWithGraphicsPort. This seemed to work, but the resulting pdf would be too short, missing the trailer of the pdf, and trying to create a pdf would result in "failed to find start of cross-reference table. missing or invalid cross-reference trailer." being printed to the console. On inspection of the raw pdf bytes, indeed, the pdf was short.

The solution to all of this was to call graphicsContextWithGraphicsPort in a new NSAutoReleasePool, and letting the release pool go, which allows the cgcontext to be destroyed when CGReleaseContext is called.

Here is my code:

// (almost same as you have, but note we are supposed to call CGPDFContextBeginPage....
CGContextRef context;
CGDataConsumerRef datacon;
NSMutableData* data;

data = [[[NSMutableData alloc] init] autorelease];

datacon = CGDataConsumerCreateWithCFData((CFMutableDataRef)data);
context = CGPDFContextCreate(datacon,&bounds,NULL);

CGPDFContextBeginPage (context, NULL); // use PDF variants

/* My drawing code, using 'context' */

CGPDFContextEndPage (context);

CGContextRelease (context); // the ref count on the context needs to go to zero here so the context can dealloc, which will write PDF trailer out.
CGDataConsumerRelease(datacon);

[self setDocument:[[[PDFDocument alloc] initWithData:data] autorelease]];


myCustomDrawingInContext(CGContextRef inContext, NString* theString)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// Create an NSGraphicsContext that draws into the CGContext.
NSGraphicsContext *graphicsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:inContext flipped:NO];

// Make the NSGraphicsContext current and draw into it.
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:graphicsContext];

NSPoint thePoint;
thePoint.x = 200;
thePoint.y = 200;
[theString drawAtPoint:thePoint withAttributes:NULL];

[NSGraphicsContext restoreGraphicsState];
[pool release];
graphicsContext = NULL; // the destruction of the graphicsContext with a dealloc that happened at pool release will allow the CGContextRef to really destroy itself
}

Thought I should post this, as it took me a while to figure this out.
Tom Andersen
http://www.bodyjournal.com/
 
Good to know, indeed. I wonder if a solution to ensure generation in that case could be to call flushGraphics on the graphicsContextWithGraphicsPort-created graphicsContext, to avoid being dependant on the time of the release on more complex case (assuming the flushGraphics at Cocoa level will transmit a CGContextFlush on the CG PDF context).
 
I'm struggling with python and CoreGraphics for a few hours trying to convert a color JPEG image in a level of grays image that I insert in an PDF file. :)
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?