Created
September 30, 2017 21:39
-
-
Save wolfspider/ccfd47483e7fb231b327a40e6121c575 to your computer and use it in GitHub Desktop.
Swift SVG playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //: Playground - noun: a place where people can play | |
| import SpriteKit | |
| import PlaygroundSupport | |
| import Foundation | |
| let fileURL = Bundle.main.url(forResource: "blurplain", withExtension: "svg") | |
| let content = try String(contentsOf: fileURL!, encoding: String.Encoding.utf8) | |
| let frame = CGRect(x: 0, y: 0, width: 1024, height: 768) | |
| //Set up the view and show the scene | |
| let view = SKView(frame: frame) | |
| var scene = SKScene(size: frame.size) | |
| scene.scaleMode = SKSceneScaleMode.aspectFit | |
| let midPoint = CGPoint(x: frame.width / 6 , y: frame.height ) | |
| var path = CGMutablePath() | |
| var compositePath = CGMutablePath() | |
| var pathPointX:Float = 0.0 | |
| var pathPointY:Float = 0.0 | |
| var qpathPointCX:Float = 0.0 | |
| var qpathPointCY:Float = 0.0 | |
| var qpathPointX:Float = 0.0 | |
| var qpathPointY:Float = 0.0 | |
| var cpoint = CGPoint() | |
| var mpoint = CGPoint() | |
| var qswitch:Bool = false | |
| var qswitch2:Bool = false | |
| var qswitch3:Bool = false | |
| class ParserBase : NSObject, XMLParserDelegate { | |
| var currentElement:String = "" | |
| var foundCharacters = "" | |
| weak var parent:ParserBase? = nil | |
| func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) { | |
| currentElement = elementName | |
| } | |
| func parser(_ parser: XMLParser, foundCharacters string: String) { | |
| self.foundCharacters += string | |
| } | |
| } | |
| class SVG : ParserBase { | |
| var id = "" | |
| var groups = [Group]() | |
| override func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) { | |
| print("processing <\(elementName)> tag from SVG") | |
| if elementName == "svg" { | |
| if let id = String?(attributeDict["id"]!) { | |
| self.id = id | |
| print(id) | |
| } | |
| } | |
| if elementName == "g" { | |
| let group = Group() | |
| self.groups.append(group) | |
| parser.delegate = group | |
| group.parent = self | |
| } | |
| } | |
| } | |
| class Group : ParserBase { | |
| var path = "" | |
| override func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) { | |
| print("processing <\(elementName)> tag from Group") | |
| if elementName == "path" { | |
| if let d = String?(attributeDict["d"]!) { | |
| self.path.append(d) | |
| } | |
| parser.delegate = self | |
| } | |
| foundCharacters = "" | |
| } | |
| } | |
| let xmlData = content.data(using: String.Encoding.utf8) | |
| let parser = XMLParser(data: xmlData!) | |
| let svg = SVG() | |
| parser.delegate = svg | |
| parser.parse() | |
| var commandBuffer:String = "" | |
| var commandWindow:Bool = false | |
| func closePath() | |
| { | |
| path.addPath(compositePath) | |
| compositePath = CGMutablePath() | |
| commandWindow = false | |
| //print("path closed") | |
| } | |
| func moveTo (_ point: String) | |
| { | |
| //let pathShape = shapeArray[0] | |
| let coords = point.characters.split(separator: ",") | |
| if(commandWindow == false) | |
| { | |
| pathPointX += (String(coords[0]) as NSString).floatValue | |
| pathPointY += (String(coords[1]) as NSString).floatValue | |
| mpoint.x = CGFloat(pathPointX) | |
| mpoint.y = CGFloat(pathPointY) | |
| compositePath.move(to: mpoint) | |
| //print("Move To:") | |
| //print(mpoint) | |
| //print(pathPointX,pathPointY) | |
| commandWindow = true | |
| } | |
| else | |
| { | |
| pathPointX += (String(coords[0]) as NSString).floatValue | |
| pathPointY += (String(coords[1]) as NSString).floatValue | |
| mpoint.x = CGFloat(pathPointX) | |
| mpoint.y = CGFloat(pathPointY) | |
| compositePath.addLine(to: mpoint) | |
| //print(mpoint) | |
| //print("Move To Draw Line:") | |
| //print(pathPointX,pathPointY) | |
| } | |
| } | |
| func moveToAbsolute (_ point: String) | |
| { | |
| //let pathShape = shapeArray[0] | |
| let coords = point.characters.split(separator: ",") | |
| if(commandWindow == false) | |
| { | |
| pathPointX = (String(coords[0]) as NSString).floatValue | |
| pathPointY = (String(coords[1]) as NSString).floatValue | |
| mpoint.x = CGFloat(pathPointX) | |
| mpoint.y = CGFloat(pathPointY) | |
| compositePath.move(to: mpoint) | |
| //print("Move To Absolute:") | |
| //print(mpoint) | |
| //print(pathPointX,pathPointY) | |
| commandWindow = true | |
| } | |
| else | |
| { | |
| pathPointX = (String(coords[0]) as NSString).floatValue | |
| pathPointY = (String(coords[1]) as NSString).floatValue | |
| mpoint.x = CGFloat(pathPointX) | |
| mpoint.y = CGFloat(pathPointY) | |
| compositePath.addLine(to: mpoint) | |
| //print(mpoint) | |
| //print("Move To Draw Line:") | |
| //print(pathPointX,pathPointY) | |
| } | |
| } | |
| func quadCurve (_ point: String) | |
| { | |
| //these things come in 3s | |
| let coords = point.characters.split(separator: ",") | |
| if(qswitch == false && qswitch2 == false && qswitch3 == false){ | |
| qpathPointCX = pathPointX | |
| qpathPointCY = pathPointY | |
| qpathPointCX += (String(coords[0]) as NSString).floatValue | |
| qpathPointCY += (String(coords[1]) as NSString).floatValue | |
| qswitch = true | |
| return | |
| } | |
| if(qswitch2 == false && qswitch == true && qswitch3 == false){ | |
| qpathPointX = pathPointX | |
| qpathPointY = pathPointY | |
| qpathPointX += (String(coords[0]) as NSString).floatValue | |
| qpathPointY += (String(coords[1]) as NSString).floatValue | |
| mpoint.x = CGFloat(qpathPointX) | |
| mpoint.y = CGFloat(qpathPointY) | |
| cpoint.x = CGFloat(qpathPointCX) | |
| cpoint.y = CGFloat(qpathPointCY) | |
| //print("quadcurve:") | |
| //print(pathPointX,pathPointY,qpathPointCX,qpathPointCY,qpathPointX,qpathPointY) | |
| compositePath.addQuadCurve(to: mpoint, control: cpoint) | |
| qswitch2 = true | |
| return | |
| } | |
| if(qswitch == true && qswitch2 == true && qswitch3 == false){ | |
| qpathPointCX = qpathPointX + (String(coords[0]) as NSString).floatValue | |
| qpathPointCY = qpathPointY + (String(coords[1]) as NSString).floatValue | |
| qswitch3 = true | |
| return | |
| } | |
| if(qswitch == true && qswitch2 == true && qswitch3 == true){ | |
| qpathPointX = qpathPointX + (String(coords[0]) as NSString).floatValue | |
| qpathPointY = qpathPointY + (String(coords[1]) as NSString).floatValue | |
| mpoint.x = CGFloat(qpathPointX) | |
| mpoint.y = CGFloat(qpathPointY) | |
| cpoint.x = CGFloat(qpathPointCX) | |
| cpoint.y = CGFloat(qpathPointCY) | |
| compositePath.addQuadCurve(to: mpoint, control: cpoint) | |
| qswitch3 = false | |
| pathPointX = qpathPointX | |
| pathPointY = qpathPointY | |
| return | |
| } | |
| } | |
| func drawLine (_ point: String) | |
| { | |
| let coords = point.characters.split(separator: ",") | |
| pathPointX += (String(coords[0]) as NSString).floatValue | |
| pathPointY += (String(coords[1]) as NSString).floatValue | |
| mpoint.x = CGFloat(pathPointX) | |
| mpoint.y = CGFloat(pathPointY) | |
| compositePath.addLine(to: mpoint) | |
| commandWindow = false | |
| qswitch = false | |
| qswitch2 = false | |
| qswitch3 = false | |
| } | |
| func getDescription (_ descriptorValue: String.CharacterView) | |
| { | |
| //print(String(descriptorValue)) | |
| let command = String(descriptorValue) | |
| let commandList = ["c","C","h","H","l","L","m","M","q","Q","s","S","t","T","z","Z"] | |
| if(commandBuffer != "" && !commandList.contains(command)) | |
| { | |
| //print("Command Buffer is "+commandBuffer) | |
| switch commandBuffer { | |
| case "MoveTo":moveTo(command) | |
| case "MoveToAbsolute":moveToAbsolute(command) | |
| case "QuadCurve":quadCurve(command) | |
| case "DrawLine":drawLine(command) | |
| default: break | |
| } | |
| } | |
| switch command { | |
| case "c": break | |
| case "C": break | |
| case "h": break | |
| case "H": break | |
| case "l": commandBuffer = "DrawLine" | |
| case "L": break | |
| case "m": commandBuffer = "MoveTo" | |
| case "M": commandBuffer = "MoveToAbsolute" | |
| closePath() | |
| case "q": commandBuffer = "QuadCurve" | |
| case "Q": break | |
| case "s": break | |
| case "S": break | |
| case "t": break | |
| case "T": break | |
| case "z": closePath() | |
| case "Z": break | |
| default: break | |
| } | |
| } | |
| for group in svg.groups { | |
| //This should have a some way to describe yes we have a path | |
| //print("group path = \(group.path)") | |
| let pathSplit = group.path.characters.split(separator: " ") | |
| pathSplit.forEach { getDescription($0) } | |
| } | |
| closePath() | |
| let effect = SKEffectNode() | |
| var shape = SKShapeNode.init(path: path) | |
| path = CGMutablePath() | |
| shape.isAntialiased = true | |
| shape.setScale(CGFloat(0.8)) | |
| shape.strokeColor = .black | |
| //shape.fillColor = .cyan | |
| shape.yScale = -shape.yScale | |
| shape.position = midPoint | |
| effect.addChild(shape) | |
| let blurFilter = CIFilter(name:"CIGaussianBlur", | |
| withInputParameters: ["inputRadius": 1]) | |
| effect.filter = blurFilter | |
| scene.addChild(effect) | |
| scene.backgroundColor = .white | |
| view.presentScene(scene) | |
| PlaygroundSupport.PlaygroundPage.current.liveView = view | |
| PlaygroundPage.current.needsIndefiniteExecution = true | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment