Wow, Ken! It works like magic (the second method I mean). Thank you very much. I think I would never guess it myself.
For those who will reuse this code, don't forget to save/restore the graphics context because CGContextClipToMask modified the clipping region. Sorry for late thanking, I had to postpone this task for a while. Oleg Krupnov. On Sun, Feb 1, 2009 at 4:03 AM, Ken Ferry <kenfe...@gmail.com> wrote: > All else aside, yes you can do this in Cocoa and/or Quartz. > Here are a couple different ways. For instruction's sake, here's it done > with a compositing operation, NSCompositeDestinationIn. Result color = > what's already in the context but with additional alpha taken from the new > drawing. > > - (void)drawRect:(NSRect)dirtyRect { > NSRect bounds = [self bounds]; > NSImage *textLayerImage = [[NSImage alloc] initWithSize:bounds.size]; { > [textLayerImage lockFocus]; { > NSRect textLayerBounds = {NSZeroPoint, [textLayerImage size]}; > > [@"I am a string" drawAtPoint:textLayerBounds.origin > withAttributes:nil]; > > NSGradient *alphaGradient = [[NSGradient alloc] > initWithStartingColor:[NSColor blackColor] endingColor:[NSColor > clearColor]]; { > [[NSGraphicsContext currentContext] > setCompositingOperation:NSCompositeDestinationIn]; > [alphaGradient drawInRect:textLayerBounds angle:0]; > } [alphaGradient release]; > } [textLayerImage unlockFocus]; > > [textLayerImage drawInRect:bounds fromRect:NSZeroRect/*whole thing*/ > operation:NSCompositeSourceOver fraction:1.0]; > } [textLayerImage release]; > } > > That works, but it loses the LCD antialiasing, as others have noticed. The > text is drawn into a transparent layer, which defeats subpixel rendering. > Also, most people will not understand your code, because of the use of > NSCompositeDestinationIn. > A more understandable method that will also preserve the LCD text is to set > a clip that has partial transparency. This requires mixing CoreGraphics > calls in with the Cocoa. > > - (void)drawRect:(NSRect)dirtyRect { > CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; > NSRect bounds = [self bounds]; > > CGImageRef maskImage = CreateMaskImage(bounds.size); { > CGContextClipToMask(ctx, NSRectToCGRect(bounds), maskImage); > } CFRelease(maskImage); > > [@"I am a string" drawAtPoint:[self bounds].origin withAttributes:nil]; > } > > CGImageRef CreateMaskImage(NSSize size) { > > CGImageRef maskImage; > > CGContextRef maskContext = CGBitmapContextCreate(NULL, size.width, > size.height, 8/*bitsPerComponent*/, 0/*bytesPerRow - 0 means CG picks*/, > [[NSColorSpace genericGrayColorSpace] CGColorSpace], kCGImageAlphaNone); { > > CGGradientRef grayGradient = > CGGradientCreateWithColors([[NSColorSpace genericGrayColorSpace] > CGColorSpace], (CFArrayRef)[NSArray > arrayWithObjects:(id)CGColorGetConstantColor(kCGColorWhite), > (id)CGColorGetConstantColor(kCGColorBlack), nil], NULL/*locations - NULL > means colors evenly distribute*/); { > > CGContextDrawLinearGradient(maskContext, grayGradient, > CGPointZero, CGPointMake(CGBitmapContextGetWidth(maskContext), 0), > 0/*options*/); > > } CFRelease(grayGradient); > > > > maskImage = CGBitmapContextCreateImage(maskContext); > > > > } CFRelease(maskContext); > > > > return maskImage; > > } > > CoreImage is likely to not perform well for a small task like this. > CoreImage incurs some per-use costs that it makes up for with awesome > per-pixel performance. If you don't have very many pixels and your effect > is simple enough to do with Cocoa/CoreGraphics, the CoreGraphics approach is > likely to perform better. > -Ken > > On Thu, Jan 29, 2009 at 12:27 AM, Oleg Krupnov <oleg.krup...@gmail.com> > wrote: >> >> Yeah, the question is however how do I technically (e.g. in Cocoa) >> composite the "appropriate alpha" with an image, whether the >> background image, as you suggest, or with text image, as Ricky >> suggested. >> >> AFAIU, there is not such NSCompositingOperation to do this trick. It >> appears that I need to iterate all pixels of the intermediate bitmap, >> and multiply the transparency value by the mask. This is quite >> low-level, is there a better way? >> >> >> On Thu, Jan 29, 2009 at 8:32 AM, Kyle Sluder <kyle.slu...@gmail.com> >> wrote: >> > On Wed, Jan 28, 2009 at 10:57 AM, Thomas Davie <tom.da...@gmail.com> >> > wrote: >> >> This solution will also throw sub-pixel anti-aliasing in the bin. >> > >> > Perhaps the better solution is to draw the text as normal and then >> > re-draw the background with the appropriate alpha on top. >> > >> > --Kyle Sluder >> > >> _______________________________________________ >> >> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) >> >> Please do not post admin requests or moderator comments to the list. >> Contact the moderators at cocoa-dev-admins(at)lists.apple.com >> >> Help/Unsubscribe/Update your Subscription: >> http://lists.apple.com/mailman/options/cocoa-dev/kenferry%40gmail.com >> >> This email sent to kenfe...@gmail.com > > _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com