Skip to content

Instantly share code, notes, and snippets.

@KevinDoughty
Last active August 29, 2015 13:56
Show Gist options
  • Save KevinDoughty/9104385 to your computer and use it in GitHub Desktop.
Save KevinDoughty/9104385 to your computer and use it in GitHub Desktop.
Experiments with subpixel antialiasing of NSTextField without a background. Still not correct, text appears lighter and thinner.
-(void)drawInteriorWithFrame:(NSRect)theControlViewBounds inView:(NSView*)theControlView {
if (!self.isEditing) {
NSLog(@"%@ drawInteriorWithFrame:%@; inView:%@;",self, NSStringFromRect(theControlViewBounds),theControlView);
self.isEditing = YES;
NSTextView *theTextView = [self textDrawingObject];
NSTextContainer *theTextContainer = [theTextView textContainer];
NSLayoutManager *theLayoutManager = [theTextContainer layoutManager];
NSTextStorage *theTextStorage = [theLayoutManager textStorage];
NSRange theOldGlyphRange = NSMakeRange(0, [theLayoutManager numberOfGlyphs]);
NSRange theOldCharacterRange = [theLayoutManager characterRangeForGlyphRange:theOldGlyphRange actualGlyphRange:nil];
[self setUpFieldEditorAttributes:theTextView];
[theTextStorage replaceCharactersInRange:theOldCharacterRange withAttributedString:[self attributedStringValue]];
NSRect theCellFrame = [self titleRectForBounds:theControlViewBounds];
[theTextView setFrame:theCellFrame];
NSPoint theDrawPoint = theCellFrame.origin;
NSRange theNewGlyphRange = NSMakeRange(0, [theLayoutManager numberOfGlyphs]);
NSBitmapImageRep *theAncestorRep = nil;
NSView *theOpaqueAncestor = self.controlView;
while (theOpaqueAncestor != self.controlView.window.contentView) {
theOpaqueAncestor = theOpaqueAncestor.superview;
if (theOpaqueAncestor.isOpaque) {
NSRect theAncestorRect = [self.controlView convertRect:[self.controlView visibleRect] toView:theOpaqueAncestor];
theAncestorRep = [theOpaqueAncestor bitmapImageRepForCachingDisplayInRect:theAncestorRect];
[theOpaqueAncestor cacheDisplayInRect:theAncestorRect toBitmapImageRep:theAncestorRep];
CGSize theSize = theAncestorRect.size;
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGContextRef theCurrentContext = [[NSGraphicsContext currentContext] graphicsPort];
CGContextRef theMaskContext = CGBitmapContextCreate (NULL,theSize.width,theSize.height,8,0,colorSpace,kCGBitmapByteOrder32Host|kCGImageAlphaPremultipliedFirst);
CGContextRef theBackgroundContext = CGBitmapContextCreate (NULL,theSize.width,theSize.height,8,0,colorSpace,kCGBitmapByteOrder32Host|kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
if (theMaskContext != NULL && theBackgroundContext != NULL) {
CGRect theBounds = CGRectMake(0,0,theSize.width,theSize.height);
[NSGraphicsContext saveGraphicsState];
NSGraphicsContext *theMaskGraphicsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:theMaskContext flipped:self.controlView.isFlipped];
[NSGraphicsContext setCurrentContext:theMaskGraphicsContext];
CGContextSetShouldSmoothFonts(theMaskContext,YES);
CGContextSetAllowsAntialiasing(theMaskContext,YES);
CGContextSetAllowsFontSmoothing(theMaskContext,YES);
CGContextSetAllowsFontSubpixelPositioning(theMaskContext,YES);
CGContextSetAllowsFontSubpixelQuantization(theMaskContext,YES);
if (theOpaqueAncestor.isFlipped != self.controlView.isFlipped) {
NSAffineTransform *theTransform = [NSAffineTransform transform];
[theTransform scaleXBy:1.0 yBy:-1.0];
CGFloat theFlip = theAncestorRect.size.height;
[theTransform translateXBy:0.0 yBy:-theFlip];
[theTransform concat];
}
[theLayoutManager drawGlyphsForGlyphRange:theNewGlyphRange atPoint:theDrawPoint];
CGImageRef theMaskImage = CGBitmapContextCreateImage(theMaskContext);
CGContextDrawImage(theMaskContext, theBounds, theMaskImage);
[NSGraphicsContext restoreGraphicsState];
[NSGraphicsContext saveGraphicsState];
if (theOpaqueAncestor.isFlipped != self.controlView.isFlipped) {
NSAffineTransform *theTransform = [NSAffineTransform transform];
[theTransform scaleXBy:1.0 yBy:-1.0];
CGFloat theFlip = theAncestorRect.size.height;
[theTransform translateXBy:0.0 yBy:-theFlip];
[theTransform concat];
}
CGContextClipToMask(theCurrentContext, theBounds, theMaskImage);
CGContextDrawImage (theCurrentContext, CGRectMake(0,0,theAncestorRect.size.width,theAncestorRect.size.height),[theAncestorRep CGImage]);
[NSGraphicsContext restoreGraphicsState];
CGContextSetShouldSmoothFonts(theCurrentContext,YES);
CGContextSetAllowsAntialiasing(theCurrentContext,YES);
CGContextSetAllowsFontSmoothing(theCurrentContext,YES);
CGContextSetAllowsFontSubpixelPositioning(theCurrentContext,YES);
CGContextSetAllowsFontSubpixelQuantization(theCurrentContext,YES);
[theLayoutManager drawGlyphsForGlyphRange:theNewGlyphRange atPoint:theDrawPoint];
CGImageRelease(theMaskImage);
CGContextRelease (theMaskContext);
self.isEditing = NO;
return;
}
}
}
self.isEditing = NO;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment