Skip to content

Instantly share code, notes, and snippets.

@wolfspider
Created September 30, 2017 21:39
Show Gist options
  • Select an option

  • Save wolfspider/ccfd47483e7fb231b327a40e6121c575 to your computer and use it in GitHub Desktop.

Select an option

Save wolfspider/ccfd47483e7fb231b327a40e6121c575 to your computer and use it in GitHub Desktop.
Swift SVG playground
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
//: 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