I have found some codes to loadSVG, but I haven' t found a code to save an SVG document.
So, I have try to start a SaveSVG() procedure.
It doesn't cover all the SVG features, but it work for the main vectordrawing lib features :
- shape : box, circle, ellipse, line, curve, text
- Paint : fill, stroke (not dash or point for the moment)
- color + alpha (fill and stroke)
- Stroke flag : #PB_Path_RoundEnd, #PB_Path_SquareEnd, #PB_Path_RoundCorner
For the moment it doesn't save gradient and other feature like transformation coordonate (scale, rotation...).
I hope to add it soon.
I will integrated this code in my open-source 2D vectordrawing application "cartoon" (made in purebasic of course

Cheers

Code: Select all
; Save SVG from vectorlib
; blendman 2021
Enumeration
; shape typ
#ShapeTypBox = 0
#ShapeTypCircle
#ShapeTypLine
#ShapeTypCurve
#ShapeTypEllipse
#ShapeTypText
; stroketyp
#StrokeTypFill = 0
#StrokeTypStroke
#StrokeTypDash
#StrokeTypPoint
EndEnumeration
Structure sShape
Startx.w
Starty.w
x.w
y.w
w.w
h.w
text$
; for curve
x1.w
y1.w
x2.w
y2.w
EndStructure
Structure sSVG_line
Segment$ ; infos about the shape
shapetyp.a ; 0 = rect,1=circle,2=line,3=curve
shape.sShape
Strokecolor.i
strokesize.w
strokeColorTyp.a ; 0=Color, 1 = gradient linear, 2= gradient circular, 3= texture
strokeTyp.a ; 0=fill, 1=stroke, 2= dash, 3=point
strokeflag.a
strokeAlpha.a
EndStructure
Global NewList SVGLine.sSvg_Line()
Procedure VD_AddShape(typ.a,startx.d,starty.d,x.d,y.d,w.d,h.d,color,stroketyp.a,size.w,
alpha.a=255,txt$="",strokeflag=#PB_Path_RoundEnd,x1=0,y1=0,x2=0,y2=0)
;MovePathCursor(x, y)
Select typ
Case #ShapeTypBox
AddPathBox(x,y,w,h)
Case #ShapeTypCircle
AddPathCircle(x,y,w)
Case #ShapeTypEllipse
AddPathEllipse(x,y,w,h)
Case #ShapeTypLine
MovePathCursor(startx, starty)
AddPathLine(x,y)
Case #ShapeTypCurve
MovePathCursor(startx,starty)
AddPathCurve(x,y,x1,y1,x2,y2)
Case #ShapeTypText
VectorFont(FontID(0),size)
VectorSourceColor(RGBA(Red(color),Green(color),Blue(color), alpha))
MovePathCursor(startx,starty)
DrawVectorText(txt$)
EndSelect
If typ <> #ShapeTypText
VectorSourceColor(RGBA(Red(color),Green(color),Blue(color), alpha))
If stroketyp = #StrokeTypFill
FillPath()
ElseIf stroketyp = #StrokeTypStroke
StrokePath(size, strokeflag)
EndIf
EndIf
; then save the shape
AddElement(SVGLine())
SVGLine()\Segment$ = PathSegments()
SVGLine()\shapetyp = typ ; ellipse
SVGLine()\Strokecolor = color
SVGLine()\strokesize = size
SVGLine()\strokeTyp = stroketyp ; stroke
SVGLine()\strokeColorTyp = 0 ; for the moment only color (not gradient...)
SVGLine()\strokeflag = strokeflag
SVGLine()\strokeAlpha = alpha
SVGLine()\shape\startx = startx
SVGLine()\shape\starty = starty
SVGLine()\shape\x = x
SVGLine()\shape\y = y
SVGLine()\shape\w = w
SVGLine()\shape\h = h
SVGLine()\shape\text$ = txt$
; for curve
SVGLine()\shape\x1 = x1
SVGLine()\shape\y1 = y1
SVGLine()\shape\x2 = x2
SVGLine()\shape\y2 = y2
EndProcedure
Procedure Save_SVG(Title$="",desc$="",w=1200,h=400,zoom=100)
;date$ = FormatDate("%yyyy%mm%dd%hh%ii%ss", Date())
date$ = FormatDate("%yyyy%mm%dd", Date())
z.d = zoom*0.01
file$ = "TestSVG"+date$+".svg"
If CreateFile(0,GetCurrentDirectory()+file$)
d$ = Chr(34)
; save infos for svg
WriteStringN(0, "<?xml version="+d$+"1.0"+d$+" encoding="+d$+"utf-8"+d$+" ?>")
WriteStringN(0, "<!-- Created with Purebasic -->")
WriteStringN(0, "")
WriteStringN(0, "<svg xmlns="+d$+"http://www.w3.org/2000/svg"+d$+" version="+d$+"1.1"+d$+" width="+d$+Str(w*z)+d$+" height="+d$+Str(h*z)+d$+">")
WriteStringN(0, " <title>"+Title$+"</title>")
WriteStringN(0, " <desc>"+desc$+"</desc>")
; Here, save the informations about shape, color...
ForEach SVGLine()
With SVGLine()
text$= " "
; color
color$ = d$+"rgb("+Str(Red(\Strokecolor))+","+Str(Green(\Strokecolor))+","+Str(Blue(\Strokecolor))+")"+d$
; fill-opacity="0.5" stroke-opacity="0.8"
stroketyp$ = "fill="+color$
If \strokeTyp = #StrokeTypStroke And \shapetyp <> #ShapeTypText
stroketyp$ = "fill="+d$+"none"+d$+" stroke="+color$+" stroke-width="+d$+Str(\strokesize)+d$+" stroke-opacity="+d$+StrD(\strokeAlpha/255,2)+d$
If \strokeflag =#PB_Path_RoundEnd Or \strokeflag = #PB_Path_RoundCorner
stroketyp$ + " stroke-linecap="+d$+ "round"+d$ + " stroke-linejoin="+d$+ "round"+d$
ElseIf \strokeflag =#PB_Path_SquareEnd
stroketyp$ + " stroke-linecap="+d$+ "square"+d$+ " stroke-linejoin="+d$+ "square"+d$
EndIf
ElseIf \strokeTyp = #StrokeTypFill
stroketyp$ +" fill-opacity="+d$+StrD(\strokeAlpha/255,2)+d$
If \shapetyp <> #ShapeTypText
If \strokeflag =#PB_Path_RoundEnd
stroketyp$ + " stroke-linejoin="+d$+ "round"+d$
ElseIf \strokeflag =#PB_Path_SquareEnd
stroketyp$ + " stroke-linejoin="+d$+ "square"+d$
EndIf
EndIf
EndIf
Select \shapetyp
Case #ShapeTypBox
text$ +"<rect x="+d$+Str(\shape\x)+d$+" y="+d$+Str(\shape\y)+d$+" width="+d$+Str(\shape\w)+d$+" height="+d$+Str(\shape\h)+d$+
" "+stroketyp$+" />"
WriteStringN(0, text$)
Case #ShapeTypCircle
text$ +"<circle cx="+d$+Str(\shape\x)+d$+" cy="+d$+Str(\shape\y)+d$+" r="+d$+Str(\shape\w)+d$+" "+stroketyp$+" />"
WriteStringN(0, text$)
Case #ShapeTypLine
text$ +"<line x1="+d$+Str(\shape\startx)+d$+" x2="+d$+Str(\shape\x)+d$+" y1="+d$+Str(\shape\Starty)+d$+" y2="+d$+Str(\shape\y)+
d$+" "+stroketyp$+" />"
WriteStringN(0, text$)
Case #ShapeTypCurve
; <path d="M 10 10 C 20 20, 40 20, 50 10"/>
text$ +"<path d="+d$+"M "+Str(\shape\startx)+" "+Str(\shape\Starty)+" C "+Str(\shape\x)+" "+Str(\shape\y)+" "+
Str(\shape\x1)+" "+Str(\shape\y1)+" "+Str(\shape\x2)+" "+Str(\shape\y2)+d$
text$+" "+stroketyp$+" />"
WriteStringN(0, text$)
Case #ShapeTypText
; <text x="10" y="10">Hello World!</text>
text$ +"<text dominant-baseline="+d$+"hanging"+d$+" x="+d$+Str(\shape\startx)+d$+" y="+d$+Str(\shape\starty)+d$+" font-size="+d$+Str(\strokesize)+d$+" "+stroketyp$+" >"+\shape\text$+"</text>"
WriteStringN(0, text$)
Case #ShapeTypEllipse
; text$ =" <g transform="+d$+"translate("+Str(\shape\x)+" "+Str(\shape\y)+")"+d$+">"
; WriteStringN(0, text$)
text$ +"<ellipse cx="+d$+Str(\shape\x)+d$+" cy="+d$+Str(\shape\y)+d$+" rx="+d$+Str(\shape\w)+d$+" ry="+d$+Str(\shape\h)+d$+" "+stroketyp$+" />"
WriteStringN(0, text$)
; WriteStringN(0, " </g>")
EndSelect
EndWith
Next
WriteStringN(0, "</svg>")
CloseFile(0)
EndIf
; RunProgram(file$)
EndProcedure
winw = 1000
winh = 600
If OpenWindow(0, 0, 0, winw, winh, "SaveSVG", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, winw, winh)
LoadFont(0, "Times new roman", 20)
If StartVectorDrawing(CanvasVectorOutput(0))
; ellipse
VD_AddShape(#ShapeTypEllipse,0,0,112,116,34,45,RGB(255, 0, 0),#StrokeTypStroke,10,255)
; box with rounded stroke
VD_AddShape(#ShapeTypBox,0,0,50,50,200,100,RGB(210,150,130),#StrokeTypStroke,40,220,"",#PB_Path_RoundCorner)
VD_AddShape(#ShapeTypBox,0,0,70,150,260,120,RGB(20,240,230),#StrokeTypFill,10,90,"",#PB_Path_SquareEnd)
; circle
VD_AddShape(#ShapeTypCircle,0,0,80,60,50,100,RGB(0,150,130),#StrokeTypStroke,30,120)
; Line
VD_AddShape(#ShapeTypLine,10,30,80,60,0,0,RGB(0,0,130),#StrokeTypStroke,15,120)
VD_AddShape(#ShapeTypCurve,510,130,580,160,0,0,RGB(0,220,130),#StrokeTypStroke,25,190,"",#PB_Path_RoundEnd,710,170,680,50)
; VD_AddShape(#ShapeTypBox,0,0,50,100,30,30,RGB(160,160,160),#StrokeTypFill,40,255)
; text should be improved (there is an offset in y in browser)
VD_AddShape(#ShapeTypText,50,100,0,0,0,0,RGB(0,20,10),#StrokeTypFill,60,190,"Purebasic SVG !")
StopVectorDrawing()
EndIf
Save_SVG("SVG purebasic", "a SVG example made with purebasic" )
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf