package wpdf import ( "bytes" "github.com/jung-kurt/gofpdf" "gogs.mikescher.com/BlackForestBytes/goext/langext" ) type WPDFBuilder struct { b *gofpdf.Fpdf tr func(string) string cellHeight float64 cellSpacing float64 fontName PDFFontFamily fontStyle PDFFontStyle fontSize float64 debug bool } type PDFMargins struct { Left float64 Top float64 Right float64 } type PDFColor struct { R int G int B int } func NewPDFBuilder(orientation PDFOrientation, size PDFSize, unicode bool) *WPDFBuilder { fpdfbuilder := gofpdf.New(string(orientation), "mm", string(size), "") var tr func(string) string if unicode { tr = fpdfbuilder.UnicodeTranslatorFromDescriptor("") } else { tr = func(s string) string { return s } } b := &WPDFBuilder{ b: fpdfbuilder, tr: tr, cellHeight: 5, cellSpacing: 1, } b.SetMargins(PDFMargins{Left: 15, Top: 25, Right: 15}) // default values b.SetFont(FontHelvetica, Normal, 12) // ensures font is set return b } func (b *WPDFBuilder) FPDF() *gofpdf.Fpdf { return b.b } func (b *WPDFBuilder) SetMargins(v PDFMargins) { b.b.SetMargins(v.Left, v.Top, v.Right) } func (b *WPDFBuilder) AddPage() { b.b.AddPage() if b.debug { ml, mt, mr, mb := b.GetMargins() pw, ph := b.GetPageSize() b.Rect(pw-ml-mr, ph-mt-mb, RectOutline, NewPDFRectOpt().X(ml).Y(mt).LineWidth(0.25).DrawColor(0, 0, 128)) b.Rect(pw, mt, RectFill, NewPDFRectOpt().X(0).Y(0).FillColor(0, 0, 255).Alpha(0.2, BlendNormal)) b.Rect(ml, ph-mt-mb, RectFill, NewPDFRectOpt().X(0).Y(mt).FillColor(0, 0, 255).Alpha(0.2, BlendNormal)) b.Rect(mr, ph-mt-mb, RectFill, NewPDFRectOpt().X(pw-mr).Y(mt).FillColor(0, 0, 255).Alpha(0.2, BlendNormal)) b.Rect(pw, mb, RectFill, NewPDFRectOpt().X(0).Y(ph-mb).FillColor(0, 0, 255).Alpha(0.2, BlendNormal)) } } func (b *WPDFBuilder) SetTextColor(cr, cg, cb int) { b.b.SetTextColor(cr, cg, cb) } func (b *WPDFBuilder) GetTextColor() (cr, cg, cb int) { return b.b.GetTextColor() } func (b *WPDFBuilder) SetDrawColor(cr, cg, cb int) { b.b.SetDrawColor(cr, cg, cb) } func (b *WPDFBuilder) GetDrawColor() (cr, cg, cb int) { return b.b.GetDrawColor() } func (b *WPDFBuilder) SetFillColor(cr, cg, cb int) { b.b.SetFillColor(cr, cg, cb) } func (b *WPDFBuilder) GetFillColor() (cr, cg, cb int) { return b.b.GetFillColor() } func (b *WPDFBuilder) SetLineWidth(w float64) { b.b.SetLineWidth(w) } func (b *WPDFBuilder) GetLineWidth() float64 { return b.b.GetLineWidth() } func (b *WPDFBuilder) SetFont(fontName PDFFontFamily, fontStyle PDFFontStyle, fontSize float64) { b.b.SetFont(string(fontName), string(fontStyle), fontSize) b.fontName = fontName b.fontStyle = fontStyle b.fontSize = fontSize b.cellHeight = b.b.PointConvert(fontSize) } func (b *WPDFBuilder) GetFontSize() float64 { return b.fontSize } func (b *WPDFBuilder) GetFontFamily() PDFFontStyle { return b.fontStyle } func (b *WPDFBuilder) GetFontStyle() float64 { return b.fontSize } func (b *WPDFBuilder) SetCellSpacing(h float64) { b.cellSpacing = h } func (b *WPDFBuilder) Ln(h float64) { xBefore, yBefore := b.GetXY() b.b.Ln(h) yAfter := b.GetY() if b.debug { _, _, mr, _ := b.GetMargins() pw, _ := b.GetPageSize() b.Rect(pw-mr-xBefore, yAfter-yBefore, RectOutline, NewPDFRectOpt().X(xBefore).Y(yBefore).LineWidth(0.25).DrawColor(128, 128, 0).Alpha(0.5, BlendNormal)) b.Rect(pw-mr-xBefore, yAfter-yBefore, RectFill, NewPDFRectOpt().X(xBefore).Y(yBefore).LineWidth(0.25).FillColor(128, 128, 0).Alpha(0.1, BlendNormal)) b.Line(xBefore, yBefore, pw-mr, yAfter, NewPDFLineOpt().LineWidth(0.25).DrawColor(128, 128, 0)) } } func (b *WPDFBuilder) Build() ([]byte, error) { buf := new(bytes.Buffer) err := b.b.Output(buf) if err != nil { return nil, err } return buf.Bytes(), nil } func (b *WPDFBuilder) SetX(x float64) { b.b.SetX(x) } func (b *WPDFBuilder) IncX(dx float64) { b.b.SetX(b.b.GetX() + dx) } func (b *WPDFBuilder) GetX() float64 { return b.b.GetX() } func (b *WPDFBuilder) SetY(y float64) { b.b.SetY(y) } func (b *WPDFBuilder) GetY() float64 { return b.b.GetY() } func (b *WPDFBuilder) SetXY(x float64, y float64) { b.b.SetXY(x, y) } func (b *WPDFBuilder) GetXY() (x float64, y float64) { return b.b.GetXY() } func (b *WPDFBuilder) GetMargins() (left, top, right, bottom float64) { return b.b.GetMargins() } func (b *WPDFBuilder) GetMarginLeft() float64 { v, _, _, _ := b.b.GetMargins() return v } func (b *WPDFBuilder) GetMarginTop() float64 { _, v, _, _ := b.b.GetMargins() return v } func (b *WPDFBuilder) GetMarginRight() float64 { _, _, v, _ := b.b.GetMargins() return v } func (b *WPDFBuilder) GetMarginBottom() float64 { _, _, _, v := b.b.GetMargins() return v } func (b *WPDFBuilder) GetPageSize() (width, height float64) { return b.b.GetPageSize() } func (b *WPDFBuilder) GetPageWidth() float64 { v, _ := b.b.GetPageSize() return v } func (b *WPDFBuilder) GetPageHeight() float64 { _, v := b.b.GetPageSize() return v } func (b *WPDFBuilder) GetWorkAreaWidth() float64 { return b.GetPageWidth() - b.GetMarginLeft() - b.GetMarginRight() } func (b *WPDFBuilder) SetAutoPageBreak(auto bool, margin float64) { b.b.SetAutoPageBreak(auto, margin) } func (b *WPDFBuilder) SetFooterFunc(fnc func()) { b.b.SetFooterFunc(fnc) } func (b *WPDFBuilder) PageNo() int { return b.b.PageNo() } func (b *WPDFBuilder) GetStringWidth(str string, opts ...PDFCellOpt) float64 { var fontNameOverride *PDFFontFamily var fontStyleOverride *PDFFontStyle var fontSizeOverride *float64 for _, opt := range opts { fontNameOverride = langext.CoalesceOpt(opt.fontNameOverride, fontNameOverride) fontStyleOverride = langext.CoalesceOpt(opt.fontStyleOverride, fontStyleOverride) fontSizeOverride = langext.CoalesceOpt(opt.fontSizeOverride, fontSizeOverride) } if fontNameOverride != nil || fontStyleOverride != nil || fontSizeOverride != nil { oldFontName := b.fontName oldFontStyle := b.fontStyle oldFontSize := b.fontSize newFontName := langext.Coalesce(fontNameOverride, oldFontName) newFontStyle := langext.Coalesce(fontStyleOverride, oldFontStyle) newFontSize := langext.Coalesce(fontSizeOverride, oldFontSize) b.SetFont(newFontName, newFontStyle, newFontSize) defer func() { b.SetFont(oldFontName, oldFontStyle, oldFontSize) }() } return b.b.GetStringWidth(str) } func (b *WPDFBuilder) Debug(v bool) { b.debug = v }