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 alloc] initWithHTML:htmldata baseURL:[qccontext compositionURL] documentAttributes: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]


