Graphics.DrawSVG method

Awesome work Alwyn and contributors!!

Well you learn something every day :slight_smile:

Thanks Mike. Work not fully done yet, but almost there :wink:

[quote=229179:@Alwyn Bester]
Brock, I hope you don’t mind, I’ve added your test images to the test folder on GitHub?[/quote]
Not at all :smiley:

Here are some more examples of ones not rendering even after the update:

“Bug Icon” - Notice how the right part of his body renders the wrong way

<?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <g id="Layer_2"> <path d="M20.2,9.7c0-1.9,1.5-3.4,3.4-3.4c1.9,0,3.4,1.5,3.4,3.4"/> <g> <path d="M35,27.8c2.3,0,4.5,0,6.8,0c2.3,0,2.3-3.5,0-3.5c-2.3,0-4.5,0-6.8,0C32.8,24.3,32.8,27.8,35,27.8L35,27.8z"/> </g> <g> <path d="M34.2,32.2c1.7,0.8,3.5,1.5,5.2,2.3c0.9,0.4,1.9,0.3,2.4-0.6c0.4-0.7,0.2-2-0.6-2.4c-1.7-0.8-3.5-1.5-5.2-2.3 c-0.9-0.4-1.9-0.3-2.4,0.6C33.1,30.6,33.3,31.8,34.2,32.2L34.2,32.2z"/> </g> <g> <path d="M31,37.7c2.2,1,4.4,2,6.6,2.9c2,0.9,3.8-2.1,1.8-3c-2.2-1-4.4-2-6.6-2.9C30.7,33.8,28.9,36.8,31,37.7L31,37.7z"/> </g> <g> <g> <path d="M12.6,24.3c-2.3,0-4.5,0-6.8,0c-2.3,0-2.3,3.5,0,3.5c2.3,0,4.5,0,6.8,0C14.8,27.8,14.8,24.3,12.6,24.3L12.6,24.3z"/> </g> <g> <path d="M11.7,29.2c-1.7,0.8-3.5,1.5-5.2,2.3c-0.9,0.4-1.1,1.6-0.6,2.4c0.5,0.9,1.5,1,2.4,0.6c1.7-0.8,3.5-1.5,5.2-2.3 c0.9-0.4,1.1-1.6,0.6-2.4C13.5,28.9,12.5,28.8,11.7,29.2L11.7,29.2z"/> </g> <g> <path d="M14.9,34.7c-2.2,1-4.4,2-6.6,2.9c-2.1,0.9-0.3,3.9,1.8,3c2.2-1,4.4-2,6.6-2.9C18.7,36.8,16.9,33.8,14.9,34.7L14.9,34.7z" /> </g> </g> <g> <path d="M30,12.6c1.6-1.8,3.2-3.6,4.8-5.3C35.9,6,34.1,4.2,33,5.4c-1.6,1.8-3.2,3.6-4.8,5.3C27.1,12,28.9,13.9,30,12.6L30,12.6z" /> </g> <g> <path d="M19.4,10.8c-1.6-1.8-3.2-3.6-4.8-5.3c-1.1-1.3-3,0.6-1.9,1.9c1.6,1.8,3.2,3.6,4.8,5.3C18.7,13.9,20.5,12,19.4,10.8 L19.4,10.8z"/> </g> <path d="M35,18.4C32.9,12.8,28.6,9,23.6,9s-9.3,3.8-11.4,9.4H35z"/> <path d="M21.4,22.1H11.2c-0.2,1.3-0.4,2.6-0.4,4c0,8.4,4.6,15.4,10.6,16.8L21.4,22.1L21.4,22.1z"/> <path d="M36.1,22.1H25.8V43c6-1.4,10.6-8.4,10.6-16.9C36.4,24.8,36.3,23.4,36.1,22.1z"/> </g> </svg>

“Add - Icon” Notice how the up-down part of the “+” is too short

<?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <g id="AddIcon_1_"> <path d="M24,4c-11.1,0-20,9-20,20C4,35.1,12.9,44,24,44s20-9,20-20.1C44,12.9,35.1,4,24,4z M24,40.4C15,40.4,7.6,33,7.6,24 c0-9,7.4-16.4,16.4-16.4S40.4,14.9,40.4,24C40.4,33,33,40.4,24,40.4z"/> <path d="M31,22.4h-5.4v-5.8c0-0.8-0.8-1.5-1.6-1.5s-1.6,0.7-1.6,1.5v5.8h-5.8c-0.8,0-1.5,0.8-1.5,1.6s0.7,1.6,1.5,1.6h5.8V31 c0,0.8,0.8,1.5,1.6,1.5s1.6-0.7,1.6-1.5v-5.4H31c0.8,0,1.5-0.8,1.5-1.6S31.8,22.4,31,22.4z"/> </g> </svg>

Here are some others…

<?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <g id="Layer_2"> <g> <g> <path d="M44,14.9v-2.1c0-2.1-1.7-3.7-3.7-3.7H7.7C5.7,9.1,4,10.8,4,12.8v2.1H44z"/> <path d="M4,21.6v13.6c0,2.1,1.7,3.7,3.7,3.7h32.6c2.1,0,3.7-1.7,3.7-3.7V21.6H4z M23.4,33.5H9.4c-0.8,0-1.4-0.6-1.4-1.4 c0-0.8,0.6-1.4,1.4-1.4h14.1c0.8,0,1.4,0.6,1.4,1.4C24.8,32.9,24.2,33.5,23.4,33.5z M38.7,28.3H9.4c-0.8,0-1.4-0.6-1.4-1.4 c0-0.8,0.6-1.4,1.4-1.4h29.3c0.8,0,1.4,0.6,1.4,1.4C40.1,27.7,39.5,28.3,38.7,28.3z"/> </g> </g> </g> </svg>

<?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <g id="Layer_2"> <g> <path d="M42,15.9c0-0.3-0.1-0.5-0.4-0.7s-0.5-0.1-0.8,0L26,23.9c-0.8,0.5-1.3,1.3-1.3,2.2v17.2c0,0.3,0.1,0.5,0.4,0.7 c0.2,0.1,0.5,0.1,0.8,0l14.3-8.3c1.1-0.7,1.8-1.9,1.8-3.2V15.9z"/> <path d="M7.2,15.3c-0.2-0.1-0.5-0.1-0.8,0C6.2,15.4,6,15.7,6,15.9c0,0,0,0,0,0v16.5c0,1.3,0.7,2.5,1.8,3.2l14.3,8.3c0,0,0,0,0,0 c0.2,0.1,0.5,0.1,0.8,0c0.2-0.1,0.4-0.4,0.4-0.7V26.1c0-0.9-0.5-1.8-1.3-2.2L7.2,15.3z"/> <path d="M40.1,14.1c0.2-0.1,0.4-0.4,0.4-0.7c0-0.3-0.1-0.5-0.4-0.7c0,0,0,0,0,0L25.8,4.5c-1.1-0.7-2.6-0.7-3.7,0L7.9,12.7 c0,0,0,0,0,0c-0.2,0.1-0.4,0.4-0.4,0.7c0,0.3,0.1,0.5,0.4,0.7l14.9,8.6c0.8,0.5,1.8,0.5,2.6,0L40.1,14.1z"/> </g> </g> </svg>

<?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <g id="Layer_2"> <path d="M39,19c0.1-0.4,0.1-0.8,0.1-1.3c0-5.4-4.4-9.8-9.8-9.8c-3.2,0-6,1.6-7.8,3.9c-0.6-0.2-1.3-0.3-2-0.3 c-4.7,0-8.5,3.8-8.5,8.5c0,0.1,0,0.3,0,0.4c-3.5,1-6.1,4.3-6.1,8.2c0,4.7,3.8,8.5,8.5,8.5h20.8c5.4,0,9.8-4.4,9.8-9.8 C44,23.8,42,20.7,39,19z M14.7,25h2.4c0-4,3.3-7.3,7.3-7.3c1.5,0,2.8,0.4,4,1.2l-1.5,2c-0.7-0.4-1.6-0.7-2.5-0.7 c-2.7,0-4.9,2.2-4.9,4.9H22l-3.7,4.9L14.7,25z M31.8,25c0,4-3.3,7.3-7.3,7.3c-1.5,0-2.8-0.4-4-1.2l1.5-2c0.7,0.4,1.6,0.7,2.5,0.7 c2.7,0,4.9-2.2,4.9-4.9h-2.4l3.7-4.9l3.7,4.9H31.8z"/> </g> </svg>

@Alwyn Bester I’m still building up the framework. It is based on SpriteKit and uses actions to simplify movement.

Sample methods

[code]Sub BuildPlayer()
// Create Tank Sprite

dim tankSize as new xojo.Core.Size(tankBlue.Width * Scene.xFactor, tankBlue.Height * Scene.yFactor)

dim tankPosition as new Vector(scene.Width/2,scene.Height/2)

Player = new SpriteNodePF(tankBlue, tankPosition, tankSize)

Player.Name = “Player”

Player.zPosition = 100

// set speed and rotation speed of player
Player.SpeedPixelsPerSecond = GetPref(“PlayerSpeed”,80)
Player.RotationRadiansPerSecond = GetPref(“PlayerRotation”,0.5)

// Add barrel Sprite
Dim barrelHeight as Double = barrelBlue.Height * Scene.yFactor
dim barrelWidth As Double = barrelBlue.Width * Scene.xFactor
dim barrelSize as new xojo.Core.Size(barrelWidth, barrelHeight)

// Center the bottom center of the barrel to the middle of the tank
dim barrel as new SpriteNodePF(barrelBlue, tankPosition - new vector(0, barrelHeight/2), barrelSize)

barrel.Name = “barrel”

// make the bottom center of the barrel the anchor point
barrel.AnchorPoint = new Vector(0.5,1.0)

barrel.zPosition = 60

// rotation speed for barrel
barrel.RotationRadiansPerSecond = GetPref(“PlayerBarrelRotation”,0.7)

// add barrel to Player
Player.AddChild barrel

// keyboard actions - key presses will pause/unpause as required
Dim act As Action

act = new rotateCW
act.Key = “CW”
act.Paused = true
player.Actions.Append act
barrel.Actions.Append act.Clone

act = new rotateCCW
act.Key = “CCW”
act.Paused = true
player.Actions.Append act
barrel.Actions.Append act.Clone

act = new Move
act.Key = “FWD”
act.Paused = true
player.Actions.Append act

act = new Move
act.Key = “RVS”
act.Paused = true
player.Actions.Append act

me.Scene.AddChild(Player)

End Sub
[/code]

[code]Sub SpawnEnemy(sender As Xojo.Core.Timer)
// Create Tank Sprite

// 10 enemy limit
Dim hittanks() As SpriteNodePF = scene.EnumerateChildNodesWithName(“tank”)
if hittanks.Ubound < 9 then
dim tankSize as new xojo.Core.Size(tankGreen.Width * Scene.xFactor, tankGreen.Height * Scene.yFactor)

// start tank outside visible area (600 x 600)
// spawn points range from -100 to -25 and 625 to 700
// they are a shuffled array
dim x,y As Double

x = xojo.math.RandomInt(0,151)
y = xojo.math.RandomInt(0,151)

dim tankPosition as new Vector(SpawnPoints(x), SpawnPoints(y))

//create sprite
dim TankSprite as new SpriteNodePF(tankGreen, tankPosition, tankSize)
TankSprite.Name = "tank"
TankSprite.zPosition = 20
TankSprite.Rotation = DegreesToRadians(xojo.math.RandomInt(0,359))
// tank speed and rotation speed
TankSprite.SpeedPixelsPerSecond = GetPref("EnemySpeed",60)
TankSprite.RotationRadiansPerSecond = GetPref("EnemyRotation",0.3)

// actions for tank
// move to a random location on the screen and pause for .1 second
// Repeat 100 times
dim actseq As new ActionSequence(new MoveRandom(25,575,25,575), new Pause(0.1))
Dim actRep As New RepeatAction(actseq,100)
TankSprite.Actions.Append actRep
me.Scene.AddChild(TankSprite)

// Add barrel Sprite
Dim barrelHeight as Double = barrelGreen.Height * Scene.yFactor
dim barrelWidth As Double = barrelGreen.Width * Scene.xFactor
dim barrelSize as new xojo.Core.Size(barrelWidth, barrelHeight)
// Center the bottom center of the barrel to the middle of the tank
dim barrel as new SpriteNodePF(barrelGreen, tankPosition - new vector(0, barrelHeight/2), barrelSize)
barrel.Name = "barrel"
// make the bottom center of the barrel the anchor point
barrel.AnchorPoint = new Vector(0.5,1.0)
barrel.zPosition = 60
barrel.RotationRadiansPerSecond = GetPref("EnemyBarrelRotation",0.5)
// Create and add actions to barrel
// Rotate barrel to player position, fire and reload (3 seconds)
// Repeat 100 times
dim aimAndShoot as new ActionSequence(new RotateToTarget(Player),New Shoot, New Pause(GetPref("EnemyReloadSpeed",3.0)))
barrel.Actions.Append new RepeatAction(aimAndShoot,100)
// add barrel to tank
TankSprite.AddChild barrel

end if
End Sub
[/code]

Here is a little tank game I’m using to test things. (Set preferences to adjust difficulty)

OS X version
Win32 version

A,S,W,D to move / rotate tank
Left/Right arrows to rotate barrel
Spacebar to shoot

Game is smooth.
But I’m dead a lot… :wink:

[quote=229362:@Peter Fargo]@Alwyn Bester I’m still building up the framework. It is based on SpriteKit and uses actions to simplify movement.

Sample methods

[code]Sub BuildPlayer()
// Create Tank Sprite

dim tankSize as new xojo.Core.Size(tankBlue.Width * Scene.xFactor, tankBlue.Height * Scene.yFactor)

dim tankPosition as new Vector(scene.Width/2,scene.Height/2)

Player = new SpriteNodePF(tankBlue, tankPosition, tankSize)

Player.Name = “Player”

Player.zPosition = 100

// set speed and rotation speed of player
Player.SpeedPixelsPerSecond = GetPref(“PlayerSpeed”,80)
Player.RotationRadiansPerSecond = GetPref(“PlayerRotation”,0.5)

// Add barrel Sprite
Dim barrelHeight as Double = barrelBlue.Height * Scene.yFactor
dim barrelWidth As Double = barrelBlue.Width * Scene.xFactor
dim barrelSize as new xojo.Core.Size(barrelWidth, barrelHeight)

// Center the bottom center of the barrel to the middle of the tank
dim barrel as new SpriteNodePF(barrelBlue, tankPosition - new vector(0, barrelHeight/2), barrelSize)

barrel.Name = “barrel”

// make the bottom center of the barrel the anchor point
barrel.AnchorPoint = new Vector(0.5,1.0)

barrel.zPosition = 60

// rotation speed for barrel
barrel.RotationRadiansPerSecond = GetPref(“PlayerBarrelRotation”,0.7)

// add barrel to Player
Player.AddChild barrel

// keyboard actions - key presses will pause/unpause as required
Dim act As Action

act = new rotateCW
act.Key = “CW”
act.Paused = true
player.Actions.Append act
barrel.Actions.Append act.Clone

act = new rotateCCW
act.Key = “CCW”
act.Paused = true
player.Actions.Append act
barrel.Actions.Append act.Clone

act = new Move
act.Key = “FWD”
act.Paused = true
player.Actions.Append act

act = new Move
act.Key = “RVS”
act.Paused = true
player.Actions.Append act

me.Scene.AddChild(Player)

End Sub
[/code]

[code]Sub SpawnEnemy(sender As Xojo.Core.Timer)
// Create Tank Sprite

// 10 enemy limit
Dim hittanks() As SpriteNodePF = scene.EnumerateChildNodesWithName(“tank”)
if hittanks.Ubound < 9 then
dim tankSize as new xojo.Core.Size(tankGreen.Width * Scene.xFactor, tankGreen.Height * Scene.yFactor)

// start tank outside visible area (600 x 600)
// spawn points range from -100 to -25 and 625 to 700
// they are a shuffled array
dim x,y As Double

x = xojo.math.RandomInt(0,151)
y = xojo.math.RandomInt(0,151)

dim tankPosition as new Vector(SpawnPoints(x), SpawnPoints(y))

//create sprite
dim TankSprite as new SpriteNodePF(tankGreen, tankPosition, tankSize)
TankSprite.Name = "tank"
TankSprite.zPosition = 20
TankSprite.Rotation = DegreesToRadians(xojo.math.RandomInt(0,359))
// tank speed and rotation speed
TankSprite.SpeedPixelsPerSecond = GetPref("EnemySpeed",60)
TankSprite.RotationRadiansPerSecond = GetPref("EnemyRotation",0.3)

// actions for tank
// move to a random location on the screen and pause for .1 second
// Repeat 100 times
dim actseq As new ActionSequence(new MoveRandom(25,575,25,575), new Pause(0.1))
Dim actRep As New RepeatAction(actseq,100)
TankSprite.Actions.Append actRep
me.Scene.AddChild(TankSprite)

// Add barrel Sprite
Dim barrelHeight as Double = barrelGreen.Height * Scene.yFactor
dim barrelWidth As Double = barrelGreen.Width * Scene.xFactor
dim barrelSize as new xojo.Core.Size(barrelWidth, barrelHeight)
// Center the bottom center of the barrel to the middle of the tank
dim barrel as new SpriteNodePF(barrelGreen, tankPosition - new vector(0, barrelHeight/2), barrelSize)
barrel.Name = "barrel"
// make the bottom center of the barrel the anchor point
barrel.AnchorPoint = new Vector(0.5,1.0)
barrel.zPosition = 60
barrel.RotationRadiansPerSecond = GetPref("EnemyBarrelRotation",0.5)
// Create and add actions to barrel
// Rotate barrel to player position, fire and reload (3 seconds)
// Repeat 100 times
dim aimAndShoot as new ActionSequence(new RotateToTarget(Player),New Shoot, New Pause(GetPref("EnemyReloadSpeed",3.0)))
barrel.Actions.Append new RepeatAction(aimAndShoot,100)
// add barrel to tank
TankSprite.AddChild barrel

end if
End Sub
[/code]

Here is a little tank game I’m using to test things. (Set preferences to adjust difficulty)

OS X version
Win32 version

A,S,W,D to move / rotate tank
Left/Right arrows to rotate barrel
Spacebar to shoot[/quote]
Cool Peter!!! Very nice and its challenging meaning I get killed alot :slight_smile:

Also I hit an un-handled exception when you press the space bar before you press new game on mac.

Awesome job!

I’m starting to amass a collection of SVG files, I’ve got some really complex ones, that I’m having trouble converting to PDF. When you’re ready I’ll post them online for you to test with.

I’ve just acquired a 6 mb SVG image, which I currently can’t convert!

I converted my tank body to SVG but it does not render. I’m really looking forward to testing this.

[code]<?xml version="1.0" standalone="no"?>

[/code]

Thanks for all the test SVG files everyone… please keep 'em coming :slight_smile: it helps a lot to fast track the development.

I’ve got some of these fixed already, and are busy working on the rest. Will post here as soon as I have more info. I’ll probably only get round to continuing work on Monday though.

Awesome, that would be much appreciated. Will let you know once I’ve got all the existing known issues covered.

The latest version that I just pushed to GitHub renders your tank now.

Thanks Alwyn. This is really shaping up nicely (no surprise there)! I’ve got another that does render but the interior detail is messed up.

[code]<?xml version="1.0" standalone="no"?>

[/code]

Thanks Peter, I’ve added the SVG to the list of test images.

The inside details are all messed up because I still need to find a way to draw FigureShapes that effectively uses "PenUp/“PenDown” instructions.

It affects a few images, so I hope to find a solution soon. Will keep you posted.

As curious as I am, I decided to get an eye on Peter last shared image.

So, I copy/paste the text from here into Apple’s TextEdit, save it to svg, go to the Finder and use Quick Look feature to watch its contents: nice !

BTW: svg default application (to open it) is Safari, here; Open with does not propose Apple’s TextEdit (drop the svg files on TextEdit application).

I subclassed my sprite node as an svg node and after a healthy dose of svg education I’ve got them playing nicely along with other sprites. I still think I’m going to have to bite the bullet and deal with openGL to get the frame rates up. Several forays in that realm have only resulted in headaches for me though :frowning:

@Alwyn Bester Amazing job on the DrawSVG module. Kudos and thanks.

Glad you like Peter :wink:

The last SVG that you posted should now also render correctly (just get the latest version from GitHub).

My first goal with the DrawSVG is to get something functional in place. But at some stage for the best possible quality and speed, I will probably have to look into using declares for the rendering.

Brock, I’m still looking into some of your images that are creating unwanted artifacts when rendered.

Ok, got the unwanted artifacts fixed. This was tough nut to crack, for the issue is caused by the FigureShape not supporting PenUp/PenDown commands.

I had to implement a debatable “hack”/“workaround” to accommodate for the missing feature, but it seems to do the trick for now. I’ll revisit this issue again when I get to using declares for rendering.

All the SVGs posted in this conversation up until now should render correctly with the latest version on GitHub. Feel free to send through any other SVG data that is not rendering as it should.

l will now continue with the implementation of the Arc and Bezier Curve path commands.

I have a bunch that are still messed up but this might be related to the Arc/Bezier Curve path commands so I’ll plan on waiting until these are done before I report that they’re not rending right.

1 Like

@Alwyn Bester – I have a suggestion. You may want to raise an exception if the XML is invalid. It’s odd when it just doesn’t draw anything.