Advertisement
thecrypticace

NSShadow inside text NSBezierPath

Feb 12th, 2013
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. - (void)drawInteriorWithFrame:(NSRect)cellFrame
  2.                        inView:(NSView *)controlView
  3. {
  4.     NSBezierPath *stringPath = [self bezierPathWithString:self.stringValue
  5.                                                    inFont:self.font];
  6.  
  7.     [NSGraphicsContext saveGraphicsState];
  8.    
  9.     _innerShadow = [[NSShadow alloc] init];
  10.     _innerShadow.shadowColor = [NSColor blackColor];
  11.     _innerShadow.shadowBlurRadius = 3.0;
  12.     _innerShadow.shadowOffset = NSMakeSize(10, 0);
  13.    
  14.     NSSize offset = _innerShadow.shadowOffset;
  15.     NSSize originalOffset = offset;
  16.     CGFloat radius = _innerShadow.shadowBlurRadius;
  17.     NSRect bounds = NSInsetRect(stringPath.bounds, -(ABS(offset.width) + radius), -(ABS(offset.height) + radius));
  18.     offset.height += bounds.size.height;
  19.     _innerShadow.shadowOffset = offset;
  20.  
  21.     NSBezierPath *drawingPath = [NSBezierPath bezierPathWithRect:bounds];
  22.     [drawingPath setWindingRule:NSEvenOddWindingRule];
  23.     [drawingPath appendBezierPath:stringPath];
  24.  
  25.     [stringPath addClip];
  26.     [_innerShadow set];
  27.     [[NSColor blackColor] set];
  28.     [drawingPath fill];
  29.    
  30.     _innerShadow.shadowOffset = originalOffset;
  31.    
  32.     [NSGraphicsContext restoreGraphicsState];
  33. }
  34.  
  35. - (NSBezierPath *)bezierPathWithString:(NSString *)text
  36.                                 inFont:(NSFont *)font
  37. {
  38.     // This has some weird alphabet shifting problem
  39.     // Don't use in production until fixed
  40.  
  41.     NSBezierPath *aPath = [NSBezierPath bezierPath];
  42.     [aPath moveToPoint:NSZeroPoint];
  43.    
  44.     NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text];
  45.     CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)CFBridgingRetain(attributedString));
  46.  
  47.     CFArrayRef glyphRuns = CTLineGetGlyphRuns(line);
  48.     CFIndex count = CFArrayGetCount(glyphRuns);
  49.  
  50.     for (CFIndex index = 0; index < count; index++) {
  51.         CTRunRef currentRun = CFArrayGetValueAtIndex(glyphRuns, index);
  52.  
  53.         CFIndex glyphCount = CTRunGetGlyphCount(currentRun);
  54.  
  55.         CGGlyph glyphs[glyphCount];
  56.         CTRunGetGlyphs(currentRun, CTRunGetStringRange(currentRun), glyphs);
  57.  
  58.         NSGlyph bezierPathGlyphs[glyphCount];
  59.         for (CFIndex glyphIndex = 0; glyphIndex < glyphCount; glyphIndex++) {
  60.             bezierPathGlyphs[glyphIndex] = glyphs[glyphIndex];
  61.         }
  62.  
  63.         [aPath appendBezierPathWithGlyphs:bezierPathGlyphs
  64.                                     count:glyphCount
  65.                                    inFont:font];
  66.     }
  67.  
  68.     CFRelease(line);
  69.    
  70.     [aPath transformUsingAffineTransform:[self verticallyFlippedAffineTransformForRect:aPath.bounds]];
  71.    
  72.     return aPath;
  73. }
  74.  
  75. - (NSAffineTransform *)verticallyFlippedAffineTransformForRect:(NSRect)rect
  76. {
  77.     NSAffineTransform *affineTransform = [NSAffineTransform transform];
  78.  
  79.     NSAffineTransformStruct transformStruct;
  80.     transformStruct.m11 = 1.0;
  81.     transformStruct.m12 = 0.0;
  82.     transformStruct.tX  = 0;
  83.     transformStruct.m21 = 0.0;
  84.     transformStruct.m22 = -1.0;
  85.     transformStruct.tY  = rect.size.height;
  86.     [affineTransform setTransformStruct:transformStruct];
  87.  
  88.     return affineTransform;
  89. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement