12-16-2023, 02:40 PM
Another demo program showing how to draw SVGs and load them via memory buffer to use SVG as an alternative drawing method.
SVG's can draw polygons with a simple path definition that is mostly string of numbers.
this string "<path stroke ='#FFFFFF' fill='#FF0000' stroke-width='3' d ='M 200 200 700 200 700 400 200 400 200 200'/>" would draw a red rectangle with a 3 pixel wide white border if embedded in complete SVG string. The polygon is simply defined as a series of points. The only variation in this series of points is the use of M which tells any program drawing the path to move to the following point instead of drawing to the point.
In this example the subroutione svgpoly$ will take a randomly defined polygons and convert them into an SVGpath description held in a string. The path descriptions will be inserted into a complete SVG definition and loaded into a memory buffer and displayed.
SVG's can draw polygons with a simple path definition that is mostly string of numbers.
this string "<path stroke ='#FFFFFF' fill='#FF0000' stroke-width='3' d ='M 200 200 700 200 700 400 200 400 200 200'/>" would draw a red rectangle with a 3 pixel wide white border if embedded in complete SVG string. The polygon is simply defined as a series of points. The only variation in this series of points is the use of M which tells any program drawing the path to move to the following point instead of drawing to the point.
In this example the subroutione svgpoly$ will take a randomly defined polygons and convert them into an SVGpath description held in a string. The path descriptions will be inserted into a complete SVG definition and loaded into a memory buffer and displayed.
Code: (Select All)
'SVG polygon drawing example
'drawing polygons with paths
'a QB64 example by James D. Jarvis
'works with QB64-PE version 3.9.0 and later
'
'this demonstrates how to use subroutines to build a multiple polygon definitions and combine them into a memory buffer that is
'loaded and displayed
Screen _NewImage(800, 500, 32)
Randomize Timer
Dim si As _Unsigned Long 'the SVG image buffer, it's an image handle like any other
Do
Cls , _RGB32(Int(Rnd * 256), Int(Rnd * 256), Int(Rnd * 256)) 'clear the screen and fill it with a random color
ss$ = "" 'the the SVG string
'build the polygons for the demo
np = Int(6 + Int(Rnd * 100))
If Rnd * 100 < 3 Then np = np * 20
For p = 1 To np
ss$ = ss$ + svgpoly$(Int(25 + Rnd * (_Width - 50)), Int(25 + Rnd * (_Height - 50)), Int(10 + Rnd * 100), Int(10 + Rnd * 120), (Int(Rnd * 90)), Int(1 + Rnd * 10), _RGB32(Int(Rnd * 256), Int(Rnd * 256), Int(Rnd * 256)), _RGB32(Int(Rnd * 256), Int(Rnd * 256), Int(Rnd * 256)))
Next p
'take the polygon defintions and compine them with the rest of the SVG string
ss$ = "<svg width='" + _Trim$(Str$(_Width)) + "' height='" + _Trim$(Str$(_Height)) + "'>" + ss$ + " </svg>" 'putting all those polygons inside an SVG as large as the window
si = _LoadImage(ss$, 32, "memory") 'load the svg described in ss$ into memory
_PutImage (0, 0), si 'put the svg on the screen, using 0,0 because the source SVG is as large as the window
tt$ = Str$(p) + " polygons": _Title tt$ 'put the polygon count in the window title
Sleep
_FreeImage si 'free the image so we can load a new one without wasting memory or if we are exiting the program
Loop Until InKey$ = Chr$(27)
'_CLIPBOARD$ = ss$ 'windows users can uncomment the commad on the left to dump the last sbg drawn to their clipboard.
Function svgpoly$ (cx, cy, rr, shapedeg, turn, ww, bklr As _Unsigned Long, fklr As _Unsigned Long)
'filled rotated polygon returned as a string portion of an svg string buffer
'cx,cy are center of polygon
'rr oios radius of polygon
'shapedeg is the angle forming the basis of the polygon , if it doesn't divide into 360 evenly an irregular polygon will be created
'turn will be the angle the whole polygon is turned off of 0 degree
'ww is the width fo the border border stroke of the polygon
'output returned from theis function will be astring holding an SVG path describing a polygon.
'
'define the path that will form the polygon and fill the border and fill colors
i$ = i$ + "<path stroke ='" + packcolorN$(bklr) + "' fill='" + packcolorN$(fklr) + "' "
'add the stroke width
i$ = i$ + " stroke-width='" + _Trim$(Str$(ww)) + "' "
'find the 1st point in the polygon
x = rr * Sin(0.01745329 * turn)
y = rr * Cos(0.01745329 * turn)
'tell the svg to draw the path by moving to the first point of the polygon
i$ = i$ + "d ='M"
i$ = i$ + Str$(cx + x) + Str$(cy + y) + Str$(cx + x) + Str$(cy + y)
'find the perimter of the polygon
For deg = turn To turn + 360 Step shapedeg
x2 = rr * Sin(0.01745329 * deg)
y2 = rr * Cos(0.01745329 * deg)
'record the consecutive points of the polygon that will be drawn to form the path that defines the polygon perimeter
i$ = i$ + Str$(cx + x2) + Str$(cy + y2)
Next
'close the polyon by drawing to the first point
i$ = i$ + Str$(cx + x) + Str$(cy + y)
i$ = i$ + "'/>" 'end the path definition of the polygon
svgpoly$ = i$ 'return this path holding a polygon definiton to the SVG to be drawn
End Function
Function packcolorN$ (klr As _Unsigned Long)
'convert an unsigned long color value into a hexidecimal # that will be used in an SVG
Dim As _Unsigned Long rk, gk, bk
'get the color channels of the unsinged long color
rk = _Red32(klr)
gk = _Green32(klr)
bk = _Blue32(klr)
'convert those channel values into hexidecimal
If rk < 16 Then
r$ = "0" + Hex$(rk) 'put in a padded hexidcimal value
Else
r$ = Hex$(rk) 'put in a 2 digit hexidecimal value
End If
If gk < 16 Then
g$ = "0" + Hex$(gk) 'put in a padded hexidcimal value
Else
g$ = Hex$(gk) 'put in a 2 digit hexidecimal value
End If
If bk < 16 Then
b$ = "0" + Hex$(bk) 'put in a padded hexidcimal value
Else
b$ = Hex$(bk) 'put in a 2 digit hexidecimal value
End If
packcolorN$ = "#" + r$ + g$ + b$
End Function