views:

109

answers:

0

Here's a picture of one of the stranger problems I've had. I'm using a plugin architecture to draw things in Core Graphics. The host app creates a context that is passed to the plugin, which draws into the context and sends it back. Here this was done multiple times to draw multiple objects (though just for demonstration, it happens even with just one object). The results are converted to CGImageRefs and placed on a canvas (another CGContext) which is in turn converted to an NSImage and displayed.

The problem, as you can see, is that it often returns a slightly corrupted version. It's different every time. The other strange thing is that the boxes are supposed to have 50% alpha, but they don't (except for the top of the second box, which looks like it's about the right color for that). Interestingly, the background (drawn in Core Graphics within the host app) isn't ever corrupted, so it's not a problem with the CGImage to NSImage conversion or anything like that.

The even weirder part is that I've tried having the plugin export an NSImage directly, and it had the exact same effect, maybe a little worse even. It seems to me like the problem is with drawing anything with Core Graphics in a plugin. Has anybody else run into this, or, even better, has anybody else found a solution?

Here's the host code if it helps:

 CGContextRef tC = [TC CreateBitmapContextWithWidth:720 Height:480]; //Sets up context
 CGContextSetRGBFillColor(tC, 1.0, 1.0, 1.0, 1.0);
 CGContextFillRect(tC, CGRectMake(0, 0, size.width, size.height)); //Draws Background

 for(CDObject *cdo in [[TC DocStorage] Objects]){ //Draws each object
  CGContextRef pluginContext = [TC CreateBitmapContextWithWidth:cdo.width Height:cdo.height]; //Creates context to send to plugin
  [[[TC plugins] objectForKey:[cdo Type]] drawObject:cdo inContext:pluginContext]; //Pass context through appropriate plugin (based on type)
  CGImageRef gci = CGBitmapContextCreateImage(pluginContext); //Create image of context
  CGContextDrawImage(tC, CGRectMake(cdo.x, cdo.y, CGImageGetWidth(gci), CGImageGetHeight(gci)), gci); //Draw image to canvas

  CGImageRelease(gci);
  char *bitmapData = CGBitmapContextGetData(pluginContext);
  CGContextRelease (pluginContext);
  if (bitmapData) free(bitmapData);
 }

 CGImageRef fi = CGBitmapContextCreateImage(tC); //Get image of canvas
 NSImage *tImage = [CGImagetoNSImage(fi) autorelease]; //Use external function to convert to NSImage
 CGImageRelease(fi);
 char *bitmapData = CGBitmapContextGetData(tC);
 CGContextRelease (tC);
    if (bitmapData) free(bitmapData);
 return tImage; //Return the image to be drawn in a view

And the plugin code:

 - (void)drawObject:(CDObject*)cdo inContext:(CGContextRef)ctx {
 CGContextSetRGBFillColor(ctx, 1.0, 0.0, 0.0, 0.5);
 CGContextFillRect(ctx, CGRectMake(0, 0, cdo.width, cdo.height));}