Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SVG gradient example 1
#1
A simple example showing how to make use of the SVG library in QB64 PE 3.9.0 and higher.

There are some peculiarities in how SVG and XML tags used to define the SVG graphics are parsed and rendered. I'm still learning how they all work myself and want to share as I go along. 

The _LOADIMAGE command is doing a lot of work here and the ability to load a SVG file from a string buffer out of memory let's us treat SVGs as an alternative and more power version of DRAW.

Go review  _LOADIMAGE - QB64 Phoenix Edition Wiki when you get a chance. 

The example program here will draw a big rounded-corner rectangle with a gradient fill in the middle of the screen. Press any key to exit. Read the comments for a hopefully useful description of what is going on in the program.
Code: (Select All)
 'SVG gradient example 1
'by James D. Jarvis Nove,ber 16,2023
'
'how to build an SVG gradient inside a rectangle with rounded corners within the program without needing to call an external file
'
Screen _NewImage(800, 500, 32)
Dim As Long simg 'we are going to draw the SVG into this image

'make a minimal header and footer to setup the SVG
svgheader$ = "<svg x='0' y='0' width='" + _Trim$(Str$(_Width)) + "' height= '" + _Trim$(Str$(_Height)) + "'  >" 'makes sure the SVG will match the screen 1 to 1
svgfooter$ = "</svg>" 'this indicates the end of the SVG

'gd$ is going to be the linear gradient
'gradients have to be defined before they can be called later in the SVG
'
gd$ = "  <defs> <linearGradient id='LGrad1' x1='0' y1='0' x2='0' y2='500'  >" 'x1,y1,x2,y2 establishes the gradient will run from top to bottom
'removing coordinate data from the line above will cause the gradient to be rendered from left to right as opposed to top to bottom
gd$ = gd$ + "      <stop class='stop1' offset='0%'stop-color='#550000' />" 'the gradient at this point is starting out dark red
gd$ = gd$ + "      <stop class='stop2' offset='40%'stop-color='red' />" 'the gradient at this point is default red
gd$ = gd$ + "      <stop class='stop3' offset='60%'stop-color='red' />" 'the gradient at this point is default red
gd$ = gd$ + "      <stop class='stop4' offset='100%'stop-color='#550000' />" 'the gradient is ending in dark red
gd$ = gd$ + "    </linearGradient> "
gd$ = gd$ + " </defs>"

'scaling the postion of the rectangle to be drawn relative to the dimensions of the screen
'this will result in a centered rectangle being drawn on the screen
xoff$ = _Trim$(Str$(Int(_Width / 20))) '_trim$ needs to be used to trim off the leading space STR$ creates to make sure the value is properly entered
yoff$ = _Trim$(Str$(Int(_Height / 20)))
rw1$ = _Trim$(Str$(Int(_Width * .9)))
rh1$ = _Trim$(Str$(Int(_Height * .9)))
'i$  will hold the actual image data
'rect defines a rectanglt at x,y with height and width, rx,ty define the rounded rectangle corners
i$ = "<rect x='" + xoff$ + "' y='" + yoff$ + "' height='" + rh1$ + "' width='" + rw1$ + "'rx='24' ry='24' fill='url(#LGrad1)' stroke='white' stroke-width='9' />"
i$ = i$ + "<rect x='" + xoff$ + "' y='" + yoff$ + "' height='" + rh1$ + "' width='" + rw1$ + "'rx='24' ry='24' fill='none' stroke='black' stroke-width='3' />"
'note in the second rectangle definition above that draw the back line is set to a fill='none' as opposed to 'transparent' the library doesn't render 'none' but will render 'transparent' as a grey box

svg$ = svgheader$ + gd$ + i$ + svgfooter$ 'put all the strings together into one string called svg$
simg = _LoadImage(svg$, 32, "memory") 'load and render the defined SVG$ into simg
_PutImage , simg 'put simg on the screen
Sleep
Cls
Print "Here is the SVG created by this program"
Print
Print svg$
_FreeImage simg 'clear that image out of memory unless you want to keep using it of course
Reply
#2
@James D Jarvis I guess we have a fan of SVG Smile
b = b + ...
Reply
#3
(11-16-2023, 09:34 PM)bplus Wrote: @James D Jarvis  I guess we have a fan of SVG Smile

Yes. Yes we do. Being able to create vector images in a high-end illustration program and import them is useful. But being able to create such graphics inside a QB64 program itself is fantastic.

Anyone know if there's any decent documentation for the SVG library being used? I've discovered some quirks but nothing bad. I'm not a real SVG guru but I was using them years back for animations and interface elements professionally and am delighted to be able to use them in my QB64 programs.
Reply
#4
Must get into Inkscape, create or load SVG file and save as "plain SVG". By default, the program saves as "sodipodi", that is, what it claims is its own format. It adds a lot more XML junk. That's why I warn here to save as "plain SVG", must choose it from the file types in the save file dialog.

This is to study other ins and outs of the SVG format. Doing bezier curves could be tricky. Some pictures switch back and forth between absolute and relative coordinates so one has to look out for that when trying to parse an SVG. The "sodipodi" format tends to have a lot of transformations too, which could be a PITA to get the true absolute coordinates. I should have checked if QB64PE could load one of my Inkscape "projects".

Another thing to watch out for is that in "plain" SVG, there are no layers like what Inkscape supports. Every "layer" in a "plain" SVG file is a group. Indeed, a "plain" SVG is loaded by Inkscape into a single layer, which might have more than one group.

This is for people who think SVG is "yet another cryptic XML-like format" but it really isn't.
Reply
#5
(11-17-2023, 01:08 AM)mnrvovrfc Wrote: Must get into Inkscape, create or load SVG file and save as "plain SVG". By default, the program saves as "sodipodi", that is, what it claims is its own format. It adds a lot more XML junk. That's why I warn here to save as "plain SVG", must choose it from the file types in the save file dialog.

This is to study other ins and outs of the SVG format. Doing bezier curves could be tricky. Some pictures switch back and forth between absolute and relative coordinates so one has to look out for that when trying to parse an SVG. The "sodipodi" format tends to have a lot of transformations too, which could be a PITA to get the true absolute coordinates. I should have checked if QB64PE could load one of my Inkscape "projects".

Another thing to watch out for is that in "plain" SVG, there are no layers like what Inkscape supports. Every "layer" in a "plain" SVG file is a group. Indeed, a "plain" SVG is loaded by Inkscape into a single layer, which might have more than one group.

This is for people who think SVG is "yet another cryptic XML-like format" but it really isn't.
Most of my experience with it is with Adobe Illustrator and I have the best results bringing it into QB64 after saving as a Tiny SVG (??).  What I like is how editable they can be from within QB64 itself since they are just strings.
Reply
#6
(11-16-2023, 09:45 PM)James D Jarvis Wrote:
(11-16-2023, 09:34 PM)bplus Wrote: @James D Jarvis  I guess we have a fan of SVG Smile

Yes. Yes we do. Being able to create vector images in a high-end illustration program and import them is useful. But being able to create such graphics inside a QB64 program itself is fantastic.

Anyone know if there's any decent documentation for the SVG library being used? I've discovered some quirks but nothing bad. I'm not a real SVG guru but I was using them years back for animations and interface elements professionally and am delighted to be able to use them in my QB64 programs.

We are using the NanoSVG library to implement SVG support in QB64-PE. The NanoSVG rasterizer can only render flat filled shapes. Notably, SVG text rendering is absent.
See memononen/nanosvg: Simple stupid SVG parser (github.com)
Reply
#7
(11-17-2023, 05:05 AM)a740g Wrote: James D Jarvis...
bplus...

We are using the NanoSVG library to implement SVG support in QB64-PE. The NanoSVG rasterizer can only render flat filled shapes. Notably, SVG text rendering is absent.
See memononen/nanosvg: Simple stupid SVG parser (github.com)

Thanks, from looking there is seems digging into the headers will be my best option for looking for the setting the library pays attention to (unless there's something I'm missing). In just a couple minutes it's already been effective.
Reply




Users browsing this thread: 3 Guest(s)