use pdf native transforms
This commit is contained in:
parent
458c46b28c
commit
b3bea4f206
3 changed files with 65 additions and 70 deletions
|
@ -10,6 +10,7 @@ import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
@ -79,18 +80,15 @@ func NewGraphicContext(pdf *gofpdf.Fpdf) *GraphicContext {
|
||||||
// DrawImage draws an image as PNG
|
// DrawImage draws an image as PNG
|
||||||
// TODO: add type (tp) as parameter to argument list?
|
// TODO: add type (tp) as parameter to argument list?
|
||||||
func (gc *GraphicContext) DrawImage(image image.Image) {
|
func (gc *GraphicContext) DrawImage(image image.Image) {
|
||||||
// TODO: fix rotation gc.Current.Tr
|
|
||||||
name := strconv.Itoa(int(imageCount))
|
name := strconv.Itoa(int(imageCount))
|
||||||
tp := "PNG" // "JPG", "JPEG", "PNG" and "GIF"
|
tp := "PNG" // "JPG", "JPEG", "PNG" and "GIF"
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
png.Encode(b, image)
|
png.Encode(b, image)
|
||||||
gc.pdf.RegisterImageReader(name, tp, b)
|
gc.pdf.RegisterImageReader(name, tp, b)
|
||||||
bounds := image.Bounds()
|
bounds := image.Bounds()
|
||||||
//x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Dx()), float64(bounds.Dy())
|
x0, y0 := float64(bounds.Min.X), float64(bounds.Min.Y)
|
||||||
x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y)
|
w, h := float64(bounds.Dx()), float64(bounds.Dy())
|
||||||
tr := gc.Current.Tr
|
gc.pdf.Image(name, x0, y0, w, h, false, tp, 0, "")
|
||||||
tr.TransformRectangle(&x0, &y0, &x1, &y1)
|
|
||||||
gc.pdf.Image(name, x0, y0, x1-x0, y1-y0, false, tp, 0, "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear draws a white rectangle over the whole page
|
// Clear draws a white rectangle over the whole page
|
||||||
|
@ -123,13 +121,9 @@ func (gc *GraphicContext) GetStringBounds(s string) (left, top, right, bottom fl
|
||||||
|
|
||||||
// CreateStringPath creates a path from the string s at x, y, and returns the string width.
|
// CreateStringPath creates a path from the string s at x, y, and returns the string width.
|
||||||
func (gc *GraphicContext) CreateStringPath(text string, x, y float64) (cursor float64) {
|
func (gc *GraphicContext) CreateStringPath(text string, x, y float64) (cursor float64) {
|
||||||
// TODO: fix rotation of gc.Current.Tr
|
|
||||||
_, _, w, h := gc.GetStringBounds(text)
|
_, _, w, h := gc.GetStringBounds(text)
|
||||||
x1, y1 := x+w, y+h
|
|
||||||
tr := gc.Current.Tr
|
|
||||||
tr.TransformRectangle(&x, &y, &x1, &y1)
|
|
||||||
gc.pdf.MoveTo(x, y)
|
gc.pdf.MoveTo(x, y)
|
||||||
gc.pdf.Cell(x1-x, y1-y, text)
|
gc.pdf.Cell(w, h, text)
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,8 +169,8 @@ var logger = log.New(os.Stdout, "", log.Lshortfile)
|
||||||
// draw fills and/or strokes paths
|
// draw fills and/or strokes paths
|
||||||
func (gc *GraphicContext) draw(style string, paths ...*draw2d.PathStorage) {
|
func (gc *GraphicContext) draw(style string, paths ...*draw2d.PathStorage) {
|
||||||
paths = append(paths, gc.Current.Path)
|
paths = append(paths, gc.Current.Path)
|
||||||
pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr, gc.pdf))
|
pathConverter := NewPathConverter(gc.pdf)
|
||||||
// pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr,NewPathLogger(logger, gc.pdf)))
|
// pathConverter := NewPathConverter(NewPathLogger(logger, gc.pdf))
|
||||||
pathConverter.Convert(paths...)
|
pathConverter.Convert(paths...)
|
||||||
if gc.Current.FillRule.UseNonZeroWinding() {
|
if gc.Current.FillRule.UseNonZeroWinding() {
|
||||||
style += "*"
|
style += "*"
|
||||||
|
@ -245,3 +239,59 @@ func (gc *GraphicContext) SetLineCap(Cap draw2d.Cap) {
|
||||||
gc.StackGraphicContext.SetLineCap(Cap)
|
gc.StackGraphicContext.SetLineCap(Cap)
|
||||||
gc.pdf.SetLineCapStyle(caps[Cap])
|
gc.pdf.SetLineCapStyle(caps[Cap])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transformations
|
||||||
|
|
||||||
|
// Scale generally scales the following text, drawings and images.
|
||||||
|
// sx and sy are the scaling factors for width and height.
|
||||||
|
// This must be placed between gc.Save() and gc.Restore(), otherwise
|
||||||
|
// the pdf is invalid.
|
||||||
|
func (gc *GraphicContext) Scale(sx, sy float64) {
|
||||||
|
gc.StackGraphicContext.Scale(sx, sy)
|
||||||
|
gc.pdf.TransformScale(sx*100, sy*100, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate rotates the following text, drawings and images.
|
||||||
|
// Angle is specified in radians and measured clockwise from the
|
||||||
|
// 3 o'clock position.
|
||||||
|
// This must be placed between gc.Save() and gc.Restore(), otherwise
|
||||||
|
// the pdf is invalid.
|
||||||
|
func (gc *GraphicContext) Rotate(angle float64) {
|
||||||
|
gc.StackGraphicContext.Rotate(angle)
|
||||||
|
gc.pdf.TransformRotate(-angle*180/math.Pi, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate moves the following text, drawings and images
|
||||||
|
// horizontally and vertically by the amounts specified by tx and ty.
|
||||||
|
// This must be placed between gc.Save() and gc.Restore(), otherwise
|
||||||
|
// the pdf is invalid.
|
||||||
|
func (gc *GraphicContext) Translate(tx, ty float64) {
|
||||||
|
gc.StackGraphicContext.Translate(tx, ty)
|
||||||
|
gc.pdf.TransformTranslate(tx, ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save saves the current context stack
|
||||||
|
// (transformation, font, color,...).
|
||||||
|
func (gc *GraphicContext) Save() {
|
||||||
|
gc.StackGraphicContext.Save()
|
||||||
|
gc.pdf.TransformBegin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore restores the current context stack
|
||||||
|
// (transformation, color,...). Restoring the font is not supported.
|
||||||
|
func (gc *GraphicContext) Restore() {
|
||||||
|
gc.pdf.TransformEnd()
|
||||||
|
gc.StackGraphicContext.Restore()
|
||||||
|
c := gc.Current
|
||||||
|
gc.SetFontSize(c.FontSize)
|
||||||
|
// gc.SetFontData(c.FontData) unsupported, causes bug (do not enable)
|
||||||
|
gc.SetLineWidth(c.LineWidth)
|
||||||
|
gc.SetStrokeColor(c.StrokeColor)
|
||||||
|
gc.SetFillColor(c.FillColor)
|
||||||
|
gc.SetFillRule(c.FillRule)
|
||||||
|
// gc.SetLineDash(c.Dash, c.DashOffset) // TODO
|
||||||
|
gc.SetLineCap(c.Cap)
|
||||||
|
// gc.SetLineJoin(c.Join) // TODO
|
||||||
|
// c.Path unsupported
|
||||||
|
// c.Font unsupported
|
||||||
|
}
|
||||||
|
|
|
@ -37,10 +37,12 @@ func main() {
|
||||||
// Draw image to fit in the frame
|
// Draw image to fit in the frame
|
||||||
// TODO Seems to have a transform bug here on draw image
|
// TODO Seems to have a transform bug here on draw image
|
||||||
scale := math.Min((dw-margin*2)/sw, (dh-margin*2)/sh)
|
scale := math.Min((dw-margin*2)/sw, (dh-margin*2)/sh)
|
||||||
|
gc.Save()
|
||||||
gc.Translate(margin, margin)
|
gc.Translate(margin, margin)
|
||||||
gc.Scale(scale, scale)
|
gc.Scale(scale, scale)
|
||||||
|
|
||||||
gc.DrawImage(source)
|
gc.DrawImage(source)
|
||||||
|
gc.Restore()
|
||||||
|
|
||||||
// Save to pdf
|
// Save to pdf
|
||||||
pdf2d.SaveToPdfFile("frame-image.pdf", dest)
|
pdf2d.SaveToPdfFile("frame-image.pdf", dest)
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
// Copyright 2015 The draw2d Authors. All rights reserved.
|
|
||||||
// created: 26/06/2015 by Stani Michiels
|
|
||||||
|
|
||||||
package pdf2d
|
|
||||||
|
|
||||||
import "github.com/stanim/draw2d"
|
|
||||||
|
|
||||||
// VertexMatrixTransform implements Vectorizer and applies the Matrix
|
|
||||||
// transformation tr. It is normally wrapped around gofpdf Fpdf
|
|
||||||
// or PathLogger.
|
|
||||||
type VertexMatrixTransform struct {
|
|
||||||
tr draw2d.MatrixTransform
|
|
||||||
Next Vectorizer
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVertexMatrixTransform constructs an new VertexMatrixTransform
|
|
||||||
func NewVertexMatrixTransform(tr draw2d.MatrixTransform,
|
|
||||||
vectorizer Vectorizer) *VertexMatrixTransform {
|
|
||||||
return &VertexMatrixTransform{tr, vectorizer}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MoveTo creates a new subpath that start at the specified point
|
|
||||||
func (vmt *VertexMatrixTransform) MoveTo(x, y float64) {
|
|
||||||
vmt.tr.Transform(&x, &y)
|
|
||||||
vmt.Next.MoveTo(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LineTo adds a line to the current subpath
|
|
||||||
func (vmt *VertexMatrixTransform) LineTo(x, y float64) {
|
|
||||||
vmt.tr.Transform(&x, &y)
|
|
||||||
vmt.Next.LineTo(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurveTo adds a quadratic bezier curve to the current subpath
|
|
||||||
func (vmt *VertexMatrixTransform) CurveTo(cx, cy, x, y float64) {
|
|
||||||
vmt.tr.Transform(&cx, &cy, &x, &y)
|
|
||||||
vmt.Next.CurveTo(cx, cy, x, y)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurveBezierCubicTo adds a cubic bezier curve to the current subpath
|
|
||||||
func (vmt *VertexMatrixTransform) CurveBezierCubicTo(cx1, cy1,
|
|
||||||
cx2, cy2, x, y float64) {
|
|
||||||
vmt.tr.Transform(&cx1, &cy1, &cx2, &cy2, &x, &y)
|
|
||||||
vmt.Next.CurveBezierCubicTo(cx1, cy1, cx2, cy2, x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArcTo adds an arc to the current subpath
|
|
||||||
func (vmt *VertexMatrixTransform) ArcTo(x, y, rx, ry, degRotate, degStart, degEnd float64) {
|
|
||||||
vmt.tr.Transform(&x, &y)
|
|
||||||
vmt.Next.ArcTo(x, y, rx, ry, degRotate, degStart, degEnd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClosePath closes the subpath
|
|
||||||
func (vmt *VertexMatrixTransform) ClosePath() {
|
|
||||||
vmt.Next.ClosePath()
|
|
||||||
}
|
|
Loading…
Reference in a new issue