Commit 0487cafcd4457972f2cc185ae23f604b4c75ed32

Authored by Marko Tikvić
1 parent bf3ea2f8ef
Exists in master

superscript

Showing 1 changed file with 12 additions and 0 deletions   Show diff stats
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