Cabbage Logo
Back to Cabbage Site

svgElement() identifier

I’ve added a new svgElement() identifier to the image widget. This allows us to draw SVGs to an image from a string. For example, the code below will create this shape:

Screen Shot 2021-08-06 at 12.44.23
svgStar.csd (693 Bytes)

instr 1
    cabbageSet "image1", "svgElement", {{
    <polygon points="100,10 40,198 190,78 10,78 160,198" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:nonzero;"/>
    }}
endin

You can pass any number of elements, i.e, rectangles, circles, paths, etc. You do not need to wrap the elements in <svg> tags. These are automatically appended.

Because an SVG elements can contain any number of Cabbage syntax wildcards, and delimiters, it will quickly break the Cabbage preprocessor. So ONLY use this identifier within your Csound code! The path elements are really nice, because they let you do things like this:


svgElements.csd (3.6 KB)
  • This example could be a lot better. If I was doing it again I would create a UDO to generate the envelopes with the components encapsulated, rather than creating the various components in the <Cabbage> section and pulling them together in my Csound code.

Animations are also possible. All you need to do is keep updating the SVG elements in realtime. But be forewarned that this might cause a spike in your CPU!

This is very poorly tested for now, so please let me know if you have any issues with it.

2 Likes

I’m wondering if you could give a short explanation of the identifiers that are being used to generate vector graphics?

The SVG specs are quite well documented. The w3schools pages are quite good. This editor is quite good too for getting your head around the various SVG elements and identifiers. The SVG text is shown on the top left hand side.

this looks super promising)

Wow ! Looks really great !
I wonder what is the most efficient to create an envelope visualizer between this and classic Gentable ?
At first sight I’d say this new SGVelements looks way more smooth than Gentable.
Can’t wait to get my hands on this !

I think I would rather use this than the gentable method. It will beat it hands down in terms of customisations. Also, this new method uses an SVG parser that written by some of the best programmers in the world, whereas I wrote the gentable stuff :rofl:

I should have said however that the SVG parser doesn’t works for SVG filters, and some of the more complex aspects of the SVG specs. But for basic shapes, paths, strokes, fills, etc, it works just fine.

Just thinking out loud here. I wonder if there’s a way to add physics/gravity etc… I guess you could do all the math in Csound too…? :thinking: I envision some generative/reactive UIs with elements bouncing around or the user can “throw” them…

Have you seen Iain’s Ping Clang example in the FunAndGames menu? It’s great fun and adds a level of physics to the scene too. In terms of throwing stuff around the screen, check out the custom xypad I creating using only Cabbage and Csound code, i.e, without using an actual xypad.

This could also be done with SVGs too, but I think I would still make each component an image that draws a single SVG rather than try to create one mega SVG that renders the entire scene.

2 Likes

Yes! perfect… :smiley_cat:

1 Like

It’s a crazy example. I looked at it one evening for about an hour and still couldn’t get my head around it :rofl:

Are all of the other SVG elements supported?
I tried some of the blending modes but couldn’t quite get it to do what I want

    cabbageSet "image", "svgElement", {{
    <feFlood result="floodFill" x="0" y="0" width="100%" height="100%" flood-color="green" flood-opacity="1"/>
<feFlood result="floodFill2" x="0" y="0" width="100%" height="100%" flood-color="blue" flood-opacity="0.5"/>
      <feBlend in="floodFill" in2="floodFill2" mode="multiply"/>
    }}

From a few posts ago:

gotcha - thanks

If you find other things let me know. I tried using a <defs> tag earlier but got caught out. It is supported in later versions of JUCE but not the one Cabbage uses. But I think I can pull in some updates without violating any licensing issues. So if you find some non-filter aspects of the SVG stuff that doesn’t work let me know.

Back to this - before I try and wrap my head around it - do you think it’s possible to constrain the ball’s bounds to a polygon shape (ie triangle)? I’m feeling really avant-garde w UI design now! :laughing:

Sure, with a bit of math to figure out if the ball lies within the triangle.

1 Like

@chronopolis, here is a simple example using only SVGs. I grabbed some triangle hit code from here.


ballAndTriangle.csd (1.5 KB)

If you move the mouse too quick it skips a frame or so. I think it would be better to make the ball an image component on its own.

Thanks Rory - I’ll try that out! I’m wondering if there’s any potential for tracking mouseover and boundaries on more complex polygons, algorithmically generated or even animated shapes. I know this is probably way beyond the scope of Cabbage’s intentions but I am experimenting with some algorithmically generated UI elements like grids and curved shapes — something visual and interactive that can be coupled to generative audio. I don’t suppose you know of a simple way to pull info on an image (SVG) objects vectors without employing tons of math?

This could all be done, but not without some serious work. We can track mouseover easy enough by simply querying the CURRENT_WIDGET channel, but each widget is basically a rectangle. So any kind of complex boundary detection is likely to be difficult.

Do you mean their positional vectors or their path/polygon vectors? You can parse the SVG file for any info you like. And then pass that to an array. Or you can manually take this info and put it into an array.

I’ve often thought some 2d/3d positional vector opcodes would be nice. Even simpler operations like distance, magnitude, etc. I was half tempted to write a set of them for Cabbage a while back, but never got around to it.

Both I guess. Still, even with that info in an array I think it would take some heavier lifting to delineate the boundaries, right?

I’ve often thought some 2d/3d positional vector opcodes would be nice. Even simpler operations like distance, magnitude, etc.

Cool. Curious what an example of that might look like…

Sort of related - I assume you are familiar with Hydra? I was thinking of building a few UDOs for SVGs that emulate its more basic functions like repeat, scale, scroll.