Advertisement
thecrypticace

Text Inset NSShadow

Feb 12th, 2013
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // The only contents of an NSTextFieldCell subclass
  2.  
  3. - (void)drawInteriorWithFrame:(NSRect)cellFrame
  4.                        inView:(NSView *)controlView
  5. {
  6.     // Works but looks really bad
  7.     NSBezierPath *stringPath = [self bezierPathWithString:self.stringValue
  8.                                                    inFont:self.font];
  9.     NSAffineTransform *aTransform = [NSAffineTransform transform];
  10.     [aTransform translateXBy:4
  11.                          yBy:5];
  12.     [stringPath transformUsingAffineTransform:aTransform];
  13.  
  14.     if (!_innerShadow) {
  15.         _innerShadow = [[NSShadow alloc] init];
  16.         _innerShadow.shadowColor = [[NSColor blackColor] colorWithAlphaComponent:0.9];
  17.         _innerShadow.shadowBlurRadius = 4.0;
  18.         _innerShadow.shadowOffset = NSMakeSize(0, -1.0);
  19.     }
  20.  
  21.     [NSGraphicsContext saveGraphicsState];
  22.    
  23.     NSShadow *raisedShaow = [[NSShadow alloc] init];
  24.     raisedShaow.shadowColor = [[NSColor whiteColor] colorWithAlphaComponent:1.0];
  25.     raisedShaow.shadowBlurRadius = 0.0;
  26.     raisedShaow.shadowOffset = NSMakeSize(0, -1.0);
  27.     [raisedShaow set];
  28.    
  29.     CGContextSetBlendMode([[NSGraphicsContext currentContext] graphicsPort], kCGBlendModeScreen);
  30.    
  31.     self.textColor = [NSColor blackColor];
  32.     [super drawInteriorWithFrame:cellFrame
  33.                           inView:controlView];
  34.  
  35.     [NSGraphicsContext restoreGraphicsState];  
  36.     [NSGraphicsContext saveGraphicsState];
  37.    
  38.     NSBezierPath *framePath = [NSBezierPath bezierPathWithRect:cellFrame];
  39.     [framePath setWindingRule:NSEvenOddWindingRule];
  40.     [framePath appendBezierPath:stringPath];
  41.     [stringPath setClip];
  42.    
  43.     [_innerShadow set];
  44.     [framePath fill];
  45.    
  46.     [NSGraphicsContext restoreGraphicsState];
  47.  
  48.     // Doesn't really work, and I've no idea why
  49.     /*CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
  50.     CGContextRef maskContext = CGBitmapContextCreate(
  51.                           NULL,
  52.                           cellFrame.size.width,
  53.                           cellFrame.size.height,
  54.                           8,
  55.                           cellFrame.size.width,
  56.                           colorspace,
  57.                           0);
  58.     CGColorSpaceRelease(colorspace);
  59.    
  60.     // Switch to the context for drawing
  61.     [NSGraphicsContext saveGraphicsState];
  62.     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:maskContext
  63.                                                                                     flipped:YES]];
  64.  
  65.     // Draw a black background to exclude
  66.     [[NSColor blackColor] set];
  67.     CGContextFillRect(maskContext, cellFrame);
  68.  
  69.     // Draw the string in white to include
  70.     [self.stringValue drawInRect:cellFrame
  71.                   withAttributes:@{
  72.             NSFontAttributeName : self.font,
  73.  NSForegroundColorAttributeName : [NSColor whiteColor]
  74.      }];
  75.    
  76.     CGImageRef alphaMask = CGBitmapContextCreateImage(maskContext);
  77.     [NSGraphicsContext restoreGraphicsState];
  78.  
  79.     // Draw a white background in the window
  80.     CGContextRef windowContext = [[NSGraphicsContext currentContext] graphicsPort];
  81.  
  82.     // Draw the image, clipped by the mask
  83.     CGContextSaveGState(windowContext);
  84.     CGContextClipToMask(windowContext, NSRectToCGRect(cellFrame), alphaMask);
  85.    
  86.     [_innerShadow set];
  87.  
  88.     NSRectFill(cellFrame);
  89.  
  90.     CGContextRestoreGState(windowContext);
  91.     CGImageRelease(alphaMask);*/
  92. }
  93.  
  94. - (NSBezierPath *)bezierPathWithString:(NSString *)text
  95.                                 inFont:(NSFont *)font
  96. {
  97.     // This has some weird alphabet shifting problem
  98.     // Don't use in production until fixed
  99.  
  100.     NSBezierPath *aPath = [NSBezierPath bezierPath];
  101.     [aPath moveToPoint:NSZeroPoint];
  102.  
  103.     NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text
  104.                                                                            attributes:@{
  105.                                                                  NSFontAttributeName : self.font
  106.                                             }];
  107.     CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)CFBridgingRetain(attributedString));
  108.  
  109.     CFArrayRef glyphRuns = CTLineGetGlyphRuns(line);
  110.     CFIndex count = CFArrayGetCount(glyphRuns);
  111.  
  112.     for (CFIndex index = 0; index < count; index++) {
  113.         CTRunRef currentRun = CFArrayGetValueAtIndex(glyphRuns, index);
  114.  
  115.         CFIndex glyphCount = CTRunGetGlyphCount(currentRun);
  116.  
  117.         CGGlyph glyphs[glyphCount];
  118.         CTRunGetGlyphs(currentRun, CTRunGetStringRange(currentRun), glyphs);
  119.  
  120.         NSGlyph bezierPathGlyphs[glyphCount];
  121.         for (CFIndex glyphIndex = 0; glyphIndex < glyphCount; glyphIndex++) {
  122.             bezierPathGlyphs[glyphIndex] = glyphs[glyphIndex];
  123.         }
  124.  
  125.         [aPath appendBezierPathWithGlyphs:bezierPathGlyphs
  126.                                     count:glyphCount
  127.                                    inFont:font];
  128.     }
  129.  
  130.     CFRelease(line);
  131.    
  132.     [aPath transformUsingAffineTransform:[self verticallyFlippedAffineTransformForRect:aPath.bounds]];
  133.    
  134.     return aPath;
  135. }
  136.  
  137. - (NSAffineTransform *)verticallyFlippedAffineTransformForRect:(NSRect)rect
  138. {
  139.     NSAffineTransform *affineTransform = [NSAffineTransform transform];
  140.  
  141.     NSAffineTransformStruct transformStruct;
  142.     transformStruct.m11 = 1.0;
  143.     transformStruct.m12 = 0.0;
  144.     transformStruct.tX  = 0;
  145.     transformStruct.m21 = 0.0;
  146.     transformStruct.m22 = -1.0;
  147.     transformStruct.tY  = rect.size.height;
  148.     [affineTransform setTransformStruct:transformStruct];
  149.  
  150.     return affineTransform;
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement