github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/core/utils/pdf/pdfutils.go (about) 1 package pdf 2 3 import ( 4 "fmt" 5 "path/filepath" 6 "strings" 7 "time" 8 9 rd "github.com/benoitkugler/goACVE/server/core/rawdata" 10 11 "github.com/jung-kurt/gofpdf" 12 ) 13 14 // ------------------------------------ Helpers ------------------------------------ 15 type rgb [3]int 16 17 type CustomPdf struct { 18 *gofpdf.Fpdf 19 Tr func(string) string 20 } 21 22 // renvoie un pdf prêt à l'emploi (footer et page prête) 23 func InitPdfDetails(addPage bool, footerOnlyLastPage bool) CustomPdf { 24 pdf := gofpdf.New("P", "mm", "A4", "") 25 pdf.SetFont("Arial", "", 12) 26 pdf.SetMargins(sideMargin, marginTop, -1) 27 mypdf := CustomPdf{Fpdf: pdf, Tr: pdf.UnicodeTranslatorFromDescriptor("")} 28 if footerOnlyLastPage { 29 mypdf.SetFooterFuncLpi(func(lastPage bool) { 30 if lastPage { 31 mypdf.drawFooter() 32 } 33 }) 34 } else { 35 mypdf.SetFooterFunc(mypdf.drawFooter) 36 } 37 if addPage { 38 mypdf.AddPage() 39 } 40 return mypdf 41 } 42 43 func initPdf() CustomPdf { 44 return InitPdfDetails(true, true) 45 } 46 47 func (pdf CustomPdf) SetFillColor(c rgb) { 48 pdf.Fpdf.SetFillColor(c[0], c[1], c[2]) 49 } 50 51 func (pdf CustomPdf) SetDrawColor(c rgb) { 52 pdf.Fpdf.SetDrawColor(c[0], c[1], c[2]) 53 } 54 55 func (pdf CustomPdf) insertImage(name string, w, h float64) { 56 file := filepath.Join(IMAGES_PATH, name) 57 pdf.ImageOptions(file, -1, -1, w, h, true, gofpdf.ImageOptions{}, 0, "") 58 } 59 60 func (pdf CustomPdf) AreaWidth() float64 { 61 w, _ := pdf.GetPageSize() 62 mL, _, mR, _ := pdf.GetMargins() 63 return w - mL - mR 64 } 65 66 func (pdf CustomPdf) areaBottomLimit() float64 { 67 _, h := pdf.GetPageSize() 68 return h - heightFooter - 6 69 } 70 71 func (pdf CustomPdf) LineHeight() float64 { 72 _, lineHeight := pdf.GetFontSize() 73 return lineHeight + 1 74 } 75 76 func (pdf CustomPdf) CellFormat(w, h float64, txtStr, borderStr, alignStr string, fill bool) { 77 pdf.Fpdf.CellFormat(w, h, txtStr, borderStr, 0, alignStr, fill, 0, "") 78 } 79 80 func (pdf CustomPdf) widthNeeded(lines []string) float64 { 81 max, addPadding := 0., 5. 82 for _, s := range lines { 83 w := pdf.GetStringWidth(s) 84 if w > max { 85 max = w 86 } 87 } 88 return max + addPadding 89 } 90 91 // ------------------------------------------ Header / Footer ------------------------------------------ 92 93 // Attention, len(lignes) <= 5 sinon ca dépasse ! 94 func (pdf CustomPdf) drawHeaderRight(expediteur []string, h float64) { 95 lineHeight := pdf.LineHeight() 96 padding := (h - lineHeight*float64(len(expediteur))) / 2 97 pdf.SetY(pdf.GetY() + padding) 98 pdf.MultiCell(pdf.AreaWidth(), lineHeight, pdf.Tr(strings.Join(expediteur, "\n")), "", "RM", false) 99 } 100 101 // DrawHeader ajoute un header 102 // `iconWidth` et `iconHeight` peuvent être non nul 103 // pour forcer une taille d'icône. 104 func (pdf CustomPdf) DrawHeader(rightHeaderContent []string, iconWidth, iconHeight float64) { 105 pdf.SetY(pdf.GetY() + paddingHeaderTop) 106 oldY := pdf.GetY() 107 pdf.insertImage("app.png", iconWidth, iconHeight) 108 y, h := pdf.GetY(), pdf.GetY()-oldY 109 pdf.SetY(oldY) 110 pdf.drawHeaderRight(rightHeaderContent, h) 111 pdf.SetY(y) 112 } 113 114 func (pdf CustomPdf) drawFooter() { 115 h := pdf.HTMLBasicNew() 116 pdf.SetFontSize(10) 117 _, _, mR, _ := pdf.GetMargins() 118 rondsWidth, rondsHeight := 70., 6. 119 120 pdf.SetY(-heightFooter) 121 pdf.SetFillColor(secondaryColor) 122 pdf.SetTextColor(0, 0, 0) 123 pdf.CellFormat(0, 17, "", "", "", true) 124 pdf.SetXY(-(rondsWidth + mR + 2), -heightFooter-(rondsHeight/2)) 125 pdf.insertImage("ronds.png", rondsWidth, rondsHeight) 126 pdf.SetY(-15) 127 pdf.SetLeftMargin(sideMargin + paddingFooter) 128 pdf.SetRightMargin(sideMargin + paddingFooter) 129 h.Write(4, pdf.Tr(rd.Asso.Title)) 130 pdf.Ln(-1) 131 pdf.SetFontSize(9) 132 h.Write(4, pdf.Tr(rd.Asso.Infos)) 133 pdf.Ln(-1) 134 pdf.SetFontSize(7.5) 135 h.Write(3, pdf.Tr(rd.Asso.Details)) 136 } 137 138 // ------------------------ Zone titre / destinataire ------------------------ 139 func formatAdresse(s string) []string { 140 var outs []string 141 for _, line := range strings.Split(s, "\n") { 142 trim := strings.TrimSpace(line) 143 if trim != "" { 144 outs = append(outs, trim) 145 } 146 } 147 return outs 148 } 149 150 func (pdf CustomPdf) drawBandeDestinataire(titre string, dest rd.Destinataire) { 151 titreWidth, titreHeight, spacingDate := 60., 10., 2. 152 y := pdf.GetY() + spacingHeader 153 pdf.SetY(y) 154 pdf.SetDrawColor(primaryColor) 155 pdf.SetLineWidth(0.8) 156 pdf.ClipRoundedRect(pdf.GetX(), y, titreWidth, titreHeight, 4, true) 157 pdf.CellFormat(titreWidth, titreHeight, pdf.Tr(titre), "", "CM", false) 158 pdf.ClipEnd() 159 pdf.SetY(y + titreHeight + spacingDate) 160 now := time.Now() 161 pdf.SetFont("Arial", "I", 10) 162 pdf.CellFormat(titreWidth, 5, fmt.Sprintf("Edition au %d/%d/%d", now.Day(), now.Month(), now.Year()), "", "CM", false) 163 164 pdf.SetFont("Arial", "", 13) 165 codePostalVille := strings.TrimSpace(dest.CodePostal.String()) + " " + strings.TrimSpace(dest.Ville.ToUpper()) 166 adresseLines := formatAdresse(dest.Adresse.String()) 167 lines := append(append([]string{dest.NomPrenom.String()}, adresseLines...), codePostalVille) 168 neededWidth, neededHeight := pdf.widthNeeded(lines), pdf.LineHeight()*float64(len(lines)) 169 x, paddingTop, paddingRight := pdf.AreaWidth()-neededWidth, 2., 3. 170 pdf.SetDrawColor(secondaryColor) 171 pdf.ClipRoundedRect(x, y, neededWidth+paddingRight, neededHeight+3, 5, true) 172 pdf.SetXY(x, y+paddingTop) 173 pdf.MultiCell(neededWidth, pdf.LineHeight(), pdf.Tr(strings.Join(lines, "\n")), "", "R", false) 174 pdf.ClipEnd() 175 pdf.Ln(spacingBandeDestinataire) 176 pdf.SetDrawColor(rgb{0, 0, 0}) 177 pdf.SetLineWidth(0.2) 178 }