Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flipping the Y axis doesn't work with "draw2dpdf.GraphicContext" #139

Open
korayeyinc opened this issue Jan 8, 2018 · 4 comments
Open
Labels

Comments

@korayeyinc
Copy link

korayeyinc commented Jan 8, 2018

I've written an helper function to flip the image around the Y axis as in below:

// Flips the image around the Y axis.
func invertY(gc draw2d.GraphicContext, height int) {
gc.Translate(0, float64(height))
gc.Scale(1, -1)
}

It works just fine with the "draw2dimg.GraphicContext", but silently fails if the current graphic context is in "draw2dpdf.GraphicContext". The "gofpdf" package seems to provide image transformation functions such as:

func (f *Fpdf) Transform(tm TransformMatrix)
func (f *Fpdf) TransformBegin()
func (f *Fpdf) TransformEnd()
func (f *Fpdf) TransformMirrorHorizontal(x float64)
func (f *Fpdf) TransformMirrorLine(angle, x, y float64)
func (f *Fpdf) TransformMirrorPoint(x, y float64)
func (f *Fpdf) TransformMirrorVertical(y float64)
func (f *Fpdf) TransformRotate(angle, x, y float64)
func (f *Fpdf) TransformScale(scaleWd, scaleHt, x, y float64)
func (f *Fpdf) TransformScaleX(scaleWd, x, y float64)
func (f *Fpdf) TransformScaleXY(s, x, y float64)
func (f *Fpdf) TransformScaleY(scaleHt, x, y float64)
func (f *Fpdf) TransformSkew(angleX, angleY, x, y float64)
func (f *Fpdf) TransformSkewX(angleX, x, y float64)
func (f *Fpdf) TransformSkewY(angleY, x, y float64)
func (f *Fpdf) TransformTranslate(tx, ty float64)
func (f *Fpdf) TransformTranslateX(tx float64)
func (f *Fpdf) TransformTranslateY(ty float64)

So, is it possible to add some basic functionality to "draw2dpdf.GraphicContext", so that we can make use of these image transformation capabilities ? Thanks.

@llgcode llgcode added the bug label Jan 8, 2018
@llgcode
Copy link
Owner

llgcode commented Jan 8, 2018

Hi @korayeyinc ,
Can you provide a code that reproduces the problem please? @stanim what do you think about this bug?

draw2dpdf already uses TransformTranslate and TransformScale in implementation of gc.Translate and gc.Scale.
regards

@korayeyinc
Copy link
Author

Hi @llgcode ,

Sure, the code below builds successfully using go version "go1.9.2" on a "linux/amd64" box -- i'm sorry about the formatting though, the code tag seems to unindent the code:

package main

import (
"image"
"image/color"

"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/draw2dimg"
"github.com/llgcode/draw2d/draw2dpdf"
)

var black = color.RGBA{0, 0, 0, 255}

// Flips the image around the Y axis.
func invertY(gc draw2d.GraphicContext, height int) {
gc.Translate(0, float64(height))
gc.Scale(1, -1)
}

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

// Generates PDF output.
func genPDF() {
height := 600
dst := draw2dpdf.NewPdf("L", "mm", "A4")
gc := draw2dpdf.NewGraphicContext(dst)

gc.SetStrokeColor(black)
gc.SetLineWidth(2)

gc.MoveTo(10, 10)
gc.LineTo(100, 100)
gc.QuadCurveTo(100, 10, 10, 10)
gc.Close()

invertY(gc, height)
gc.Stroke()

filename := "sample.pdf"
err := draw2dpdf.SaveToPdfFile(filename, dst)
check(err)
}

// Generates PNG output.
func genPNG() {
width, height := 800, 600
dst := image.NewRGBA(image.Rect(0, 0, width, height))
gc := draw2dimg.NewGraphicContext(dst)

gc.SetStrokeColor(black)
gc.SetLineWidth(2)

gc.MoveTo(10, 10)
gc.LineTo(100, 100)
gc.QuadCurveTo(100, 10, 10, 10)
gc.Close()

invertY(gc, height)
gc.Stroke()

filename := "sample.png"
err := draw2dimg.SaveToPngFile(filename, dst)
check(err)
}

func main() {
genPNG()
genPDF()
}

By the way, it generates PNG output successfully but throws the error "panic: transformation context is not active" during PDF generation. Thanks.

@llgcode
Copy link
Owner

llgcode commented Jan 8, 2018

Thansk @korayeyinc ,
I think the problem is drawimg apply the transformation also on the path that is not already stroke or fill unlike drawpdf. Apply the transformation before creating the path (before gc.MoveTo), transformation have to be set before creating a path.

Just for tips:
You can use the code blocks for code.
I used the playground for guickly formatting.

package main

import (
	"image"
	"image/color"

	"github.com/llgcode/draw2d"
	"github.com/llgcode/draw2d/draw2dimg"
	"github.com/llgcode/draw2d/draw2dpdf"
)

var black = color.RGBA{0, 0, 0, 255}

// Flips the image around the Y axis.
func invertY(gc draw2d.GraphicContext, height int) {
	gc.Translate(0, float64(height))
	gc.Scale(1, -1)
}

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

// Generates PDF output.
func genPDF() {
	height := 600
	dst := draw2dpdf.NewPdf("L", "mm", "A4")
	gc := draw2dpdf.NewGraphicContext(dst)

	gc.SetStrokeColor(black)
	gc.SetLineWidth(2)

	gc.MoveTo(10, 10)
	gc.LineTo(100, 100)
	gc.QuadCurveTo(100, 10, 10, 10)
	gc.Close()

	invertY(gc, height)
	gc.Stroke()

	filename := "sample.pdf"
	err := draw2dpdf.SaveToPdfFile(filename, dst)
	check(err)
}

// Generates PNG output.
func genPNG() {
	width, height := 800, 600
	dst := image.NewRGBA(image.Rect(0, 0, width, height))
	gc := draw2dimg.NewGraphicContext(dst)

	gc.SetStrokeColor(black)
	gc.SetLineWidth(2)

	gc.MoveTo(10, 10)
	gc.LineTo(100, 100)
	gc.QuadCurveTo(100, 10, 10, 10)
	gc.Close()

	invertY(gc, height)
	gc.Stroke()

	filename := "sample.png"
	err := draw2dimg.SaveToPngFile(filename, dst)
	check(err)
}

func main() {
	genPNG()
	genPDF()
}

regards

@korayeyinc
Copy link
Author

Thanks for the tips. This is taken from the gofpdf package documentation:

go doc gofpdf.TransformBegin

func (f *Fpdf) TransformBegin()
    TransformBegin sets up a transformation context for subsequent text,
    drawings and images. The typical usage is to immediately follow a call to
    this method with a call to one or more of the transformation methods such as
    TransformScale(), TransformSkew(), etc. This is followed by text, drawing or
    image output and finally a call to TransformEnd(). All transformation
    contexts must be properly ended prior to outputting the document.

So, i applied the TransformBegin() and TransformEnd() functions as told in the the documentation and it works:

// Generates PDF output.
func genPDF() {
	height := 600
	dst := draw2dpdf.NewPdf("L", "mm", "A4")
	gc := draw2dpdf.NewGraphicContext(dst)
	dst.TransformBegin()
	invertY(gc, height)
	gc.SetStrokeColor(black)
	gc.SetLineWidth(2)
	
	gc.MoveTo(10, 10)
	gc.LineTo(100, 100)
	gc.QuadCurveTo(100, 10, 10, 10)
	gc.Close()
	dst.TransformEnd()
	gc.Stroke()

	filename := "sample.pdf"
	err := draw2dpdf.SaveToPdfFile(filename, dst)
	check(err)
}

I believe it would be more straightforward if both TransformBegin() and TransformEnd() functions were accessible via gc -- *draw2dpdf.GraphicContext. Also, i should note that it's necessary to apply dst.TransformEnd() function just before gc.Stroke(). Thanks for pointing me in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants