Skip to content

Instantly share code, notes, and snippets.

@eonist
Created December 10, 2015 16:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eonist/520fa35958c123ad6840 to your computer and use it in GitHub Desktop.
Save eonist/520fa35958c123ad6840 to your computer and use it in GitHub Desktop.
Quartz Inner Shadow (playground)
import Cocoa
import XCPlayground
import XCTest
/*
shadow.shadowColor = NSColor.blackColor().colorWithAlphaComponent(1.0)
shadow.shadowOffset = NSMakeSize(0.1, 0.1)
shadow.shadowBlurRadius = 15
*/
extension NSShadow{
convenience init(_ color:NSColor,_ offsetX:CGFloat,_ offsetY:CGFloat,_ blurRadius:CGFloat){
self.init()
self.shadowColor = color
self.shadowOffset = NSMakeSize(offsetX,offsetY)
self.shadowBlurRadius = blurRadius
}
}
extension NSColor{
/**
* EXAMPLE: :NSColor(NSColor.blackColor(),0.5)//outputs a black color with 50% transparancy
*/
convenience init(_ color:NSColor,_ alpha:CGFloat/*0.0 - 1.0*/){
let ciColor:CIColor = CIColor(color: color)!
self.init(red: ciColor.red, green: ciColor.green, blue: ciColor.blue, alpha: alpha)
}
/**
* EXAMPLE: NSColor.redColor().alpha(0.5)
*/
func alpha(alpha:CGFloat)->NSColor{
return NSColor(self,alpha)
}
}
class FlippedView:NSView {//Organizes your view from top to bottom
override var flipped:Bool {return true}
}
class Container:FlippedView{
var color:NSColor = NSColor.blueColor()
override var wantsDefaultClipping:Bool{return false}//avoids clipping the view
override var wantsUpdateLayer:Bool {return true}
init(_ width:Int = 400, _ height:Int = 400, _ color:NSColor = NSColor.blueColor() ) {
Swift.print("Container.init()")
self.color = color
let frame = NSRect(x: 0, y: 0, width: width, height: height)
super.init(frame: frame)
self.wantsLayer = false
}
/**
* NOTE: One can also use NSShadow(shadow.shadowColor!.colorWithAlphaComponent(1.0),shadow.shadowOffset.width,shadow.shadowOffset.height,shadow.shadowBlurRadius).set() instead of CGContextSetShadowWithColor
*/
override func drawRect(dirtyRect: NSRect) {
//Swift.print("drawRect()")
//// General Declarations
let context = NSGraphicsContext.currentContext()!.CGContext
/*Draw first shapes:*/
let path:CGMutablePathRef = CGPathCreateMutable();
let rectangle:CGRect = CGRectMake(10.0, 10.0,200.0, 200.0);
let roundRectPath:CGMutablePathRef = CGPathCreateWithRoundedRect(rectangle, 20, 20, nil) as! CGMutablePathRef/* Add the roundRectangle to the roundRectPath*/
CGPathAddPath(path, nil, roundRectPath)/*Adds the roundRectPath to the path*/
/*draw second shape*/
let rect:CGRect = CGRectMake(210.0, 210.0,100.0, 100.0)
let rectPath:CGMutablePathRef = CGPathCreateWithRect(rect, nil) as! CGMutablePathRef
CGPathAddPath(path, nil, rectPath)/*Adds the rectPath to the path*/
/*Add,fill and draw path to the context*/
CGContextAddPath(context,path)/* Add the path to the context*/
CGContextSetFillColorWithColor(context,NSColor.cyanColor().CGColor)
//CGContextDrawPath(context, CGPathDrawingMode.Fill)/*draw the path with a fill*/ //
CGContextDrawPath(context, CGPathDrawingMode.Fill)
/*Init the inset dropshadow scheme*/
CGContextSaveGState(context);/*init the gState*/
CGContextAddPath(context, path);/*add The clipping path to the context*/
CGContextClip(context);/*The clipping ensures that the shadow is within its shape that it tries to cast an inset shadow on*/
/*Stores data about the Shadow*/
let shadow = NSShadow(NSColor.blackColor().alpha(1.0),0.1,0.1,15)
let opaqueShadowColor:CGColorRef = CGColorCreateCopyWithAlpha(shadow.shadowColor!.CGColor, 1.0)!/*We need a copy of the shadow color as CGColor with alpha set to 1*/
CGContextSetAlpha(context, CGColorGetAlpha(shadow.shadowColor!.CGColor));
CGContextBeginTransparencyLayer(context, nil);
CGContextSetShadowWithColor(context, shadow.shadowOffset, shadow.shadowBlurRadius, opaqueShadowColor);/*This is where the setting of the shadow happens*/
CGContextSetBlendMode(context, CGBlendMode.SourceOut);/*The blend mode creates the hole in the shadow so that it appears like an inner shadow*/
CGContextSetFillColorWithColor(context, opaqueShadowColor);
CGContextAddPath(context, path);
CGContextFillPath(context);
CGContextEndTransparencyLayer(context);
CGContextRestoreGState(context);/*end the gState*/
/*end the inset dropshadow scheme*/
/*Continue drawing regular stuff here, like stroke*/
CGContextAddPath(context, path);/*The clipping path*/
CGContextSetStrokeColorWithColor(context, NSColor.magentaColor().CGColor)
CGContextSetLineWidth(context, 10)//set the stroke width!
CGContextDrawPath(context, CGPathDrawingMode.Stroke)
}
/**
* Required by super class
*/
required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}
}
let container = Container()
XCPlaygroundPage.currentPage.liveView = container
@eonist
Copy link
Author

eonist commented Jan 29, 2016

Example:

screen shot 2015-12-07 at 15 36 53

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment