Commit 1b51eed04dcd7aaa90727f3586530ec57f1d2843

Authored by Marko Tikvić
1 parent b80ee4b2bc
Exists in master

pdf helper

... ... @@ -2,6 +2,7 @@ package webutility
2 2  
3 3 import (
4 4 "fmt"
  5 + "strings"
5 6 "time"
6 7 )
7 8  
... ... @@ -23,6 +24,11 @@ const (
23 24 DDMMYYYY_HHMMSS_dt = "02.01.2006. 15:04:05"
24 25 )
25 26  
  27 +var (
  28 + regularYear = [12]int64{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
  29 + leapYear = [12]int64{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
  30 +)
  31 +
26 32 func Systime() int64 {
27 33 return time.Now().Unix()
28 34 }
... ... @@ -39,3 +45,26 @@ func DateToEpoch(date, format string) int64 {
39 45 func EpochToDate(e int64, format string) string {
40 46 return time.Unix(e, 0).Format(format)
41 47 }
  48 +
  49 +func EpochToDayMonthYear(timestamp int64) (d, m, y int64) {
  50 + datestring := EpochToDate(timestamp, DDMMYYYY_sl)
  51 + parts := strings.Split(datestring, "/")
  52 + d = StringToInt64(parts[0])
  53 + m = StringToInt64(parts[1])
  54 + y = StringToInt64(parts[2])
  55 + return d, m, y
  56 +}
  57 +
  58 +func DaysInMonth(year, month int64) int64 {
  59 + if month < 1 || month > 12 {
  60 + return 0
  61 + }
  62 + if IsLeapYear(year) {
  63 + return leapYear[month-1]
  64 + }
  65 + return regularYear[month-1]
  66 +}
  67 +
  68 +func IsLeapYear(year int64) bool {
  69 + return year%4 == 0 && !((year%100 == 0) && (year%400 != 0))
  70 +}
... ...
... ... @@ -57,3 +57,10 @@ func BFtoFloat(f *big.Float) float64 {
57 57 func Float64ToString(f float64) string {
58 58 return fmt.Sprintf("%.2f", f)
59 59 }
  60 +
  61 +func Float64PtrToString(f *float64) string {
  62 + if f == nil {
  63 + return ""
  64 + }
  65 + return fmt.Sprintf("%.2f", *f)
  66 +}
... ...
1 1 package webutility
2 2  
3 3 import (
4   - "crypto/rand"
5 4 "fmt"
  5 + "math/rand"
6 6 )
7 7  
  8 +func SeedGUID(seed int64) {
  9 + rand.Seed(seed)
  10 +}
  11 +
8 12 // GUID ...
9 13 func GUID() (string, error) {
10 14 b := make([]byte, 16)
... ... @@ -15,3 +19,8 @@ func GUID() (string, error) {
15 19 id := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
16 20 return id, nil
17 21 }
  22 +
  23 +func NewGUID() string {
  24 + id, _ := GUID()
  25 + return id
  26 +}
... ...
... ... @@ -168,6 +168,6 @@ func GetHeader(r *http.Request, key string) string {
168 168 return r.Header.Get(key)
169 169 }
170 170  
171   -func GetClientAgentUTCOffset(req *http.Request) int64 {
  171 +func ClientUTCOffset(req *http.Request) int64 {
172 172 return StringToInt64(GetHeader(req, "X-Timezone-Offset"))
173 173 }
... ...
... ... @@ -25,6 +25,14 @@ func Int64ToString(i int64) string {
25 25 return fmt.Sprintf("%d", i)
26 26 }
27 27  
  28 +// Int64PtrToString ...
  29 +func Int64PtrToString(i *int64) string {
  30 + if i == nil {
  31 + return ""
  32 + }
  33 + return fmt.Sprintf("%d", *i)
  34 +}
  35 +
28 36 // BoolToInt64 ...
29 37 func BoolToInt64(b bool) int64 {
30 38 if b {
... ... @@ -39,6 +47,7 @@ func Int64ToBool(i int64) bool {
39 47 }
40 48  
41 49 func MaxInt(vars ...int) (max int) {
  50 + max = vars[0]
42 51 for _, v := range vars {
43 52 if v > max {
44 53 max = v
... ... @@ -46,3 +55,13 @@ func MaxInt(vars ...int) (max int) {
46 55 }
47 56 return max
48 57 }
  58 +
  59 +func MinInt64(vars ...int64) (min int64) {
  60 + min = vars[0]
  61 + for _, v := range vars {
  62 + if v < min {
  63 + min = v
  64 + }
  65 + }
  66 + return min
  67 +}
... ...
... ... @@ -139,6 +139,21 @@ func (ni *NullInt64) Value() (driver.Value, error) {
139 139 return ni.Int64, nil
140 140 }
141 141  
  142 +func (ni *NullInt64) Val() int64 {
  143 + return ni.Int64
  144 +}
  145 +
  146 +// Add
  147 +func (ni *NullInt64) Add(i NullInt64) {
  148 + ni.Valid = true
  149 + ni.Int64 += i.Int64
  150 +}
  151 +
  152 +func (ni *NullInt64) Set(i int64) {
  153 + ni.Valid = true
  154 + ni.Int64 = i
  155 +}
  156 +
142 157 // MarshalJSON ...
143 158 func (ni NullInt64) MarshalJSON() ([]byte, error) {
144 159 if ni.Valid {
... ... @@ -197,6 +212,22 @@ func (nf *NullFloat64) Value() (driver.Value, error) {
197 212 return nf.Float64, nil
198 213 }
199 214  
  215 +// Val ...
  216 +func (nf *NullFloat64) Val() float64 {
  217 + return nf.Float64
  218 +}
  219 +
  220 +// Add ...
  221 +func (nf *NullFloat64) Add(f NullFloat64) {
  222 + nf.Valid = true
  223 + nf.Float64 += f.Float64
  224 +}
  225 +
  226 +func (nf *NullFloat64) Set(f float64) {
  227 + nf.Valid = true
  228 + nf.Float64 = f
  229 +}
  230 +
200 231 // MarshalJSON ...
201 232 func (nf NullFloat64) MarshalJSON() ([]byte, error) {
202 233 if nf.Valid {
... ...
... ... @@ -0,0 +1,255 @@
  1 +package pdfhelper
  2 +
  3 +import (
  4 + "fmt"
  5 + "strings"
  6 +
  7 + "git.to-net.rs/marko.tikvic/gofpdf"
  8 +)
  9 +
  10 +// Block ...
  11 +const (
  12 + CENTER = "C"
  13 + LEFT = "L"
  14 + RIGHT = "R"
  15 + TOP = "T"
  16 + BOTTOM = "B"
  17 + FULL = "1"
  18 + NOBORDER = ""
  19 +)
  20 +
  21 +const (
  22 + CONTINUE = 0
  23 + NEWLINE = 1
  24 + BELLOW = 2
  25 +)
  26 +
  27 +const (
  28 + cyrillicEncoding = "cp1251"
  29 + latinEncoding = "cp1250"
  30 +)
  31 +
  32 +// Helper ...
  33 +type Helper struct {
  34 + *gofpdf.Fpdf
  35 + translators map[string]func(string) string
  36 +}
  37 +
  38 +// New ...
  39 +func New(ori, unit, size string) *Helper {
  40 + helper := &Helper{
  41 + Fpdf: gofpdf.New(ori, unit, size, ""),
  42 + }
  43 +
  44 + return helper
  45 +}
  46 +
  47 +func (pdf *Helper) LoadTranslators() {
  48 + pdf.translators = make(map[string]func(string) string)
  49 + pdf.translators[latinEncoding] = pdf.UnicodeTranslatorFromDescriptor(latinEncoding)
  50 + pdf.translators[cyrillicEncoding] = pdf.UnicodeTranslatorFromDescriptor(cyrillicEncoding)
  51 +}
  52 +
  53 +// InsertTab ...
  54 +func (pdf *Helper) InsertTab(count int, w, h float64) {
  55 + for i := 0; i < count; i++ {
  56 + pdf.Cell(w, h, "")
  57 + }
  58 +}
  59 +
  60 +// CellWithBox ...
  61 +func (pdf *Helper) CellWithBox(w, h float64, text, align string) {
  62 + //pdf.drawCellMargins(w, h)
  63 + //pdf.Cell(w, h, text)
  64 + pdf.CellFormat(w, h, pdf.ToUTF8(text), FULL, CONTINUE, align, false, 0, "")
  65 +}
  66 +
  67 +func (pdf *Helper) CellWithMargins(w, h float64, text, align string, index, of int) {
  68 + len := of - 1
  69 + border := ""
  70 +
  71 + // if top cell
  72 + if index == 0 {
  73 + border += "T"
  74 + }
  75 +
  76 + border += "LR" // always draw these
  77 +
  78 + // if bottom cell
  79 + if index == len {
  80 + border += "B"
  81 + }
  82 +
  83 + pdf.CellFormat(w, h, pdf.ToUTF8(text), border, CONTINUE, align, false, 0, "")
  84 +}
  85 +
  86 +// MultiRowCellWithBox ...
  87 +func (pdf *Helper) MultiRowCellWithBox(w, h float64, text []string, align string) {
  88 + pdf.drawCellMargins(w, h*float64(len(text)))
  89 + for i := range text {
  90 + pdf.CellFormat(w, h, pdf.ToUTF8(text[i]), "", BELLOW, align, false, 0, "")
  91 + }
  92 +}
  93 +
  94 +// CellFormat(w, h, text, borders, newLine, fill)
  95 +
  96 +type FormatedCell struct {
  97 + W, H float64
  98 + Text string
  99 + Font, FontStyle string
  100 + FontSize float64
  101 + Border string
  102 + Alignment string
  103 +}
  104 +
  105 +func (pdf *Helper) Column(x, y float64, cells []FormatedCell) {
  106 + pdf.SetXY(x, y)
  107 + for _, c := range cells {
  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, "")
  110 + //pdf.CellFormat(c.w, c.h, c.text, c.border, BELLOW, align, false, 0, "")
  111 + }
  112 +}
  113 +
  114 +// NewLine ...
  115 +func (pdf *Helper) NewLine(h float64) {
  116 + pdf.Ln(h)
  117 +}
  118 +
  119 +// WriteColumns ...
  120 +func (pdf *Helper) WriteColumns(align string, cols []PDFCell) {
  121 + for _, c := range cols {
  122 + pdf.CellFormat(c.width, c.height, pdf.ToUTF8(c.data), "", CONTINUE, align, false, 0, "")
  123 + }
  124 +}
  125 +
  126 +func (pdf *Helper) Row(x, y float64, cells []FormatedCell) {
  127 + pdf.SetXY(x, y)
  128 + for _, c := range cells {
  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, "")
  131 + }
  132 +}
  133 +
  134 +const threeDots = "\u2056\u2056\u2056"
  135 +
  136 +// WriteColumnsWithAlignment ...
  137 +func (pdf *Helper) WriteColumnsWithAlignment(cols []PDFCellAligned) {
  138 + for _, c := range cols {
  139 + lines := pdf.SplitText(c.data, c.width)
  140 + if len(lines) == 1 {
  141 + pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]), "", CONTINUE, c.alignment, false, 0, "")
  142 + } else {
  143 + pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]+threeDots), "", CONTINUE, c.alignment, false, 0, "")
  144 + }
  145 + }
  146 +
  147 +}
  148 +
  149 +func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string {
  150 + parts := pdf.Fpdf.SplitText(text, maxWidth)
  151 + if len(parts) > 1 {
  152 + return parts[0] + limiter
  153 + }
  154 +
  155 + return text
  156 +}
  157 +
  158 +// InsertImage ...
  159 +func (pdf *Helper) InsertImage(img string, x, y, w, h float64) {
  160 + imgType := ""
  161 + if parts := strings.Split(img, "."); len(parts) >= 2 {
  162 + imgType = parts[len(parts)-1]
  163 + }
  164 + opt := gofpdf.ImageOptions{
  165 + ImageType: imgType,
  166 + ReadDpi: false,
  167 + AllowNegativePosition: false,
  168 + }
  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, "")
  171 +}
  172 +
  173 +// PDFCell ...
  174 +type PDFCell struct {
  175 + data string
  176 + height, width float64
  177 +}
  178 +
  179 +// PDFCellAligned ...
  180 +type PDFCellAligned struct {
  181 + alignment string
  182 + data string
  183 + height, width float64
  184 +}
  185 +
  186 +func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 {
  187 + family, _, _, _ = pdf.setCorrectFontFamily(txt)
  188 + return pdf.Fpdf.TextLength(txt, family, style, size)
  189 +}
  190 +
  191 +// ToUTF8 ...
  192 +func (pdf *Helper) ToUTF8(s string) string {
  193 + encoding := latinEncoding
  194 + runes := []rune(s)
  195 + for _, r := range runes {
  196 + if uint64(r) >= 0x0402 && uint64(r) <= 0x044f {
  197 + encoding = cyrillicEncoding
  198 + break
  199 + }
  200 + }
  201 + pdf.setCorrectFontFamily(encoding)
  202 + translator, ok := pdf.translators[encoding]
  203 + if !ok {
  204 + return ""
  205 + }
  206 + return translator(s)
  207 +}
  208 +
  209 +func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) {
  210 + family, style, ptSize, unitSize = pdf.GetFontInfo()
  211 + if enc == cyrillicEncoding {
  212 + if !strings.HasSuffix(family, "Cyrillic") {
  213 + family += "Cyrillic"
  214 + }
  215 + } else {
  216 + if strings.HasSuffix(family, "Cyrillic") {
  217 + family = strings.TrimSuffix(family, "Cyrillic")
  218 + }
  219 + }
  220 + pdf.SetFont(family, style, ptSize)
  221 + return family, style, ptSize, unitSize
  222 +}
  223 +
  224 +func (pdf *Helper) PageHasSpace(requiredHeight float64) bool {
  225 + _, h := pdf.GetPageSize()
  226 + _, _, _, bot := pdf.GetMargins()
  227 + return (h - bot - pdf.GetY()) > requiredHeight
  228 +}
  229 +
  230 +func (pdf *Helper) imageCenterOffset(w, h float64) (x, y float64) {
  231 + pageW, pageH := pdf.GetPageSize()
  232 + x = pageW/2.0 - w/2.0
  233 + y = pageH/2.0 - h/2.0
  234 + return x, y
  235 +}
  236 +
  237 +// call before drawing the cell
  238 +func (pdf *Helper) drawCellMargins(cw, ch float64) {
  239 + x0, y0 := pdf.GetX(), pdf.GetY()
  240 + pdf.DrawBox(x0, y0, cw, ch)
  241 +}
  242 +
  243 +// DrawBox ...
  244 +func (pdf Helper) DrawBox(x0, y0, w, h float64) {
  245 + pdf.Line(x0, y0, x0+w, y0)
  246 + pdf.Line(x0+w, y0, x0+w, y0+h)
  247 + pdf.Line(x0+w, y0+h, x0, y0+h)
  248 + pdf.Line(x0, y0+h, x0, y0)
  249 +}
  250 +
  251 +// Strana %d/{TotalPages}
  252 +func (pdf *Helper) InsertPageNumber(x, y float64, format string) {
  253 + num := fmt.Sprintf(format, pdf.PageNo())
  254 + pdf.Column(x, y, []FormatedCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}})
  255 +}
... ...