package pdfhelper import ( "fmt" "strings" "git.to-net.rs/marko.tikvic/gofpdf" ) // Block ... const ( CENTER = "C" LEFT = "L" RIGHT = "R" TOP = "T" BOTTOM = "B" FULL = "1" NOBORDER = "" ) const ( CONTINUE = 0 NEWLINE = 1 BELLOW = 2 ) const ( cyrillicEncoding = "cp1251" latinEncoding = "cp1250" ) // Helper ... type Helper struct { *gofpdf.Fpdf translators map[string]func(string) string } // New ... func New(ori, unit, size string) *Helper { helper := &Helper{ Fpdf: gofpdf.New(ori, unit, size, ""), } return helper } func (pdf *Helper) LoadTranslators() { pdf.translators = make(map[string]func(string) string) pdf.translators[latinEncoding] = pdf.UnicodeTranslatorFromDescriptor(latinEncoding) pdf.translators[cyrillicEncoding] = pdf.UnicodeTranslatorFromDescriptor(cyrillicEncoding) } // InsertTab ... func (pdf *Helper) InsertTab(count int, w, h float64) { for i := 0; i < count; i++ { pdf.Cell(w, h, "") } } // CellWithBox ... func (pdf *Helper) CellWithBox(w, h float64, text, align string) { //pdf.drawCellMargins(w, h) //pdf.Cell(w, h, text) pdf.CellFormat(w, h, pdf.ToUTF8(text), FULL, CONTINUE, align, false, 0, "") } func (pdf *Helper) CellWithMargins(w, h float64, text, align string, index, of int) { len := of - 1 border := "" // if top cell if index == 0 { border += "T" } border += "LR" // always draw these // if bottom cell if index == len { border += "B" } pdf.CellFormat(w, h, pdf.ToUTF8(text), border, CONTINUE, align, false, 0, "") } // MultiRowCellWithBox ... func (pdf *Helper) MultiRowCellWithBox(w, h float64, text []string, align string) { pdf.drawCellMargins(w, h*float64(len(text))) for i := range text { pdf.CellFormat(w, h, pdf.ToUTF8(text[i]), "", BELLOW, align, false, 0, "") } } // CellFormat(w, h, text, borders, newLine, fill) type FormatedCell struct { W, H float64 Text string Font, FontStyle string FontSize float64 Border string Alignment string } func (pdf *Helper) FCell(x, y float64, c FormatedCell) { pdf.SetXY(x, y) pdf.SetFont(c.Font, c.FontStyle, c.FontSize) pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "") } func (pdf *Helper) Column(x, y float64, cells []FormatedCell) { pdf.SetXY(x, y) for _, c := range cells { pdf.SetFont(c.Font, c.FontStyle, c.FontSize) pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "") //pdf.CellFormat(c.w, c.h, c.text, c.border, BELLOW, align, false, 0, "") } } // NewLine ... func (pdf *Helper) NewLine(h float64) { pdf.Ln(h) } // WriteColumns ... func (pdf *Helper) WriteColumns(align string, cols []PDFCell) { for _, c := range cols { pdf.CellFormat(c.width, c.height, pdf.ToUTF8(c.data), "", CONTINUE, align, false, 0, "") } } func (pdf *Helper) Row(x, y float64, cells []FormatedCell) { pdf.SetXY(x, y) for _, c := range cells { pdf.SetFont(c.Font, c.FontStyle, c.FontSize) pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "") } } const threeDots = "\u2056\u2056\u2056" // WriteColumnsWithAlignment ... func (pdf *Helper) WriteColumnsWithAlignment(cols []PDFCellAligned) { for _, c := range cols { lines := pdf.SplitText(c.data, c.width) if len(lines) == 1 { pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]), "", CONTINUE, c.alignment, false, 0, "") } else { pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]+threeDots), "", CONTINUE, c.alignment, false, 0, "") } } } func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string { parts := pdf.Fpdf.SplitText(text, maxWidth) if len(parts) > 1 { return parts[0] + limiter } return text } // InsertImage ... func (pdf *Helper) InsertImage(img string, x, y, w, h float64) { imgType := "" if parts := strings.Split(img, "."); len(parts) >= 2 { imgType = parts[len(parts)-1] } opt := gofpdf.ImageOptions{ ImageType: imgType, ReadDpi: false, AllowNegativePosition: false, } autoBreak := false // if it's not false then you can't draw the image at an arbitrary height (y position) pdf.ImageOptions(img, x, y, w, h, autoBreak, opt, 0, "") } // PDFCell ... type PDFCell struct { data string height, width float64 } // PDFCellAligned ... type PDFCellAligned struct { alignment string data string height, width float64 } func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 { family, _, _, _ = pdf.setCorrectFontFamily(textEncoding(txt)) return pdf.Fpdf.TextLength(txt, family, style, size) } func textEncoding(s string) string { encoding := latinEncoding runes := []rune(s) for _, r := range runes { if uint64(r) >= 0x0402 && uint64(r) <= 0x044f { encoding = cyrillicEncoding break } } return encoding } // ToUTF8 ... func (pdf *Helper) ToUTF8(s string) string { encoding := textEncoding(s) pdf.setCorrectFontFamily(encoding) translator, ok := pdf.translators[encoding] if !ok { return "" } return translator(s) } func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) { family, style, ptSize, unitSize = pdf.GetFontInfo() if enc == cyrillicEncoding { if !strings.HasSuffix(family, "cyrillic") { family += "cyrillic" } } else { if strings.HasSuffix(family, "cyrillic") { family = strings.TrimSuffix(family, "cyrillic") } } pdf.SetFont(family, style, ptSize) return family, style, ptSize, unitSize } func (pdf *Helper) PageHasSpace(requiredHeight float64) bool { _, h := pdf.GetPageSize() _, _, _, bot := pdf.GetMargins() return (h - bot - pdf.GetY()) > requiredHeight } func (pdf *Helper) imageCenterOffset(w, h float64) (x, y float64) { pageW, pageH := pdf.GetPageSize() x = pageW/2.0 - w/2.0 y = pageH/2.0 - h/2.0 return x, y } // call before drawing the cell func (pdf *Helper) drawCellMargins(cw, ch float64) { x0, y0 := pdf.GetX(), pdf.GetY() pdf.DrawBox(x0, y0, cw, ch) } // DrawBox ... func (pdf Helper) DrawBox(x0, y0, w, h float64) { pdf.Line(x0, y0, x0+w, y0) pdf.Line(x0+w, y0, x0+w, y0+h) pdf.Line(x0+w, y0+h, x0, y0+h) pdf.Line(x0, y0+h, x0, y0) } // Strana %d/{TotalPages} func (pdf *Helper) InsertPageNumber(x, y float64, format string) { num := fmt.Sprintf(format, pdf.PageNo()) pdf.Column(x, y, []FormatedCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}}) } func (pdf *Helper) SuperscriptText(x, y, cw, ch float64, text, script string) { family, style, size, sizeU := pdf.setCorrectFontFamily(textEncoding(text)) pdf.FCell(x, y, FormatedCell{cw, ch, text, family, style, size, NOBORDER, LEFT}) sx := x + pdf.TextLength(text, family, style, size) sy := y - sizeU*0.2 pdf.FCell(sx, sy, FormatedCell{cw, ch, script, family, style, size - 2, NOBORDER, LEFT}) }