Commit 0487cafcd4457972f2cc185ae23f604b4c75ed32
1 parent
bf3ea2f8ef
Exists in
master
superscript
Showing
1 changed file
with
12 additions
and
0 deletions
Show diff stats
pdfhelper/pdf.go
1 | package pdfhelper | 1 | package pdfhelper |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "strings" | 5 | "strings" |
6 | 6 | ||
7 | "git.to-net.rs/marko.tikvic/gofpdf" | 7 | "git.to-net.rs/marko.tikvic/gofpdf" |
8 | ) | 8 | ) |
9 | 9 | ||
10 | // Block ... | 10 | // Block ... |
11 | const ( | 11 | const ( |
12 | CENTER = "C" | 12 | CENTER = "C" |
13 | LEFT = "L" | 13 | LEFT = "L" |
14 | RIGHT = "R" | 14 | RIGHT = "R" |
15 | TOP = "T" | 15 | TOP = "T" |
16 | BOTTOM = "B" | 16 | BOTTOM = "B" |
17 | FULL = "1" | 17 | FULL = "1" |
18 | NOBORDER = "" | 18 | NOBORDER = "" |
19 | ) | 19 | ) |
20 | 20 | ||
21 | const ( | 21 | const ( |
22 | CONTINUE = 0 | 22 | CONTINUE = 0 |
23 | NEWLINE = 1 | 23 | NEWLINE = 1 |
24 | BELLOW = 2 | 24 | BELLOW = 2 |
25 | ) | 25 | ) |
26 | 26 | ||
27 | const ( | 27 | const ( |
28 | cyrillicEncoding = "cp1251" | 28 | cyrillicEncoding = "cp1251" |
29 | latinEncoding = "cp1250" | 29 | latinEncoding = "cp1250" |
30 | ) | 30 | ) |
31 | 31 | ||
32 | // Helper ... | 32 | // Helper ... |
33 | type Helper struct { | 33 | type Helper struct { |
34 | *gofpdf.Fpdf | 34 | *gofpdf.Fpdf |
35 | translators map[string]func(string) string | 35 | translators map[string]func(string) string |
36 | } | 36 | } |
37 | 37 | ||
38 | // New ... | 38 | // New ... |
39 | func New(ori, unit, size string) *Helper { | 39 | func New(ori, unit, size string) *Helper { |
40 | helper := &Helper{ | 40 | helper := &Helper{ |
41 | Fpdf: gofpdf.New(ori, unit, size, ""), | 41 | Fpdf: gofpdf.New(ori, unit, size, ""), |
42 | } | 42 | } |
43 | 43 | ||
44 | return helper | 44 | return helper |
45 | } | 45 | } |
46 | 46 | ||
47 | func (pdf *Helper) LoadTranslators() { | 47 | func (pdf *Helper) LoadTranslators() { |
48 | pdf.translators = make(map[string]func(string) string) | 48 | pdf.translators = make(map[string]func(string) string) |
49 | pdf.translators[latinEncoding] = pdf.UnicodeTranslatorFromDescriptor(latinEncoding) | 49 | pdf.translators[latinEncoding] = pdf.UnicodeTranslatorFromDescriptor(latinEncoding) |
50 | pdf.translators[cyrillicEncoding] = pdf.UnicodeTranslatorFromDescriptor(cyrillicEncoding) | 50 | pdf.translators[cyrillicEncoding] = pdf.UnicodeTranslatorFromDescriptor(cyrillicEncoding) |
51 | } | 51 | } |
52 | 52 | ||
53 | // InsertTab ... | 53 | // InsertTab ... |
54 | func (pdf *Helper) InsertTab(count int, w, h float64) { | 54 | func (pdf *Helper) InsertTab(count int, w, h float64) { |
55 | for i := 0; i < count; i++ { | 55 | for i := 0; i < count; i++ { |
56 | pdf.Cell(w, h, "") | 56 | pdf.Cell(w, h, "") |
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | // CellWithBox ... | 60 | // CellWithBox ... |
61 | func (pdf *Helper) CellWithBox(w, h float64, text, align string) { | 61 | func (pdf *Helper) CellWithBox(w, h float64, text, align string) { |
62 | //pdf.drawCellMargins(w, h) | 62 | //pdf.drawCellMargins(w, h) |
63 | //pdf.Cell(w, h, text) | 63 | //pdf.Cell(w, h, text) |
64 | pdf.CellFormat(w, h, pdf.ToUTF8(text), FULL, CONTINUE, align, false, 0, "") | 64 | pdf.CellFormat(w, h, pdf.ToUTF8(text), FULL, CONTINUE, align, false, 0, "") |
65 | } | 65 | } |
66 | 66 | ||
67 | func (pdf *Helper) CellWithMargins(w, h float64, text, align string, index, of int) { | 67 | func (pdf *Helper) CellWithMargins(w, h float64, text, align string, index, of int) { |
68 | len := of - 1 | 68 | len := of - 1 |
69 | border := "" | 69 | border := "" |
70 | 70 | ||
71 | // if top cell | 71 | // if top cell |
72 | if index == 0 { | 72 | if index == 0 { |
73 | border += "T" | 73 | border += "T" |
74 | } | 74 | } |
75 | 75 | ||
76 | border += "LR" // always draw these | 76 | border += "LR" // always draw these |
77 | 77 | ||
78 | // if bottom cell | 78 | // if bottom cell |
79 | if index == len { | 79 | if index == len { |
80 | border += "B" | 80 | border += "B" |
81 | } | 81 | } |
82 | 82 | ||
83 | pdf.CellFormat(w, h, pdf.ToUTF8(text), border, CONTINUE, align, false, 0, "") | 83 | pdf.CellFormat(w, h, pdf.ToUTF8(text), border, CONTINUE, align, false, 0, "") |
84 | } | 84 | } |
85 | 85 | ||
86 | // MultiRowCellWithBox ... | 86 | // MultiRowCellWithBox ... |
87 | func (pdf *Helper) MultiRowCellWithBox(w, h float64, text []string, align string) { | 87 | func (pdf *Helper) MultiRowCellWithBox(w, h float64, text []string, align string) { |
88 | pdf.drawCellMargins(w, h*float64(len(text))) | 88 | pdf.drawCellMargins(w, h*float64(len(text))) |
89 | for i := range text { | 89 | for i := range text { |
90 | pdf.CellFormat(w, h, pdf.ToUTF8(text[i]), "", BELLOW, align, false, 0, "") | 90 | pdf.CellFormat(w, h, pdf.ToUTF8(text[i]), "", BELLOW, align, false, 0, "") |
91 | } | 91 | } |
92 | } | 92 | } |
93 | 93 | ||
94 | // CellFormat(w, h, text, borders, newLine, fill) | 94 | // CellFormat(w, h, text, borders, newLine, fill) |
95 | 95 | ||
96 | type FormatedCell struct { | 96 | type FormatedCell struct { |
97 | W, H float64 | 97 | W, H float64 |
98 | Text string | 98 | Text string |
99 | Font, FontStyle string | 99 | Font, FontStyle string |
100 | FontSize float64 | 100 | FontSize float64 |
101 | Border string | 101 | Border string |
102 | Alignment string | 102 | Alignment string |
103 | } | 103 | } |
104 | 104 | ||
105 | func (pdf *Helper) Column(x, y float64, cells []FormatedCell) { | 105 | func (pdf *Helper) Column(x, y float64, cells []FormatedCell) { |
106 | pdf.SetXY(x, y) | 106 | pdf.SetXY(x, y) |
107 | for _, c := range cells { | 107 | for _, c := range cells { |
108 | pdf.SetFont(c.Font, c.FontStyle, c.FontSize) | 108 | pdf.SetFont(c.Font, c.FontStyle, c.FontSize) |
109 | pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "") | 109 | pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "") |
110 | //pdf.CellFormat(c.w, c.h, c.text, c.border, BELLOW, align, false, 0, "") | 110 | //pdf.CellFormat(c.w, c.h, c.text, c.border, BELLOW, align, false, 0, "") |
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | // NewLine ... | 114 | // NewLine ... |
115 | func (pdf *Helper) NewLine(h float64) { | 115 | func (pdf *Helper) NewLine(h float64) { |
116 | pdf.Ln(h) | 116 | pdf.Ln(h) |
117 | } | 117 | } |
118 | 118 | ||
119 | // WriteColumns ... | 119 | // WriteColumns ... |
120 | func (pdf *Helper) WriteColumns(align string, cols []PDFCell) { | 120 | func (pdf *Helper) WriteColumns(align string, cols []PDFCell) { |
121 | for _, c := range cols { | 121 | for _, c := range cols { |
122 | pdf.CellFormat(c.width, c.height, pdf.ToUTF8(c.data), "", CONTINUE, align, false, 0, "") | 122 | pdf.CellFormat(c.width, c.height, pdf.ToUTF8(c.data), "", CONTINUE, align, false, 0, "") |
123 | } | 123 | } |
124 | } | 124 | } |
125 | 125 | ||
126 | func (pdf *Helper) Row(x, y float64, cells []FormatedCell) { | 126 | func (pdf *Helper) Row(x, y float64, cells []FormatedCell) { |
127 | pdf.SetXY(x, y) | 127 | pdf.SetXY(x, y) |
128 | for _, c := range cells { | 128 | for _, c := range cells { |
129 | pdf.SetFont(c.Font, c.FontStyle, c.FontSize) | 129 | pdf.SetFont(c.Font, c.FontStyle, c.FontSize) |
130 | pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "") | 130 | pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "") |
131 | } | 131 | } |
132 | } | 132 | } |
133 | 133 | ||
134 | const threeDots = "\u2056\u2056\u2056" | 134 | const threeDots = "\u2056\u2056\u2056" |
135 | 135 | ||
136 | // WriteColumnsWithAlignment ... | 136 | // WriteColumnsWithAlignment ... |
137 | func (pdf *Helper) WriteColumnsWithAlignment(cols []PDFCellAligned) { | 137 | func (pdf *Helper) WriteColumnsWithAlignment(cols []PDFCellAligned) { |
138 | for _, c := range cols { | 138 | for _, c := range cols { |
139 | lines := pdf.SplitText(c.data, c.width) | 139 | lines := pdf.SplitText(c.data, c.width) |
140 | if len(lines) == 1 { | 140 | if len(lines) == 1 { |
141 | pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]), "", CONTINUE, c.alignment, false, 0, "") | 141 | pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]), "", CONTINUE, c.alignment, false, 0, "") |
142 | } else { | 142 | } else { |
143 | pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]+threeDots), "", CONTINUE, c.alignment, false, 0, "") | 143 | pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]+threeDots), "", CONTINUE, c.alignment, false, 0, "") |
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | } | 147 | } |
148 | 148 | ||
149 | func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string { | 149 | func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string { |
150 | parts := pdf.Fpdf.SplitText(text, maxWidth) | 150 | parts := pdf.Fpdf.SplitText(text, maxWidth) |
151 | if len(parts) > 1 { | 151 | if len(parts) > 1 { |
152 | return parts[0] + limiter | 152 | return parts[0] + limiter |
153 | } | 153 | } |
154 | 154 | ||
155 | return text | 155 | return text |
156 | } | 156 | } |
157 | 157 | ||
158 | // InsertImage ... | 158 | // InsertImage ... |
159 | func (pdf *Helper) InsertImage(img string, x, y, w, h float64) { | 159 | func (pdf *Helper) InsertImage(img string, x, y, w, h float64) { |
160 | imgType := "" | 160 | imgType := "" |
161 | if parts := strings.Split(img, "."); len(parts) >= 2 { | 161 | if parts := strings.Split(img, "."); len(parts) >= 2 { |
162 | imgType = parts[len(parts)-1] | 162 | imgType = parts[len(parts)-1] |
163 | } | 163 | } |
164 | opt := gofpdf.ImageOptions{ | 164 | opt := gofpdf.ImageOptions{ |
165 | ImageType: imgType, | 165 | ImageType: imgType, |
166 | ReadDpi: false, | 166 | ReadDpi: false, |
167 | AllowNegativePosition: false, | 167 | AllowNegativePosition: false, |
168 | } | 168 | } |
169 | autoBreak := false // if it's not false then you can't draw the image at an arbitrary height (y position) | 169 | autoBreak := false // if it's not false then you can't draw the image at an arbitrary height (y position) |
170 | pdf.ImageOptions(img, x, y, w, h, autoBreak, opt, 0, "") | 170 | pdf.ImageOptions(img, x, y, w, h, autoBreak, opt, 0, "") |
171 | } | 171 | } |
172 | 172 | ||
173 | // PDFCell ... | 173 | // PDFCell ... |
174 | type PDFCell struct { | 174 | type PDFCell struct { |
175 | data string | 175 | data string |
176 | height, width float64 | 176 | height, width float64 |
177 | } | 177 | } |
178 | 178 | ||
179 | // PDFCellAligned ... | 179 | // PDFCellAligned ... |
180 | type PDFCellAligned struct { | 180 | type PDFCellAligned struct { |
181 | alignment string | 181 | alignment string |
182 | data string | 182 | data string |
183 | height, width float64 | 183 | height, width float64 |
184 | } | 184 | } |
185 | 185 | ||
186 | func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 { | 186 | func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 { |
187 | family, _, _, _ = pdf.setCorrectFontFamily(txt) | 187 | family, _, _, _ = pdf.setCorrectFontFamily(txt) |
188 | return pdf.Fpdf.TextLength(txt, family, style, size) | 188 | return pdf.Fpdf.TextLength(txt, family, style, size) |
189 | } | 189 | } |
190 | 190 | ||
191 | // ToUTF8 ... | 191 | // ToUTF8 ... |
192 | func (pdf *Helper) ToUTF8(s string) string { | 192 | func (pdf *Helper) ToUTF8(s string) string { |
193 | encoding := latinEncoding | 193 | encoding := latinEncoding |
194 | runes := []rune(s) | 194 | runes := []rune(s) |
195 | for _, r := range runes { | 195 | for _, r := range runes { |
196 | if uint64(r) >= 0x0402 && uint64(r) <= 0x044f { | 196 | if uint64(r) >= 0x0402 && uint64(r) <= 0x044f { |
197 | encoding = cyrillicEncoding | 197 | encoding = cyrillicEncoding |
198 | break | 198 | break |
199 | } | 199 | } |
200 | } | 200 | } |
201 | pdf.setCorrectFontFamily(encoding) | 201 | pdf.setCorrectFontFamily(encoding) |
202 | translator, ok := pdf.translators[encoding] | 202 | translator, ok := pdf.translators[encoding] |
203 | if !ok { | 203 | if !ok { |
204 | return "" | 204 | return "" |
205 | } | 205 | } |
206 | return translator(s) | 206 | return translator(s) |
207 | } | 207 | } |
208 | 208 | ||
209 | func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) { | 209 | func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) { |
210 | family, style, ptSize, unitSize = pdf.GetFontInfo() | 210 | family, style, ptSize, unitSize = pdf.GetFontInfo() |
211 | if enc == cyrillicEncoding { | 211 | if enc == cyrillicEncoding { |
212 | if !strings.HasSuffix(family, "Cyrillic") { | 212 | if !strings.HasSuffix(family, "Cyrillic") { |
213 | family += "Cyrillic" | 213 | family += "Cyrillic" |
214 | } | 214 | } |
215 | } else { | 215 | } else { |
216 | if strings.HasSuffix(family, "Cyrillic") { | 216 | if strings.HasSuffix(family, "Cyrillic") { |
217 | family = strings.TrimSuffix(family, "Cyrillic") | 217 | family = strings.TrimSuffix(family, "Cyrillic") |
218 | } | 218 | } |
219 | } | 219 | } |
220 | pdf.SetFont(family, style, ptSize) | 220 | pdf.SetFont(family, style, ptSize) |
221 | return family, style, ptSize, unitSize | 221 | return family, style, ptSize, unitSize |
222 | } | 222 | } |
223 | 223 | ||
224 | func (pdf *Helper) PageHasSpace(requiredHeight float64) bool { | 224 | func (pdf *Helper) PageHasSpace(requiredHeight float64) bool { |
225 | _, h := pdf.GetPageSize() | 225 | _, h := pdf.GetPageSize() |
226 | _, _, _, bot := pdf.GetMargins() | 226 | _, _, _, bot := pdf.GetMargins() |
227 | return (h - bot - pdf.GetY()) > requiredHeight | 227 | return (h - bot - pdf.GetY()) > requiredHeight |
228 | } | 228 | } |
229 | 229 | ||
230 | func (pdf *Helper) imageCenterOffset(w, h float64) (x, y float64) { | 230 | func (pdf *Helper) imageCenterOffset(w, h float64) (x, y float64) { |
231 | pageW, pageH := pdf.GetPageSize() | 231 | pageW, pageH := pdf.GetPageSize() |
232 | x = pageW/2.0 - w/2.0 | 232 | x = pageW/2.0 - w/2.0 |
233 | y = pageH/2.0 - h/2.0 | 233 | y = pageH/2.0 - h/2.0 |
234 | return x, y | 234 | return x, y |
235 | } | 235 | } |
236 | 236 | ||
237 | // call before drawing the cell | 237 | // call before drawing the cell |
238 | func (pdf *Helper) drawCellMargins(cw, ch float64) { | 238 | func (pdf *Helper) drawCellMargins(cw, ch float64) { |
239 | x0, y0 := pdf.GetX(), pdf.GetY() | 239 | x0, y0 := pdf.GetX(), pdf.GetY() |
240 | pdf.DrawBox(x0, y0, cw, ch) | 240 | pdf.DrawBox(x0, y0, cw, ch) |
241 | } | 241 | } |
242 | 242 | ||
243 | // DrawBox ... | 243 | // DrawBox ... |
244 | func (pdf Helper) DrawBox(x0, y0, w, h float64) { | 244 | func (pdf Helper) DrawBox(x0, y0, w, h float64) { |
245 | pdf.Line(x0, y0, x0+w, y0) | 245 | pdf.Line(x0, y0, x0+w, y0) |
246 | pdf.Line(x0+w, y0, x0+w, y0+h) | 246 | pdf.Line(x0+w, y0, x0+w, y0+h) |
247 | pdf.Line(x0+w, y0+h, x0, y0+h) | 247 | pdf.Line(x0+w, y0+h, x0, y0+h) |
248 | pdf.Line(x0, y0+h, x0, y0) | 248 | pdf.Line(x0, y0+h, x0, y0) |
249 | } | 249 | } |
250 | 250 | ||
251 | // Strana %d/{TotalPages} | 251 | // Strana %d/{TotalPages} |
252 | func (pdf *Helper) InsertPageNumber(x, y float64, format string) { | 252 | func (pdf *Helper) InsertPageNumber(x, y float64, format string) { |
253 | num := fmt.Sprintf(format, pdf.PageNo()) | 253 | num := fmt.Sprintf(format, pdf.PageNo()) |
254 | pdf.Column(x, y, []FormatedCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}}) | 254 | pdf.Column(x, y, []FormatedCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}}) |
255 | } | 255 | } |
256 | |||
257 | func (pdf *Helper) WriteSuperscript( | ||
258 | txt, script string, | ||
259 | x, y float64, | ||
260 | fontFamily, fontStyle string, | ||
261 | fontSize float64) { | ||
262 | |||
263 | scriptOffsetX := x + pdf.TextLength(txt, fontFamily, fontStyle, fontSize) | ||
264 | scriptOffsetY := y - fontSize*0.3 | ||
265 | pdf.Column(x, y, []FormatedCell{{5.0, 5.0, txt, fontFamily, fontStyle, 6, NOBORDER, LEFT}}) | ||
266 | pdf.Column(scripttxtOffset, scriptOffsetY, []FormatedCell{{5.0, 5.0, script, fontFamily, fontStyle, 6, NOBORDER, LEFT}}) | ||
267 | } | ||
256 | 268 |