Nice find. That seems really odd though to me. Might be worth submitting as a bug or asking for clarification on the Quartz list.
On Jan 22, 2010, at 3:08 PM, Adrian Ward wrote:
Ok... here's some weird progress...I've gone back to putting creation of the NSAttributedString on the main thread, but this time I'm not waiting for it to complete before returning.[self performSelectorOnMainThread:@selector(createAttributedString:) withObject:... waitUntilDone:NO];It's a hack, but it stops the QC view becoming corrupt. So this must be a threading problem, right? I know this is a typical WebKit issue.However this all means the string isn't inited with the latest value until after the frame has been rendered, but if I switch back to kQCPlugInTimeModeIdle then I will see the results, correctly, at the next time the plugin generates an image (ie. usually pretty quickly).I'm not happy with this since it's causing my routine to execute every frame unnecessarily but I can't think of another way to avoid the issue.If I made this an idle plugin, but tried to optimise my execute: routine so it didn't do *anything* except once a new attributed string was available, would this be bad coding practice? I'm assuming there's no way to make an kQCPlugInTimeModeNone plugin "bump" it's own execute routine?Thoughts appreciated... ttfn, Ade. On 22 Jan 2010, at 17:23, vade wrote:Hey Adrian. I did not see any additional screen flickering, but you are right about the sprite thing. I did not catch that (its square for me but is indeed full width as thought its width 2 height 2). Weird, I totally missed that. And here I thought I was being helpful!This might be worth taking to the Quartz list and questioning how the HTML drawing with NSAttributedString is done in the back end, or why it might cause issues. Shoot, sorry I thought I had nailed it bit was not being careful enough.You get new/different/worse scaling issues every time you 'ping' the plugin to redraw? I tried that, and was not able to reproduce, it seems to stay constant for me (width 1 looking like width 2). A brief look at OpenGL Profiler with break on error shows nothing, so it looks like no GL behind the scenes is going awry, or at least, throwing errors. Curious.Not sure where to go from here. On Jan 22, 2010, at 11:57 AM, Adrian Ward wrote:Hey vade,Dude that's totally awesome, thanks for fixing my messy code... it works better what with the non CG drawing but I'm still seeing this viewport scaling weirdness - except this time it's only causing it any time the scene needs re-rendering (because it's now kQCPlugInTimeModeNone instead of incrementally worsening every frame).In the test.qtz file, the main sprite is width 1, height 1, which should be a square in the centre of the viewer half the width of the window. However, this is how it renders on my MacBook Pro 10.6/ QC4(103.1)Note how the sprite is stretched to be twice the width it should be, and how the type is stretched? Rolling over the Image input on the Sprite reveals the bitmap is rendering correctly (unstretched). Also, any other Sprites placed in the composition are subjected to the same distortion...If you can confirm you're seeing this the same, I'd be grateful. Ade. <Untitled Image.png> On 22 Jan 2010, at 06:00, vade wrote:Oh, oops. I left a CGContextSetBlendMode() call in there that is extraneous. You can remove that. Also you could in theory add an alpha input double port so you can fade all the text using CGContextSetAlpha which might be handy in some situations? Of course you could just fade the billboard/sprite. Anyway :)On Jan 22, 2010, at 12:57 AM, vade wrote:<StyledText fixed vade.zip> this should do it.I switched to time mode none, so you only draw when there is need to create and upload a new QCOutputImageProvider. I switched the drawing use NSAttributedStrings built in drawing code rather than the layout code.Use NSGraphicsContext to draw to the CGBitmapContext Fixed alpha and premultiply issues.That alpha thing was a pain in the ass. I think I have the ordering right, but it may need an#if __BIG_ENDIAN__ use ARGB output provider format etc. But it works, colors and alpha just fine.This is a handy QC plugin. Great idea using HTML/styles for fonts. Lots of options now. :):) On Jan 21, 2010, at 7:17 PM, Adrian Ward wrote:Hey Toby,Thanks for the tip. I had already been through your code and tried your NSImage-in-NSDictionary technique beforehand :-) Certainly made getting a test idea up and running quickly.Back to my problem, I'm still no nearer solving this. I've tried glLoadIdentity, glTranslatef, glScalef etc. I've tried saving and restoring graphics states, locking contexts whereever I can. I'm not sure what I should be trying without seeing this problem elsewhere, which I haven't yet. I even tried putting creation of the NSAttributedString into the main thread (performSelectorOnMainThread:) but there's no joy. The QC viewer window is being messed up by my NSAttributedString, and only when I use initWithHTML. It's really quite irrational and I have a feeling it has nothing to do with QC and everything to do with AppKit.Perhaps someone could give it a bash, and at the very least confirm the problem I'm experiencing?<StyledText.zip> All the best, Ade. On 21 Jan 2010, at 08:49, lists @ tobyz wrote: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 tooWhich 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 formatting4. 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 contextCTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);CFRelease(framesetter); CTFrameDraw(frame, cgcontext); CFRelease(frame); CFRelease(path); // Make the output providerid<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/doktorp%40mac.com 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/doktorp%40mac.com 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]

