Coder Social home page Coder Social logo

oksvg's Introduction

oksvg

oksvg is a rasterizer for a partial implementation of the SVG2.0 specification in golang.

Although many SVG elements will not be read by oksvg, it is good enough to faithfully produce thousands, but certainly not all, SVG icons available both for free and commercially. A list of valid and invalid elements is in the doc folder.

oksvg uses the rasterx rasterizer package which implements full SVG2.0 path functions, including the newer 'arc' join-mode.

arcs and caps

Extra non-standard features.

In addition to 'arc' as a valid join mode value, oksvg also allows 'arc-clip' which is the arc analog of miter-clip and some extra capping and gap values. It can also specify different capping functions for line starts and ends.

Rasterizations of SVG to PNG from creative commons 3.0 sources.

Example renderings of unedited open source SVG files by oksvg and rasterx are shown below.

Thanks to Freepik from Flaticon Licensed by Creative Commons 3.0 for the example icons shown below, and also used as test icons in the testdata folder.

Jupiter

lander

mountains

bus

Non-standard library dependencies

oksvg requires the following imports which are not included in the go standard library:

  • golang.org/x/net/html/charset
  • golang.org/x/image/colornames
  • golang.org/x/image/math/fixed

These can be included in your gopath by the following 'get' commands:

  • "go get golang.org/x/image/math/fixed"
  • "go get golang.org/x/image/colornames"
  • "go get golang.org/x/net/html/charset"

oksvg also requires the user to get or clone into the workspace the rasterx package located here:

  • github.com/srwiley/rasterx

oksvg's People

Contributors

andydotxyz avatar cedy avatar karimsa avatar noofbiz avatar srwiley avatar uberswe avatar yeldirium avatar zrcoder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

oksvg's Issues

Support for defs

Hello,

An svg I'm trying to parse uses the defs tag. I was thinking it could grab the elements defined in defs and save them in the SvgIcon's Ids, like it does for gradients.

compound path drawing seems to fail for any circular subpath

Preface
I am very inexperienced when it comes to parsing svg-definitions and am not really familiar with the spec, so I apologize if I am completely misunderstanding what is happening here or I use the wrong terminology.

Issue
Any circular sub-path enclosed by an arbitrary different path is not rendered properly.
Examples (left svg rendered by browser, right by oksvg):
2023-12-28 14_19_55-
2023-12-28 14_21_45-
These examples only use a path-object with z, Z, m, M and a operators inside a viewbox.

Steps to Reproduce
Add either the following minimal example (circle with donut-hole) or any svg from fontawesome.com with a hole as a svg-file to the existing testdata folder of oksvg add the reference to the file in svgdraw_test.go:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#000000" d="M256 512a256 256 0 1 0 0-512 256 256 0 1 0 0 512zm0-352a96 96 0 1 1 0 192 96 96 0 1 1 0-192z"/></svg>

Specifically tested and incorrectly rendered files from fontawesome:

Steps Taken
I got a local development environment for oksvg running and fiddled with the svg-files themselves as well as the code handling z, Z, m and M. I assumed it might be an edge-case for handling the closing of arcs that was misbehaving, but failed to identify anything meaningful.

Notes

SVG conversion to a large PNG takes a lot of time

Hi,
I'm trying to convert an SVG file to a large PNG.
score
But it takes a lot of time. So I'm trying to profile the CPU usage to provide a PR. Maybe you could give me a hint?

I found this comment:
// This draws the entire bounds of the image, because
// at this point the alpha mask does not shift with the
// placement of the target rectangle in the vector rasterizer

Indeed, why is it that to draw a single SvgPath we need to iterate over the pixels of the whole canvas?

License disambiguation

LICENSE states that the library is distributed under BSD but doc/LICENSE is referring to GPLv2+ or Freetype. So which one do apply?

Thanks.

Request: surpport "class" element

look at the svg bellow:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 361.75 338.01">
  <defs>
    <style>.cls-2{fill:blue;}</style>
  </defs>
  <title>test</title>
  <path class="cls-2" d="M141.1,283.87s-28,30.76-45.12,15c-5.16-4.75-6.84-10.25-18.46-9.57l4.78-6.84s6.15-2.05,15,4.78c7.29,5.61,19.14,8.89,28.71-11.62Z"/>
</svg>

the "class" in <path> has no effect.

Flexible rendering backends

If there was the ability to plug in different back-ends this project would be super useful for all sorts of different renderings, such as PDF's, or even GUI applications. Even if this project could support Canvas as a back-end there's already a variety of places it could render, even GioUI.

This project was an early attempt to do what I'm describing above. https://github.com/benoitkugler/oksvg

Add support for different renderers

Hi !
This is not an issue, but rather a proposal; feel free to close it if not interested !

I would like to use oksvg to render svg files to an other target than an image: I have in mind a PDF file, but it could be any other target.

To do so, I propose an intermediate package which handles the svg parsing but do not import rasterx (or any other backend package). Instead it delegates the drawing to a Driver interface.

This interface is then easily implemented by a thin wrapper around rasterx, but may also be implemented by a PDF writter.

It's true that a PDF writer could directly implement the Scanner interface, but it would be rather inefficient since PDF directly supports high-level path painting operators.

I have a proof of concept at https://github.com/benoitkugler/oksvg : the raster backend is complete, and the PDF one is
in progress, but already support a large number of features.

If you considerer this idea interesting, we can discuss the details of a possible PR...

support for text?

hello :)

wondering if the converter supports text or Im doing something wrong :|

have this svg that I create in the code, so in the end I have the svg string.

canvas := svg.New(&buf)
canvas.Start(width, height)
canvas.Text(width/2, height/2, "aloha, SVG", "text-anchor:middle;font-size:30px;fill:white")
canvas.Circle(width/2, height/2, 100, "fill: green")
canvas.End()

the svg looks like this:
Screen Shot 2021-05-03 at 6 26 28

but when Im running the repo code to generate a png, I get only a circle.

So want to make sure if text is supported, as it mentions in the readme that not all svg options are available.

Black background when converting SVG to PNG

I'm trying to convert a svg file to png, but the output file ended with a black background instead of white.

package converter

import (
	"image"
	"image/png"

	"net/http"
	"os"

	"github.com/srwiley/oksvg"
	"github.com/srwiley/rasterx"
)

func ConvertSvgToPng() error {
	url := "https://s.glbimg.com/es/sde/f/organizacoes/2020/02/12/botsvg.svg"
	w, h := 512, 512

	response, err := http.Get(url)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	icon, _ := oksvg.ReadIconStream(response.Body)
	icon.SetTarget(0, 0, float64(w), float64(h))

	rgba := image.NewRGBA(image.Rect(0, 0, w, h))
	icon.Draw(rasterx.NewDasher(w, h, rasterx.NewScannerGV(w, h, rgba, rgba.Bounds())), 1)

	out, err := os.Create("out.png")
	if err != nil {
		return err
	}
	defer out.Close()

	err = png.Encode(out, rgba)
	if err != nil {
		return err
	}
	return err
}

SVG file: https://s.glbimg.com/es/sde/f/organizacoes/2020/02/12/botsvg.svg

PNG output:
out

Rect with missing X or Y crashes

If you have the content <rect fill="none" height="24" width="24"/> then it hits a ParseError on "" (empty string).
It should, however, default to 0.
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect

Stack is approximately:

fyne.io/fynedesk/vendor/github.com/srwiley/oksvg.parseFloat(0xc00390ff90, 0x5, 0x40, 0x4014000000000000, 0x0, 0x0)
	/home/andy/Code/Go/src/fyne.io/fynedesk/vendor/github.com/srwiley/oksvg/svgd.go:525 +0xbe
fyne.io/fynedesk/vendor/github.com/srwiley/oksvg.(*PathCursor).ReadFloat(0xc002a56f00, 0xc00390ff90, 0x5, 0x0, 0x0)
	/home/andy/Code/Go/src/fyne.io/fynedesk/vendor/github.com/srwiley/oksvg/svgp.go:104 +0x236
fyne.io/fynedesk/vendor/github.com/srwiley/oksvg.(*PathCursor).GetPoints(0xc002a56f00, 0xc00390ff90, 0x5, 0x1, 0x0)
	/home/andy/Code/Go/src/fyne.io/fynedesk/vendor/github.com/srwiley/oksvg/svgp.go:136 +0x235
fyne.io/fynedesk/vendor/github.com/srwiley/oksvg.(*PathCursor).addSeg(0xc002a56f00, 0xc00390ff8f, 0x6, 0x0, 0x0)
	/home/andy/Code/Go/src/fyne.io/fynedesk/vendor/github.com/srwiley/oksvg/svgp.go:165 +0x78
fyne.io/fynedesk/vendor/github.com/srwiley/oksvg.(*PathCursor).CompilePath(0xc002a56f00, 0xc00390fe40, 0x156, 0xc000096f18, 0x4629fc)
	/home/andy/Code/Go/src/fyne.io/fynedesk/vendor/github.com/srwiley/oksvg/svgp.go:384 +0x10c

SVG File Not well drawn

I run demo code in the test case, just modified my svg file, like this,
`

str := []string{"00dbdcf748734ed890fbf39ca76ce266",
"1ade369b862d44118c126ff8f80bbd1b",
"1bedfd263a1f4ca58c660806e03e80e7",
"1d7d7deed0ae484a8e893950ad700582",
"1e6c8acc04134b5a91cf1ecc1d43c433",
"1ed618bb2816400bbc29e40fffae8114",
"1fbd523827844e4ebea89657ea16c3de",
"2be84432e3ea4e01a919be01ec79fff5",
"2c2766e105bf4081b7f46d50a840d017",
"4c8536828410457ebd2996e3b2437863",
"4d1078d7548045d7921329e9ea91fe0c",
"4f0f35b1b5454a4482cecb693564c98b",
"4fe9018d54ec43da999f6712e2b4afc9",
"5abbd764d36b470c804a4d0b51353eae",
"5ec8889735b04398a7e17a54761f0c31"}
for _, s := range str {
iconPath := "gg_demo/icons2/" + s + ".svg"

	icon, errSvg := oksvg.ReadIcon(iconPath, oksvg.WarnErrorMode)
	if errSvg != nil {
		fmt.Println(errSvg)
		return
	}
	w, h := int(icon.ViewBox.W), int(icon.ViewBox.H)
	img := image.NewRGBA(image.Rect(0, 0, w, h))
	tb := img.Bounds()
	tb.Max.X /= 2
	scannerGV := rasterx.NewScannerGV(w, h, img, img.Bounds())
	raster := rasterx.NewDasher(w, h, scannerGV)
	icon.Draw(raster, 1.0)
	if img != nil {
		p := strings.Split(iconPath, "/")
		err := SaveToPngFile(fmt.Sprintf("gg_demo/targets/%s.png", p[len(p)-1]), img)
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

`

and the final result like this:
image
source code is
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 83.51 83.46"> <title>&#x8D44;&#x6E90; 35</title> <path d="M.06 62.2V45.36c0-1.12.76-1.57 1.48-2.14 7.31-5.68 15.49-6.79 24.3-4.61 8.35 2.06 16 6.09 24 9.09a48.68 48.68 0 0 0 14.71 3.53 26 26 0 0 0 16.61-5c.59-.42 1.09-1.31 1.89-1s.42 1.32.43 2v13a3.67 3.67 0 0 1-1.71 3.31C73.14 70 63.77 70.08 54 67c-8-2.53-15.44-6.52-23.38-9.21-8.37-2.85-16.68-3.84-24.89.51a32.29 32.29 0 0 0-5.67 3.9z" fill="#146fb7"/> <path d="M.07 39.11V22.39c0-1.12.78-1.58 1.5-2.13 7.15-5.56 15.17-6.73 23.82-4.69 8 1.88 15.25 5.65 22.83 8.6 6.06 2.37 12.18 4.42 18.85 4.12a26.13 26.13 0 0 0 14.3-5.22c.51-.36 1-1.14 1.71-.73s.33 1.21.33 1.83c0 4.33-.05 8.66 0 13a3.88 3.88 0 0 1-1.85 3.51c-7.6 5.68-16 6.43-24.89 4.1-8.39-2.19-16-6.37-24.15-9.28-6.38-2.28-12.84-4-19.75-2.67-4.57.89-8.54 3.01-12.7 6.28z" fill="#ec2032"/> <path d="M.09 15.6V1.26A1.05 1.05 0 0 1 1.31.06h78.94c2.45 0 3.4.5 3.23 3.14-.25 3.73-.12 7.49 0 11.24a3.48 3.48 0 0 1-1.55 3.13c-7.7 5.93-16.23 6.69-25.32 4.28-8.39-2.23-16-6.4-24.17-9.31-6.14-2.2-12.36-3.83-19-2.71a28.08 28.08 0 0 0-11.53 5c-.51.28-.82.86-1.82.77z" fill="#ec2032"/> <path d="M41.47 83.41H2.53C.6 83.47-.08 83 0 81c.16-3.9.1-7.82 0-11.73a3.46 3.46 0 0 1 1.52-3.14c8.28-6.36 17.36-6.76 27-3.85 7.09 2.15 13.7 5.51 20.61 8.14 5.52 2.1 11.1 3.87 17.14 3.79a26.07 26.07 0 0 0 14.86-5c.58-.41 1.1-1.3 1.9-.91s.39 1.34.4 2c0 3.58-.12 7.16.07 10.73.11 2.12-.75 2.45-2.59 2.45-13.15-.1-26.3-.07-39.44-.07z" fill="#146fb7"/> </svg>

Long dashed lines break

When using the "stroke-dasharray" attribute short lines render correctly, but long lines break

Screenshot

Left: Chrome
Right: Fyne (using OKSVG)
Screen Shot 2021-04-28 at 11 53 52

Sample SVG

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="480" height="640" viewBox="0 0 480 640">
    <g stroke="red">
        <line x1="60" y1="0" x2="60" y2="40" stroke-dasharray="4" />
        <line x1="120" y1="0" x2="120" y2="140" stroke-dasharray="4" />
        <line x1="180" y1="0" x2="180" y2="240" stroke-dasharray="4" />
        <line x1="240" y1="0" x2="240" y2="340" stroke-dasharray="4" />
        <line x1="300" y1="0" x2="300" y2="440" stroke-dasharray="4" />
        <line x1="360" y1="0" x2="360" y2="540" stroke-dasharray="4" />
        <line x1="420" y1="0" x2="420" y2="640" stroke-dasharray="4" />
    </g>
</svg>

Sample Code

//go:generate fyne bundle -o bundled.go dasharray.svg
package main

import (
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
)

func main() {
	a := app.New()
	w := a.NewWindow("Dashes")
	w.SetContent(&canvas.Image{
		Resource: resourceDasharraySvg,
		FillMode: canvas.ImageFillOriginal,
	})
	w.ShowAndRun()
}

Command

go generate ./...
go run ./...

Dependency x/net is vulnerable

go mod why -m golang.org/x/net

github.com/srwiley/oksvg
golang.org/x/net/html/charset
Dependency go:golang.org/x/net:v0.6.0 is vulnerable, safe version v0.21.0
CVE-2022-41723 7.5 Uncontrolled Resource Consumption vulnerability with High severity found
CVE-2023-44487 5.3 Uncontrolled Resource Consumption vulnerability with Medium severity found
CVE-2023-39325 7.5 Uncontrolled Resource Consumption vulnerability with High severity found

Announce: SVG Editor

Hey @srwiley,

This is not an issue so feel free to close, but I just wanted to tell you about a simple SVG Editor I was able to create thanks to oksvg and rasterx.

Keep up the great work!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.