Hello all,

I'm trying to build a plugin that makes it possible to generate images with attributed strings (ie. support for bold, italic, etc). Ultimately I'd like this to be a drop-in replacement for Image With String, but that could accept HTML markup, using a CSS stylesheet etc.

The technique I'm attempting is:

1. Allocate a bitmap buffer
2. Create a CGContextRef for it
3. Create an NSAttributedString with some suitable formatting
4. Render it into the CGContext using a CTFramesetter (as per Apple's Core Text Programming Guide)
5. Make a QCPlugInOutputImageProvider using [qccontext outputImageProviderFromBufferWithPixelFormat:...]

As you can see, this technique seems to be working - albeit with some weirdness, hacks and bugs - however, when I try implementing step 3 like so:

  NSData* htmldata = [self.inputString dataUsingEncoding:NSUnicodeStringEncoding];
  NSAttributedString* attrString = [[NSAttributedString allocinitWithHTML:htmldata baseURL:[qccontext compositionURLdocumentAttributes:nil];

This does work, but Quartz Composer's OpenGL view seems to become corrupted, and subsequent drawing goes wildly wrong. Sprites with width 1 suddenly and rapidly render at double their size, and the corruption gets worse each frame, quickly causing QC to render nonsense. There's no crashing, just garbage being rendered.

I know that initWithHTML:... causes WebKit to load internally, and this probably requires all sorts of graphics state changes, and am guessing that this is causing the problem. However, I'm not sure what I should be looking at to get around the problem and would appreciate some tips.

Solutions/workarounds I've tried:

- blindly experimenting with CGContextSaveGState, glLoadIdentity, etc in attempts to avoid corrupt graphics states (makes no difference)
- using NSAttributedString's initWithPath:@"/test.html" instead (same problem)
- using NSAttributedString's initWithPath:@"/test.docx" instead (works perfectly! ...but isn't what I want to achieve)
- manually building my NSAttributedString instead of using initWithHTML: (problem goes away, but I lose the convenience of HTML, CSS etc)

Would anyone with a bit more experience be able to make some kind suggestions?

Thanks and all the best,



Ade.



- (BOOL) execute:(id<QCPlugInContext>)qccontext atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{

// CGLContextObj ctl_ctx = [qccontext CGLContextObj];


// Make the backing buffer
NSUInteger width = self.inputWidth;
NSUInteger height = self.inputHeight;
NSUInteger bytesPerRow = width * 4; // FIXME: This must be modulo 16 - what if width isn't a nice number?
char* buffer = valloc(height * bytesPerRow); // FIXME: What if the memory wasn't allocated?


// Clear the buffer
memset(buffer, 0, height * bytesPerRow);


// Make a CGContextRef around it FIXME: What if we're running on a non-Intel platform, where the format wouldn't be ARGB but BGRA?
CGColorSpaceRef cgcolorspace = CGColorSpaceCreateDeviceRGB();
CGContextRef cgcontext = CGBitmapContextCreate(buffer, width, height, 8, bytesPerRow, cgcolorspace, kCGImageAlphaPremultipliedFirst); // FIXME: What if the CGContextRef wasn't created?


// Create attributed string FIXME: This corrupts QC's graphics state???
NSData* htmldata = [self.inputString dataUsingEncoding:NSUnicodeStringEncoding];
NSAttributedString* attrString = [[NSAttributedString alloc] initWithHTML:htmldata baseURL:[qccontext compositionURL] documentAttributes:nil]; // FIXME: What if attrString wasn't created?


// Draw a string using a typesetter
// Initialize a rectangular path.
CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(0, 0, width, height);
CGPathAddRect(path, NULL, bounds);


// Create the framesetter with the attributed string.
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attrString);


// Create the frame and draw it into the graphics context
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CFRelease(framesetter);
CTFrameDraw(frame, cgcontext);
CFRelease(frame);
CFRelease(path);

// Make the output provider
id<QCPlugInOutputImageProvider> provider = [qccontext outputImageProviderFromBufferWithPixelFormat:QCPlugInPixelFormatARGB8 pixelsWide:width pixelsHigh:height baseAddress:buffer bytesPerRow:bytesPerRow releaseCallback:(QCPlugInBufferReleaseCallback)_bufferReleaseCallback releaseContext:nil colorSpace:cgcolorspace shouldColorMatch:YES];
self.outputImage = provider;

// Free everything
[attrString release];


CGContextRelease(cgcontext);
CGColorSpaceRelease(cgcolorspace);


return YES;
}



 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Quartzcomposer-dev mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/quartzcomposer-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to