Commit ec4067ed8ba730da221afb46f9dc988110e3c968

Authored by Marko Tikvić
1 parent 0487cafcd4
Exists in master

accessories

Showing 2 changed files with 43 additions and 16 deletions   Show diff stats
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "io" 5 "io"
6 "io/ioutil" 6 "io/ioutil"
7 "os" 7 "os"
8 "strings" 8 "strings"
9 ) 9 )
10 10
11 // ReadFileContent ... 11 // ReadFileContent ...
12 func ReadFileContent(path string) ([]byte, error) { 12 func ReadFileContent(path string) ([]byte, error) {
13 f, err := os.Open(path) 13 f, err := os.Open(path)
14 if err != nil { 14 if err != nil {
15 return nil, err 15 return nil, err
16 } 16 }
17 defer f.Close() 17 defer f.Close()
18 18
19 buf := &bytes.Buffer{} 19 buf := &bytes.Buffer{}
20 if _, err = io.Copy(buf, f); err != nil { 20 if _, err = io.Copy(buf, f); err != nil {
21 return nil, err 21 return nil, err
22 } 22 }
23 23
24 return buf.Bytes(), nil 24 return buf.Bytes(), nil
25 } 25 }
26 26
27 // ReadFileLines ... 27 // ReadFileLines ...
28 func ReadFileLines(path string) ([]string, error) { 28 func ReadFileLines(path string) ([]string, error) {
29 f, err := os.Open(path) 29 f, err := os.Open(path)
30 if err != nil { 30 if err != nil {
31 return nil, err 31 return nil, err
32 } 32 }
33 defer f.Close() 33 defer f.Close()
34 34
35 var s strings.Builder 35 var s strings.Builder
36 36
37 if _, err = io.Copy(&s, f); err != nil { 37 if _, err = io.Copy(&s, f); err != nil {
38 return nil, err 38 return nil, err
39 } 39 }
40 40
41 lines := strings.Split(s.String(), "\n") 41 lines := strings.Split(s.String(), "\n")
42 for i := range lines { 42 for i := range lines {
43 lines[i] = strings.TrimRight(lines[i], "\r\n") 43 lines[i] = strings.TrimRight(lines[i], "\r\n")
44 } 44 }
45 45
46 return lines, nil 46 return lines, nil
47 } 47 }
48 48
49 // LinesToFile ... 49 // LinesToFile ...
50 func LinesToFile(path string, lines []string) error { 50 func LinesToFile(path string, lines []string) error {
51 content := "" 51 content := ""
52 for _, l := range lines { 52 for _, l := range lines {
53 content += l + "\n" 53 content += l + "\n"
54 } 54 }
55 55
56 return ioutil.WriteFile(path, []byte(content), 0644) // drw-r--r-- 56 return ioutil.WriteFile(path, []byte(content), 0644) // drw-r--r--
57 } 57 }
58 58
59 // InsertLine ... 59 // InsertLine ...
60 func InsertLine(lines *[]string, pos int64, l string) { 60 func InsertLine(lines *[]string, pos int64, l string) {
61 tail := append([]string{l}, (*lines)[pos:]...) 61 tail := append([]string{l}, (*lines)[pos:]...)
62 62
63 *lines = append((*lines)[:pos], tail...) 63 *lines = append((*lines)[:pos], tail...)
64 } 64 }
65 65
66 func WriteFile(path string, content []byte) error { 66 func WriteFile(path string, content []byte) error {
67 return ioutil.WriteFile(path, content, 0644) // drw-r--r-- 67 return ioutil.WriteFile(path, content, 0644) // drw-r--r--
68 } 68 }
69
70 func ListDir(path string) (fnames []string, err error) {
71 finfo, err := ioutil.ReadDir(path)
72 if err != nil {
73 return nil, err
74 }
75
76 for _, f := range finfo {
77 fnames = append(fnames, f.Name())
78 }
79
80 return fnames, nil
81 }
82
83 func WorkingDir() string {
84 dir, _ := os.Getwd()
85 return dir
86 }
69 87
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) FCell(x, y float64, c FormatedCell) {
106 pdf.SetXY(x, y)
107 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
108 pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
109 }
110
105 func (pdf *Helper) Column(x, y float64, cells []FormatedCell) { 111 func (pdf *Helper) Column(x, y float64, cells []FormatedCell) {
106 pdf.SetXY(x, y) 112 pdf.SetXY(x, y)
107 for _, c := range cells { 113 for _, c := range cells {
108 pdf.SetFont(c.Font, c.FontStyle, c.FontSize) 114 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, "") 115 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, "") 116 //pdf.CellFormat(c.w, c.h, c.text, c.border, BELLOW, align, false, 0, "")
111 } 117 }
112 } 118 }
113 119
114 // NewLine ... 120 // NewLine ...
115 func (pdf *Helper) NewLine(h float64) { 121 func (pdf *Helper) NewLine(h float64) {
116 pdf.Ln(h) 122 pdf.Ln(h)
117 } 123 }
118 124
119 // WriteColumns ... 125 // WriteColumns ...
120 func (pdf *Helper) WriteColumns(align string, cols []PDFCell) { 126 func (pdf *Helper) WriteColumns(align string, cols []PDFCell) {
121 for _, c := range cols { 127 for _, c := range cols {
122 pdf.CellFormat(c.width, c.height, pdf.ToUTF8(c.data), "", CONTINUE, align, false, 0, "") 128 pdf.CellFormat(c.width, c.height, pdf.ToUTF8(c.data), "", CONTINUE, align, false, 0, "")
123 } 129 }
124 } 130 }
125 131
126 func (pdf *Helper) Row(x, y float64, cells []FormatedCell) { 132 func (pdf *Helper) Row(x, y float64, cells []FormatedCell) {
127 pdf.SetXY(x, y) 133 pdf.SetXY(x, y)
128 for _, c := range cells { 134 for _, c := range cells {
129 pdf.SetFont(c.Font, c.FontStyle, c.FontSize) 135 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, "") 136 pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "")
131 } 137 }
132 } 138 }
133 139
134 const threeDots = "\u2056\u2056\u2056" 140 const threeDots = "\u2056\u2056\u2056"
135 141
136 // WriteColumnsWithAlignment ... 142 // WriteColumnsWithAlignment ...
137 func (pdf *Helper) WriteColumnsWithAlignment(cols []PDFCellAligned) { 143 func (pdf *Helper) WriteColumnsWithAlignment(cols []PDFCellAligned) {
138 for _, c := range cols { 144 for _, c := range cols {
139 lines := pdf.SplitText(c.data, c.width) 145 lines := pdf.SplitText(c.data, c.width)
140 if len(lines) == 1 { 146 if len(lines) == 1 {
141 pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]), "", CONTINUE, c.alignment, false, 0, "") 147 pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]), "", CONTINUE, c.alignment, false, 0, "")
142 } else { 148 } else {
143 pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]+threeDots), "", CONTINUE, c.alignment, false, 0, "") 149 pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]+threeDots), "", CONTINUE, c.alignment, false, 0, "")
144 } 150 }
145 } 151 }
146 152
147 } 153 }
148 154
149 func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string { 155 func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string {
150 parts := pdf.Fpdf.SplitText(text, maxWidth) 156 parts := pdf.Fpdf.SplitText(text, maxWidth)
151 if len(parts) > 1 { 157 if len(parts) > 1 {
152 return parts[0] + limiter 158 return parts[0] + limiter
153 } 159 }
154 160
155 return text 161 return text
156 } 162 }
157 163
158 // InsertImage ... 164 // InsertImage ...
159 func (pdf *Helper) InsertImage(img string, x, y, w, h float64) { 165 func (pdf *Helper) InsertImage(img string, x, y, w, h float64) {
160 imgType := "" 166 imgType := ""
161 if parts := strings.Split(img, "."); len(parts) >= 2 { 167 if parts := strings.Split(img, "."); len(parts) >= 2 {
162 imgType = parts[len(parts)-1] 168 imgType = parts[len(parts)-1]
163 } 169 }
164 opt := gofpdf.ImageOptions{ 170 opt := gofpdf.ImageOptions{
165 ImageType: imgType, 171 ImageType: imgType,
166 ReadDpi: false, 172 ReadDpi: false,
167 AllowNegativePosition: false, 173 AllowNegativePosition: false,
168 } 174 }
169 autoBreak := false // if it's not false then you can't draw the image at an arbitrary height (y position) 175 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, "") 176 pdf.ImageOptions(img, x, y, w, h, autoBreak, opt, 0, "")
171 } 177 }
172 178
173 // PDFCell ... 179 // PDFCell ...
174 type PDFCell struct { 180 type PDFCell struct {
175 data string 181 data string
176 height, width float64 182 height, width float64
177 } 183 }
178 184
179 // PDFCellAligned ... 185 // PDFCellAligned ...
180 type PDFCellAligned struct { 186 type PDFCellAligned struct {
181 alignment string 187 alignment string
182 data string 188 data string
183 height, width float64 189 height, width float64
184 } 190 }
185 191
186 func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 { 192 func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 {
187 family, _, _, _ = pdf.setCorrectFontFamily(txt) 193 family, _, _, _ = pdf.setCorrectFontFamily(textEncoding(txt))
188 return pdf.Fpdf.TextLength(txt, family, style, size) 194 return pdf.Fpdf.TextLength(txt, family, style, size)
189 } 195 }
190 196
191 // ToUTF8 ... 197 func textEncoding(s string) string {
192 func (pdf *Helper) ToUTF8(s string) string {
193 encoding := latinEncoding 198 encoding := latinEncoding
194 runes := []rune(s) 199 runes := []rune(s)
195 for _, r := range runes { 200 for _, r := range runes {
196 if uint64(r) >= 0x0402 && uint64(r) <= 0x044f { 201 if uint64(r) >= 0x0402 && uint64(r) <= 0x044f {
197 encoding = cyrillicEncoding 202 encoding = cyrillicEncoding
198 break 203 break
199 } 204 }
200 } 205 }
206 return encoding
207 }
208
209 // ToUTF8 ...
210 func (pdf *Helper) ToUTF8(s string) string {
211 encoding := textEncoding(s)
201 pdf.setCorrectFontFamily(encoding) 212 pdf.setCorrectFontFamily(encoding)
202 translator, ok := pdf.translators[encoding] 213 translator, ok := pdf.translators[encoding]
203 if !ok { 214 if !ok {
204 return "" 215 return ""
205 } 216 }
206 return translator(s) 217 return translator(s)
207 } 218 }
208 219
209 func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) { 220 func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) {
210 family, style, ptSize, unitSize = pdf.GetFontInfo() 221 family, style, ptSize, unitSize = pdf.GetFontInfo()
211 if enc == cyrillicEncoding { 222 if enc == cyrillicEncoding {
212 if !strings.HasSuffix(family, "Cyrillic") { 223 if !strings.HasSuffix(family, "cyrillic") {
213 family += "Cyrillic" 224 family += "cyrillic"
214 } 225 }
215 } else { 226 } else {
216 if strings.HasSuffix(family, "Cyrillic") { 227 if strings.HasSuffix(family, "cyrillic") {
217 family = strings.TrimSuffix(family, "Cyrillic") 228 family = strings.TrimSuffix(family, "cyrillic")
218 } 229 }
219 } 230 }
220 pdf.SetFont(family, style, ptSize) 231 pdf.SetFont(family, style, ptSize)
221 return family, style, ptSize, unitSize 232 return family, style, ptSize, unitSize
222 } 233 }
223 234
224 func (pdf *Helper) PageHasSpace(requiredHeight float64) bool { 235 func (pdf *Helper) PageHasSpace(requiredHeight float64) bool {
225 _, h := pdf.GetPageSize() 236 _, h := pdf.GetPageSize()
226 _, _, _, bot := pdf.GetMargins() 237 _, _, _, bot := pdf.GetMargins()
227 return (h - bot - pdf.GetY()) > requiredHeight 238 return (h - bot - pdf.GetY()) > requiredHeight
228 } 239 }
229 240
230 func (pdf *Helper) imageCenterOffset(w, h float64) (x, y float64) { 241 func (pdf *Helper) imageCenterOffset(w, h float64) (x, y float64) {
231 pageW, pageH := pdf.GetPageSize() 242 pageW, pageH := pdf.GetPageSize()
232 x = pageW/2.0 - w/2.0 243 x = pageW/2.0 - w/2.0
233 y = pageH/2.0 - h/2.0 244 y = pageH/2.0 - h/2.0
234 return x, y 245 return x, y
235 } 246 }
236 247
237 // call before drawing the cell 248 // call before drawing the cell
238 func (pdf *Helper) drawCellMargins(cw, ch float64) { 249 func (pdf *Helper) drawCellMargins(cw, ch float64) {
239 x0, y0 := pdf.GetX(), pdf.GetY() 250 x0, y0 := pdf.GetX(), pdf.GetY()
240 pdf.DrawBox(x0, y0, cw, ch) 251 pdf.DrawBox(x0, y0, cw, ch)
241 } 252 }
242 253
243 // DrawBox ... 254 // DrawBox ...
244 func (pdf Helper) DrawBox(x0, y0, w, h float64) { 255 func (pdf Helper) DrawBox(x0, y0, w, h float64) {
245 pdf.Line(x0, y0, x0+w, y0) 256 pdf.Line(x0, y0, x0+w, y0)
246 pdf.Line(x0+w, y0, x0+w, y0+h) 257 pdf.Line(x0+w, y0, x0+w, y0+h)
247 pdf.Line(x0+w, y0+h, x0, y0+h) 258 pdf.Line(x0+w, y0+h, x0, y0+h)
248 pdf.Line(x0, y0+h, x0, y0) 259 pdf.Line(x0, y0+h, x0, y0)
249 } 260 }
250 261
251 // Strana %d/{TotalPages} 262 // Strana %d/{TotalPages}
252 func (pdf *Helper) InsertPageNumber(x, y float64, format string) { 263 func (pdf *Helper) InsertPageNumber(x, y float64, format string) {
253 num := fmt.Sprintf(format, pdf.PageNo()) 264 num := fmt.Sprintf(format, pdf.PageNo())
254 pdf.Column(x, y, []FormatedCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}}) 265 pdf.Column(x, y, []FormatedCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}})
255 } 266 }
256 267
257 func (pdf *Helper) WriteSuperscript( 268 func (pdf *Helper) SuperscriptText(x, y, cw, ch float64, text, script string) {
258 txt, script string, 269 family, style, size, sizeU := pdf.setCorrectFontFamily(textEncoding(text))
259 x, y float64, 270
260 fontFamily, fontStyle string, 271 pdf.FCell(x, y, FormatedCell{cw, ch, text, family, style, size, NOBORDER, LEFT})
261 fontSize float64) {
262 272
263 scriptOffsetX := x + pdf.TextLength(txt, fontFamily, fontStyle, fontSize) 273 sx := x + pdf.TextLength(text, family, style, size)
264 scriptOffsetY := y - fontSize*0.3 274 sy := y - sizeU*0.2
265 pdf.Column(x, y, []FormatedCell{{5.0, 5.0, txt, fontFamily, fontStyle, 6, NOBORDER, LEFT}}) 275 pdf.FCell(sx, sy, FormatedCell{cw, ch, script, family, style, size - 2, NOBORDER, LEFT})