Git Product home page Git Product logo

rasterx's Issues

How do you use AddArc given the context from SVG2.0 data?

First, thanks for the library. This might be considered related to #13 Given documentation or a test as an example for AddArc may clarify both issues.

I am trying to figure out how to use AddArc given an SVG 2.0 instruction.

func AddArc(points []float64, cx, cy, px, py float64, p Adder) (lx, ly float64) {

Let's assume I have M 0 0 a4.9916 4.9916 0 0 1 -0.59375 0.1875 notice this is the relative version which I think simply means that the last two values must be adjusted by the current point and in this case it is 0, 0.

I have summarized so far that the Points is basically all the parameters of a, no issue there. What I can't figure out is what is cx, cy, px, py parameters?

I can't seem to get the correct arc. Is cx,cy current point that would make since, is that correct?

It is the px, py I don't really have any idea at all what it could be or how to derive it from the information I have.

Given this is a relative instruction would I need to update points based on the current location or is that somehow related to the c or p parameters?

Thanks for your time!

Scaled transform breaks dashing

When rasterizing an SVG with a scaled transformation matrix dashing does not behave correctly.
My goal is to create a high resolution png render of the svg.

At scale 1.0 (correct):
Not Scaled SVG

At scale 2.0:
image

Code used:

package main

import (
	"image"
	"image/png"
	"os"

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

func main() {
	scale := 2.0

	in, err := os.Open("in.svg")
	check(err)
	defer in.Close()

	icon, err := oksvg.ReadIconStream(in)
	check(err)

	w, h := int(icon.ViewBox.W*scale), int(icon.ViewBox.H*scale)

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

	out, err := os.Create("out.png")
	check(err)
	defer out.Close()

	err = png.Encode(out, rgba)
	check(err)
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}

SVG used:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 110 110">
    <path d="
      M 50, 50
	  l 0 -50
    " stroke="teal" fill="none" />
    <path d="
      M 0, 50
      a 50,50 0 1,0 100,0
      a 50,50 0 1,0 -100,0
    " stroke="teal" fill="none" stroke-dasharray="314" stroke-dashoffset="157" />
</svg>

Implementing the rasterx interface

Hello! I want to be able to render svgs directly to, say, an opengl framebuffer rather than an image.Image. I've actually already got the engine and framework and shaders needed, and It seems to me that a lot of the types in this package could be interfaces, which could then allow me to implement them to allow me to do just that. Is that a direction you'd be willing to take? I'll put together the PR and write it myself, I'm just wondering if you had any tips or ideas on going about it. Thanks!

Please explain the AddArc parameters, e.g. to make a "pie part"

Hi,
I spent hours making tests and trying to understand the parameters, and the "points" content and I didn't find my way to make a "pie part". Whatever I do, the path becomes a circle.

Using this

	cx, cy := float64(w/2.0), float64(h/2.0)
	r := float64(w / 3.0)
	angle := 45.0
	rot := angle * math.Pi / 180.0

	// find the point on circle of radius r at angle rot
	px := cx + r*math.Cos(rot)
	py := cy + r*math.Sin(rot)

	points := []float64{r, r, angle, 1, 0, px, py}

	stroker.Start(rasterx.ToFixedP(cx, cy))
	//stroker.Line(rasterx.ToFixedP(cx, cy+r))
	stroker.Start(rasterx.ToFixedP(px, py))
	rasterx.AddArc(points, cx, cy, px, py, stroker)
	//stroker.Stop(false)
	//stroker.Line(rasterx.ToFixedP(cx, cy))
	stroker.Stop(false)
	stroker.Draw()

out

With this:

	stroker.Start(rasterx.ToFixedP(cx, cy))
	stroker.Line(rasterx.ToFixedP(cx, cy+r))
	stroker.Start(rasterx.ToFixedP(px, py))
	rasterx.AddArc(points, cx, cy, px, py, stroker)
	stroker.Line(rasterx.ToFixedP(cx, cy))
	stroker.Stop(false)
	stroker.Draw()

out

I made several other tests to start the path somewhere else, with no idea of how to make a "pie chart element".

This is the wanted shape:
image

The goal is to make a pie chart (of course :) ) but (sorry to say this) the code is not well documented... Can you please give a simple example of a pie chart element?

I tried adding rasterx to awesome-go page... needs some work before they will accept it

I was adding GoGi etc to it and figured I'd add rasterx while I was at it.. Anyway, looks like you'll have to do some things and submit it separately if you want to:

avelino/awesome-go#2222

These should be improved, they have a lot of issues, especially with golint:
https://goreportcard.com/report/github.com/srwiley/rasterx

These miss a lot of documentation, which should also be improved:
https://godoc.org/github.com/srwiley/rasterx

these don't have enough coverage:
https://github.com/srwiley/rasterx

fix for radial gradients with UserSpaceOnUse, c == f

I finally found the source of a radial gradient issue I'd noticed for a while: the fx, fy coordinates were not being transformed, and so the simple distance-based case was not triggering. Diff to fix is attached -- too lazy to do a PR but let me know if you prefer that.

Parens around the d's probably doesn't matter but anyway it might be slightly more precision-preserving?

diff --git a/gradient.go b/gradient.go
index 6be8fe7..8f00985 100644
--- a/gradient.go
+++ b/gradient.go
@@ -189,8 +189,10 @@ func (g *Gradient) GetColorFunctionUS(opacity float64, objMatrix Matrix2D) inter
 			ry *= g.Bounds.H
 		} else {
 			cx, cy = g.Matrix.Transform(cx, cy)
+			fx, fy = g.Matrix.Transform(fx, fy)
 			rx, ry = g.Matrix.TransformVector(rx, ry)
 			cx, cy = objMatrix.Transform(cx, cy)
+			fx, fy = objMatrix.Transform(fx, fy)
 			rx, ry = objMatrix.TransformVector(rx, ry)
 		}
 
@@ -203,7 +205,7 @@ func (g *Gradient) GetColorFunctionUS(opacity float64, objMatrix Matrix2D) inter
 					x, y := gradT.Transform(float64(xi)+0.5, float64(yi)+0.5)
 					dx := float64(x) - cx
 					dy := float64(y) - cy
-					return g.tColor(math.Sqrt(dx*dx/(rx*rx)+dy*dy/(ry*ry)), opacity)
+					return g.tColor(math.Sqrt((dx*dx)/(rx*rx)+(dy*dy)/(ry*ry)), opacity)
 				})
 			}
 			return ColorFunc(func(xi, yi int) color.Color {
@@ -211,7 +213,7 @@ func (g *Gradient) GetColorFunctionUS(opacity float64, objMatrix Matrix2D) inter
 				y := float64(yi) + 0.5
 				dx := x - cx
 				dy := y - cy
-				return g.tColor(math.Sqrt(dx*dx/(rx*rx)+dy*dy/(ry*ry)), opacity)
+				return g.tColor(math.Sqrt((dx*dx)/(rx*rx)+(dy*dy)/(ry*ry)), opacity)
 			})
 		}
 		fx /= rx

Display bug in fyne

Hello.
After discussing with andy (main maintainer of fyne library), about my bug, we came to the conclusion that it should be poster here since fyne uses rasterx for SVG display.

Here are two SVGs that are not correctly displayed in fyne:
image
image
Code:

<?xml version="1.0" encoding="utf-8"?>

<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Calendar / Calendar_Days">
<path id="Vector" d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V8M8 4H16M8 4V2M16 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V8M16 4V2M4 8V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H16.8031C17.921 20 18.48 20 18.9074 19.7822C19.2837 19.5905 19.5905 19.2842 19.7822 18.9079C20 18.4805 20 17.9215 20 16.8036V8M4 8H20M16 16H16.002L16.002 16.002L16 16.002V16ZM12 16H12.002L12.002 16.002L12 16.002V16ZM8 16H8.002L8.00195 16.002L8 16.002V16ZM16.002 12V12.002L16 12.002V12H16.002ZM12 12H12.002L12.002 12.002L12 12.002V12ZM8 12H8.002L8.00195 12.002L8 12.002V12Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

image
image
Code

<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.5 13.75C9.5 14.72 10.25 15.5 11.17 15.5H13.05C13.85 15.5 14.5 14.82 14.5 13.97C14.5 13.06 14.1 12.73 13.51 12.52L10.5 11.47C9.91 11.26 9.51001 10.94 9.51001 10.02C9.51001 9.17999 10.16 8.48999 10.96 8.48999H12.84C13.76 8.48999 14.51 9.26999 14.51 10.24" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 7.5V16.5" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22 12C22 17.52 17.52 22 12 22C6.48 22 2 17.52 2 12C2 6.48 6.48 2 12 2" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17 3V7H21" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22 2L17 7" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Text lose

I tried to convert a svg which contains words in , but lose all text after convertion?
origin svg:

in

after:

out

incorrect rasterization of open paths

Hi,
while testing rasterx, i write this example:

package main

import (
	"image"
	"image/color"
	"image/draw"
	"log"

	"golang.org/x/exp/shiny/driver"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/exp/shiny/widget"

	"golang.org/x/image/math/fixed"

	"github.com/srwiley/rasterx"
)

const (
	S = 512
)

func main() {
	log.SetFlags(0)
	driver.Main(func(s screen.Screen) {
		src := TestMultiFunctionGV() // image.NewRGBA(image.Rect(0, 0, sw, sh))

		w := widget.NewSheet(widget.NewImage(src, src.Bounds()))
		if err := widget.RunWindow(s, w, &widget.RunWindowOptions{
			NewWindowOptions: screen.NewWindowOptions{
				Title:  "Rasterx Example",
				Width:  S,
				Height: S,
			},
		}); err != nil {
			log.Fatal(err)
		}
	})
}

//////////////////////////////////////////////////////

func toFixedP(x, y float64) (p fixed.Point26_6) {
	p.X = fixed.Int26_6(x * 64)
	p.Y = fixed.Int26_6(y * 64)
	return
}

func GetTestPath() (testPath rasterx.Path) {
	//Path for Q
	//M210.08,222.97
	testPath.Start(toFixedP(210.08, 222.97))
	//L192.55,244.95
	testPath.Line(toFixedP(192.55, 244.95))
	//Q146.53,229.95,115.55,209.55
	testPath.QuadBezier(toFixedP(146.53, 229.95), toFixedP(115.55, 209.55))
	//Q102.50,211.00,95.38,211.00
	testPath.QuadBezier(toFixedP(102.50, 211.00), toFixedP(95.38, 211.00))
	//Q56.09,211.00,31.17,182.33
	testPath.QuadBezier(toFixedP(56.09, 211.00), toFixedP(31.17, 182.33))
	//Q6.27,153.66,6.27,108.44
	testPath.QuadBezier(toFixedP(6.27, 153.66), toFixedP(6.27, 108.44))
	//Q6.27,61.89,31.44,33.94
	testPath.QuadBezier(toFixedP(6.27, 61.89), toFixedP(31.44, 33.94))
	//Q56.62,6.00,98.55,6.00
	testPath.QuadBezier(toFixedP(56.62, 6.00), toFixedP(98.55, 6.00))
	//Q141.27,6.00,166.64,33.88
	testPath.QuadBezier(toFixedP(141.27, 6.00), toFixedP(166.64, 33.88))
	//Q192.02,61.77,192.02,108.70
	testPath.QuadBezier(toFixedP(192.02, 61.77), toFixedP(192.02, 108.70))
	//Q192.02,175.67,140.86,202.05
	testPath.QuadBezier(toFixedP(192.02, 175.67), toFixedP(140.86, 202.05))
	//Q173.42,216.66,210.08,222.97
	testPath.QuadBezier(toFixedP(173.42, 216.66), toFixedP(210.08, 222.97))
	//z
	testPath.Stop(false)
	//M162.22,109.69 M162.22,109.69
	testPath.Start(toFixedP(162.22, 109.69))
	//Q162.22,70.11,145.61,48.55
	testPath.QuadBezier(toFixedP(162.22, 70.11), toFixedP(145.61, 48.55))
	//Q129.00,27.00,98.42,27.00
	testPath.QuadBezier(toFixedP(129.00, 27.00), toFixedP(98.42, 27.00))
	//Q69.14,27.00,52.53,48.62
	testPath.QuadBezier(toFixedP(69.14, 27.00), toFixedP(52.53, 48.62))
	//Q35.92,70.25,35.92,108.50
	testPath.QuadBezier(toFixedP(35.92, 70.25), toFixedP(35.92, 108.50))
	//Q35.92,146.75,52.53,168.38
	testPath.QuadBezier(toFixedP(35.92, 146.75), toFixedP(52.53, 168.38))
	//Q69.14,190.00,98.42,190.00
	testPath.QuadBezier(toFixedP(69.14, 190.00), toFixedP(98.42, 190.00))
	//Q128.34,190.00,145.28,168.70
	testPath.QuadBezier(toFixedP(128.34, 190.00), toFixedP(145.28, 168.70))
	//Q162.22,147.41,162.22,109.69
	testPath.QuadBezier(toFixedP(162.22, 147.41), toFixedP(162.22, 109.69))
	//z
	testPath.Stop(false)

	return testPath
}

// TestMultiFunction tests a Dasher's ability to function
// as a filler, stroker, and dasher by invoking the corresponding anonymous structs
func TestMultiFunctionGV() image.Image {
	img := image.NewRGBA(image.Rect(0, 0, S, S))
	src := image.NewUniform(color.NRGBA{255, 0, 0, 255})
	scannerGV := rasterx.NewScannerGV(S, S, img, img.Bounds(), src, image.ZP)

	draw.Draw(img, img.Bounds(), image.White, image.ZP, draw.Src)

	d := rasterx.NewDasher(S, S, scannerGV)
	d.SetStroke(10*64, 4*64, rasterx.RoundCap, nil, rasterx.RoundGap, rasterx.ArcClip, []float64{33, 12}, 0)
	p := GetTestPath()

	p.AddTo(d)
	d.Draw()
	d.Clear()
	return img
}

Note testPath.Stop(false) in GetTestPath.
Result is in attached file:
screenshot

i able to resolve issue by adding new PathCommand:

// Human readable path constants
const (
	PathMoveTo PathCommand = iota
	PathLineTo
	PathQuadTo
	PathCubicTo
	PathClose
	PathCloseF
)

...

// Close joins the ends of the path
func (p *Path) Stop(closeLoop bool) {
	if closeLoop {
		*p = append(*p, fixed.Int26_6(PathClose))
	} else {
		*p = append(*p, fixed.Int26_6(PathCloseF))
	}
}

// AddPath adds the Path p to q. This bridges the path and adder interface.
func (p Path) AddTo(q Adder) {
	for i := 0; i < len(p); {
		switch PathCommand(p[i]) {
		case PathMoveTo:
			q.Start(fixed.Point26_6{p[i+1], p[i+2]})
			i += 3
		case PathLineTo:
			q.Line(fixed.Point26_6{p[i+1], p[i+2]})
			i += 3
		case PathQuadTo:
			q.QuadBezier(fixed.Point26_6{p[i+1], p[i+2]}, fixed.Point26_6{p[i+3], p[i+4]})
			i += 5
		case PathCubicTo:
			q.CubeBezier(fixed.Point26_6{p[i+1], p[i+2]},
				fixed.Point26_6{p[i+3], p[i+4]}, fixed.Point26_6{p[i+5], p[i+6]})
			i += 7
		case PathClose:
			q.Stop(true)
			i += 1
		case PathCloseF:
		 	q.Stop(false)
		  	i += 1
		default:
			panic("adder geom: bad path")
		}
	}
	q.Stop(false)
}

but i am not sure if this is correct fix.

Regards.

Dashes = [0,0] ends up in infinite loop

if you scale down lines with dashes to a sufficiently small size, the fixed.Int26_6 version can end up being 0, at which point the Dasher rendering code in dash.go ends up stuck in an infinite loop!

Best soln would be to fix SetStroke to detect the problem and reset Dashes if all are 0.

I'm now catching this upstream, but would be good to fix here too.

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.