Adrian,
I can't help with the styled part, but just to see how somebody else did
something fwiw you can look at the code at
http://www.tobyz.net/tobyzstuff/diary/2008/02/spk-stringtoimagestructure, and i
have a skunkworks-more-than-alpha stringtopointstructure too
Which is a strange way of saying: go adrian, the better text handling in qc,
the better!
Toby
On 17 Jan 2010, at 19:21, Adrian Ward wrote:
>
> 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:...]
>
> <Untitled Image.png>
> 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/lists%40tobyz.net
>
> This email sent to [email protected]
_______________________________________________
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]