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/png"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
|
@ -79,18 +80,15 @@ func NewGraphicContext(pdf *gofpdf.Fpdf) *GraphicContext {
|
|||
// DrawImage draws an image as PNG
|
||||
// TODO: add type (tp) as parameter to argument list?
|
||||
func (gc *GraphicContext) DrawImage(image image.Image) {
|
||||
// TODO: fix rotation gc.Current.Tr
|
||||
name := strconv.Itoa(int(imageCount))
|
||||
tp := "PNG" // "JPG", "JPEG", "PNG" and "GIF"
|
||||
b := &bytes.Buffer{}
|
||||
png.Encode(b, image)
|
||||
gc.pdf.RegisterImageReader(name, tp, b)
|
||||
bounds := image.Bounds()
|
||||
//x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Dx()), float64(bounds.Dy())
|
||||
x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y)
|
||||
tr := gc.Current.Tr
|
||||
tr.TransformRectangle(&x0, &y0, &x1, &y1)
|
||||
gc.pdf.Image(name, x0, y0, x1-x0, y1-y0, false, tp, 0, "")
|
||||
x0, y0 := float64(bounds.Min.X), float64(bounds.Min.Y)
|
||||
w, h := float64(bounds.Dx()), float64(bounds.Dy())
|
||||
gc.pdf.Image(name, x0, y0, w, h, false, tp, 0, "")
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (gc *GraphicContext) CreateStringPath(text string, x, y float64) (cursor float64) {
|
||||
// TODO: fix rotation of gc.Current.Tr
|
||||
_, _, 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.Cell(x1-x, y1-y, text)
|
||||
gc.pdf.Cell(w, h, text)
|
||||
return w
|
||||
}
|
||||
|
||||
|
@ -175,8 +169,8 @@ var logger = log.New(os.Stdout, "", log.Lshortfile)
|
|||
// draw fills and/or strokes paths
|
||||
func (gc *GraphicContext) draw(style string, paths ...*draw2d.PathStorage) {
|
||||
paths = append(paths, gc.Current.Path)
|
||||
pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr, gc.pdf))
|
||||
// pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.Current.Tr,NewPathLogger(logger, gc.pdf)))
|
||||
pathConverter := NewPathConverter(gc.pdf)
|
||||
// pathConverter := NewPathConverter(NewPathLogger(logger, gc.pdf))
|
||||
pathConverter.Convert(paths...)
|
||||
if gc.Current.FillRule.UseNonZeroWinding() {
|
||||
style += "*"
|
||||
|
@ -245,3 +239,59 @@ func (gc *GraphicContext) SetLineCap(Cap draw2d.Cap) {
|
|||
gc.StackGraphicContext.SetLineCap(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
|
||||
// TODO Seems to have a transform bug here on draw image
|
||||
scale := math.Min((dw-margin*2)/sw, (dh-margin*2)/sh)
|
||||
gc.Save()
|
||||
gc.Translate(margin, margin)
|
||||
gc.Scale(scale, scale)
|
||||
|
||||
gc.DrawImage(source)
|
||||
gc.Restore()
|
||||
|
||||
// Save to pdf
|
||||
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