github.com/signintech/pdft@v0.5.0/pdft.go (about)

     1  package pdft
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/md5"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"os"
    11  	"strconv"
    12  	"strings"
    13  
    14  	gopdf "github.com/signintech/pdft/minigopdf"
    15  )
    16  
    17  // ErrAddSameFontName add same font name
    18  var ErrAddSameFontName = errors.New("add same font name")
    19  
    20  // ErrFontNameNotFound font name not found
    21  var ErrFontNameNotFound = errors.New("font name not found")
    22  
    23  // Left left
    24  const Left = gopdf.Left //001000
    25  // Top top
    26  const Top = gopdf.Top //000100
    27  // Right right
    28  const Right = gopdf.Right //000010
    29  // Bottom bottom
    30  const Bottom = gopdf.Bottom //000001
    31  // Center center
    32  const Center = gopdf.Center //010000
    33  // Middle middle
    34  const Middle = gopdf.Middle //100000
    35  
    36  // PDFt inject text to pdf
    37  type PDFt struct {
    38  	pdf           PDFData
    39  	fontDatas     map[string]*PDFFontData
    40  	pdfImgs       []*PDFImageData
    41  	pdfImgsMd5Map map[string]*PDFImageData
    42  	curr          current
    43  	contenters    []Contenter
    44  	pdfProtection *gopdf.PDFProtection
    45  }
    46  
    47  type current struct {
    48  	fontName  string
    49  	fontStyle int
    50  	fontSize  int
    51  	lineWidth float64
    52  }
    53  
    54  func pageHeight() float64 {
    55  	return 841.89
    56  }
    57  
    58  func (i *PDFt) protection() *gopdf.PDFProtection {
    59  	return i.pdfProtection
    60  }
    61  
    62  // ShowCellBorder  show cell of border
    63  func (i *PDFt) ShowCellBorder(isShow bool) {
    64  	var clw ContentLineStyle
    65  	if isShow {
    66  		clw.width = 0.1
    67  		clw.lineType = "dotted"
    68  		i.curr.lineWidth = 0.1
    69  	} else {
    70  		clw.width = 0.0
    71  		clw.lineType = ""
    72  		i.curr.lineWidth = 0.0
    73  	}
    74  	i.contenters = append(i.contenters, &clw)
    75  }
    76  
    77  // Open open pdf file
    78  func (i *PDFt) Open(filepath string) error {
    79  	f, err := os.Open(filepath)
    80  	if err != nil {
    81  		return err
    82  	}
    83  	defer f.Close()
    84  
    85  	return i.OpenFrom(f)
    86  }
    87  
    88  // OpenFrom open pdf from io.Reader
    89  func (i *PDFt) OpenFrom(r io.Reader) error {
    90  	//init
    91  	i.fontDatas = make(map[string]*PDFFontData)
    92  	i.curr.lineWidth = 1.0
    93  	i.pdfImgsMd5Map = make(map[string]*PDFImageData)
    94  	//open
    95  	err := PDFParse(r, &i.pdf)
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	i.ShowCellBorder(false)
   101  
   102  	return nil
   103  }
   104  
   105  // DuplicatePageAfter ...
   106  func (i *PDFt) DuplicatePageAfter(targetPageNumber, position int) error {
   107  	pageObjIds, err := i.pdf.getPageObjIDs()
   108  	if err != nil {
   109  		return err
   110  	}
   111  	if targetPageNumber > 0 && len(pageObjIds) < targetPageNumber {
   112  		return errors.New("No desired page to copy")
   113  	}
   114  
   115  	pageObj := *(i.pdf.getObjByID(pageObjIds[targetPageNumber-1])) //copy object value
   116  
   117  	props, err := pageObj.readProperties()
   118  	if err != nil {
   119  		return err
   120  	}
   121  	pageContent := props.getPropByKey("Contents")
   122  	if pageContent == nil {
   123  		return errors.New("No Contents property in this object")
   124  	}
   125  	contentID, _, err := pageContent.asDictionary()
   126  	if err != nil {
   127  		return err
   128  	}
   129  	contentID = i.pdf.putNewObject(*(i.pdf.getObjByID(contentID))) //copy object value
   130  	pageContent.setAsDictionary(contentID, 0)
   131  	pageObj.setProperties(props)
   132  
   133  	pageID := i.pdf.putNewObject(pageObj)
   134  
   135  	if position < 0 {
   136  		position = len(pageObjIds) + position // like python
   137  	}
   138  	pageObjIds = append(pageObjIds, 0)
   139  	copy(pageObjIds[position+1:], pageObjIds[position:])
   140  	pageObjIds[position+1] = pageID
   141  
   142  	return i.setPages(pageObjIds)
   143  }
   144  
   145  // RemovePage remove page at targetPageNumber
   146  func (i *PDFt) RemovePage(targetPageNumber int) error {
   147  	pageObjIds, err := i.pdf.getPageObjIDs()
   148  	if err != nil {
   149  		return err
   150  	}
   151  	if targetPageNumber > 0 && len(pageObjIds) < targetPageNumber {
   152  		return errors.New("No desired page to remove")
   153  	}
   154  	copy(pageObjIds[targetPageNumber-1:], pageObjIds[targetPageNumber:])
   155  	pageObjIds = pageObjIds[:len(pageObjIds)-1]
   156  
   157  	return i.setPages(pageObjIds)
   158  }
   159  
   160  // RemoveOtherPages remove all pages, but not targetPageNumber
   161  func (i *PDFt) RemoveOtherPages(targetPageNumber int) error {
   162  	pageObjIds, err := i.pdf.getPageObjIDs()
   163  	if err != nil {
   164  		return err
   165  	}
   166  	if targetPageNumber > 0 && len(pageObjIds) < targetPageNumber {
   167  		return errors.New("No desired page to keep")
   168  	}
   169  
   170  	return i.setPages([]int{pageObjIds[targetPageNumber]})
   171  }
   172  
   173  func (i *PDFt) setPages(pageObjIds []int) error {
   174  	props, err := i.pdf.pagesObj.readProperties()
   175  	if err != nil {
   176  		return err
   177  	}
   178  	nPage := len(pageObjIds)
   179  	props.getPropByKey("Count").rawVal = strconv.Itoa(nPage)
   180  	props.getPropByKey("Kids").setAsDictionaryArr(pageObjIds, nil)
   181  	i.pdf.pagesObj.setProperties(props)
   182  	return nil
   183  }
   184  
   185  // GetNumberOfPage get number of page
   186  func (i *PDFt) GetNumberOfPage() int {
   187  	pageObjIds, err := i.pdf.getPageObjIDs()
   188  	if err != nil {
   189  		return 0
   190  	}
   191  	return len(pageObjIds)
   192  }
   193  
   194  // Insert insert text in to pdf
   195  func (i *PDFt) Insert(text string, pageNum int, x float64, y float64, w float64, h float64, align int, fontColor *FontColor) error {
   196  	var ct ContentText
   197  	ct.text = text
   198  	ct.fontColor = fontColor
   199  	ct.fontName = i.curr.fontName
   200  	ct.fontStyle = i.curr.fontStyle
   201  	ct.fontSize = i.curr.fontSize
   202  	ct.pageNum = pageNum
   203  	ct.x = x
   204  	ct.y = y
   205  	ct.w = w
   206  	ct.h = h
   207  	ct.align = align
   208  	ct.lineWidth = i.curr.lineWidth
   209  	ct.setProtection(i.protection())
   210  	if _, have := i.fontDatas[ct.fontName]; !have {
   211  		return ErrFontNameNotFound
   212  	}
   213  	ct.pdfFontData = i.fontDatas[ct.fontName]
   214  	i.contenters = append(i.contenters, &ct)
   215  	return i.fontDatas[ct.fontName].addChars(text)
   216  }
   217  
   218  // MeasureTextWidth measure text width
   219  func (i *PDFt) MeasureTextWidth(text string) (float64, error) {
   220  	i.fontDatas[i.curr.fontName].addChars(text)
   221  	var ct ContentText
   222  	ct.text = text
   223  	ct.fontName = i.curr.fontName
   224  	ct.fontStyle = i.curr.fontStyle
   225  	ct.fontSize = i.curr.fontSize
   226  	ct.lineWidth = i.curr.lineWidth
   227  	if _, have := i.fontDatas[ct.fontName]; !have {
   228  		return 0, ErrFontNameNotFound
   229  	}
   230  	ct.pdfFontData = i.fontDatas[ct.fontName]
   231  	width, err := ct.measureTextWidth()
   232  	return width, err
   233  }
   234  
   235  // InsertImgBase64 insert img base 64
   236  func (i *PDFt) InsertImgBase64(base64str string, pageNum int, x float64, y float64, w float64, h float64) error {
   237  
   238  	var pdfimg PDFImageData
   239  	imgObj, smask, err := createImgObjFromImgBase64(base64str)
   240  	if err != nil {
   241  		return err
   242  	}
   243  
   244  	if smask != nil {
   245  		buff, err := smask.BytesBuffer(0) //ใส่ id ไปมั่วๆทำให้ไม่ support password protect
   246  		if err != nil {
   247  			return err
   248  		}
   249  		var pdfObj PDFObjData
   250  		pdfObj.data = buff.Bytes()
   251  		smaskObjID := i.pdf.putNewObject(pdfObj)
   252  		imgObj.SetSMaskObjID(smaskObjID)
   253  	}
   254  
   255  	err = pdfimg.setImgObj(imgObj)
   256  	if err != nil {
   257  		return err
   258  	}
   259  	/*err := pdfimg.setImgBase64(base64str)
   260  	if err != nil {
   261  		return err
   262  	}*/
   263  	i.pdfImgs = append(i.pdfImgs, &pdfimg)
   264  	//fmt.Printf("-->%d\n", len(i.pdfImgs))
   265  
   266  	var ct contentImgBase64
   267  	ct.pageNum = pageNum
   268  	ct.x = x
   269  	ct.y = y
   270  	ct.h = h
   271  	ct.w = w
   272  	ct.refPdfimg = &pdfimg //i.pdfImgs[len(i.pdfImgs)-1]
   273  	i.contenters = append(i.contenters, &ct)
   274  	return nil
   275  }
   276  
   277  // InsertImg insert img
   278  func (i *PDFt) InsertImg(img []byte, pageNum int, x float64, y float64, w float64, h float64) error {
   279  
   280  	var pdfimg PDFImageData
   281  	/*err := pdfimg.setImg(img)
   282  	if err != nil {
   283  		return err
   284  	}*/
   285  	imgObj, smask, err := createImgObjFromBytes(img)
   286  	if err != nil {
   287  		return err
   288  	}
   289  	if smask != nil {
   290  		buff, err := smask.BytesBuffer(0) //ใส่ id ไปมั่วๆทำให้ไม่ support password protect
   291  		if err != nil {
   292  			return err
   293  		}
   294  		var pdfObj PDFObjData
   295  		pdfObj.data = buff.Bytes()
   296  		smaskObjID := i.pdf.putNewObject(pdfObj)
   297  		imgObj.SetSMaskObjID(smaskObjID)
   298  	}
   299  
   300  	pdfimg.setImgObj(imgObj)
   301  
   302  	i.pdfImgs = append(i.pdfImgs, &pdfimg)
   303  	//fmt.Printf("-->%d\n", len(i.pdfImgs))
   304  
   305  	var ct contentImgBase64
   306  	ct.pageNum = pageNum
   307  	ct.x = x
   308  	ct.y = y
   309  	ct.h = h
   310  	ct.w = w
   311  	ct.refPdfimg = &pdfimg //i.pdfImgs[len(i.pdfImgs)-1]
   312  	i.contenters = append(i.contenters, &ct)
   313  	//fmt.Printf("append(i.contenters, &ct) %d\n", len(i.contenters))
   314  	//i.insertContenters(0, &ct)
   315  	return nil
   316  }
   317  
   318  // InsertImgWithCache insert img with cache
   319  func (i *PDFt) InsertImgWithCache(img []byte, pageNum int, x float64, y float64, w float64, h float64) error {
   320  	md5Str := fmt.Sprintf("%x", md5.Sum(img))
   321  	var pdfimg *PDFImageData
   322  	if val, ok := i.pdfImgsMd5Map[md5Str]; ok {
   323  		pdfimg = val
   324  	} else {
   325  		pdfimg = &PDFImageData{}
   326  		/*err := pdfimg.setImg(img)
   327  		if err != nil {
   328  			return err
   329  		}*/
   330  		imgObj, smask, err := createImgObjFromBytes(img)
   331  		if err != nil {
   332  			return err
   333  		}
   334  		if smask != nil {
   335  			buff, err := smask.BytesBuffer(0) //ใส่ id ไปมั่วๆทำให้ไม่ support password protect
   336  			if err != nil {
   337  				return err
   338  			}
   339  			var pdfObj PDFObjData
   340  			pdfObj.data = buff.Bytes()
   341  			smaskObjID := i.pdf.putNewObject(pdfObj)
   342  			imgObj.SetSMaskObjID(smaskObjID)
   343  		}
   344  		pdfimg.setImgObj(imgObj)
   345  
   346  		i.pdfImgs = append(i.pdfImgs, pdfimg)
   347  		i.pdfImgsMd5Map[md5Str] = pdfimg
   348  	}
   349  	var ct contentImgBase64
   350  	ct.pageNum = pageNum
   351  	ct.x = x
   352  	ct.y = y
   353  	ct.h = h
   354  	ct.w = w
   355  	ct.refPdfimg = pdfimg
   356  	i.contenters = append(i.contenters, &ct)
   357  	return nil
   358  }
   359  
   360  /*
   361  func (i *PDFt) insertContenters(index int, src Contenter) {
   362  	i.contenters = append(i.contenters, nil)
   363  	copy(i.contenters[index+1:], i.contenters[index:])
   364  	i.contenters[index] = src
   365  }*/
   366  
   367  // AddFont add ttf font
   368  func (i *PDFt) AddFont(name string, ttfpath string) error {
   369  
   370  	if _, have := i.fontDatas[name]; have {
   371  		return ErrAddSameFontName
   372  	}
   373  
   374  	fontData, err := PDFParseFont(ttfpath, name)
   375  	if err != nil {
   376  		return err
   377  	}
   378  
   379  	i.fontDatas[name] = fontData
   380  	return nil
   381  }
   382  
   383  func (i *PDFt) AddFontFrom(name string, reader io.Reader) error {
   384  
   385  	if _, have := i.fontDatas[name]; have {
   386  		return ErrAddSameFontName
   387  	}
   388  
   389  	fontData, err := PDFParseFontReader(reader, name)
   390  	if err != nil {
   391  		return err
   392  	}
   393  
   394  	i.fontDatas[name] = fontData
   395  	return nil
   396  }
   397  
   398  // TextriseOverride override text rise
   399  // Text rise, Trise , specifies the distance, in unscaled text space units,
   400  // to move the baseline up or down from its default location.
   401  // Positive values of text rise move the baseline up.
   402  // Adjustments to the baseline are useful for drawing superscripts or subscripts.
   403  // The default location of the baseline can be restored by setting the text rise to 0.
   404  func (i *PDFt) TextriseOverride(name string, fn FuncTextriseOverride) error {
   405  	if _, have := i.fontDatas[name]; !have {
   406  		return ErrFontNameNotFound
   407  	}
   408  	i.fontDatas[name].font.SetFuncTextriseOverride(func(
   409  		leftRune rune,
   410  		rightRune rune,
   411  		fontsize int,
   412  		allText string,
   413  		currTextIndex int,
   414  	) float32 {
   415  		return fn(leftRune, rightRune, fontsize, allText, currTextIndex)
   416  	})
   417  	return nil
   418  }
   419  
   420  // KernOverride override kerning
   421  func (i *PDFt) KernOverride(name string, fn FuncKernOverride) error {
   422  	if _, have := i.fontDatas[name]; !have {
   423  		return ErrFontNameNotFound
   424  	}
   425  	i.fontDatas[name].font.SetFuncKernOverride(func(
   426  		leftRune rune,
   427  		rightRune rune,
   428  		leftPair uint,
   429  		rightPair uint,
   430  		pairVal int16,
   431  	) int16 {
   432  		return fn(leftRune, rightRune, leftPair, rightPair, pairVal)
   433  	})
   434  	return nil
   435  }
   436  
   437  // SetFont set font
   438  func (i *PDFt) SetFont(name string, style string, size int) error {
   439  
   440  	if _, have := i.fontDatas[name]; !have {
   441  		return ErrFontNameNotFound
   442  	}
   443  	i.curr.fontName = name
   444  	i.curr.fontStyle = getConvertedStyle(style)
   445  	i.curr.fontSize = size
   446  	return nil
   447  }
   448  
   449  // Save save output pdf
   450  func (i *PDFt) Save(filepath string) error {
   451  	var buff bytes.Buffer
   452  	err := i.SaveTo(&buff)
   453  	if err != nil {
   454  		return err
   455  	}
   456  	err = ioutil.WriteFile(filepath, buff.Bytes(), 0644)
   457  	if err != nil {
   458  		return err
   459  	}
   460  	return nil
   461  }
   462  
   463  // SaveTo save pdf to io.Writer
   464  func (i *PDFt) SaveTo(w io.Writer) error {
   465  
   466  	newpdf, lastID, err := i.build()
   467  	if err != nil {
   468  		return err
   469  	}
   470  
   471  	buff, err := i.toStream(newpdf, lastID)
   472  	if err != nil {
   473  		return err
   474  	}
   475  	_, err = buff.WriteTo(w)
   476  	if err != nil {
   477  		return err
   478  	}
   479  	return nil
   480  }
   481  
   482  func (i *PDFt) build() (*PDFData, int, error) {
   483  
   484  	var err error
   485  	nextID := i.pdf.maxID()
   486  	for _, fontData := range i.fontDatas {
   487  		nextID++
   488  		fontData.setStartID(nextID)
   489  		nextID, err = fontData.build()
   490  		if err != nil {
   491  			return nil, 0, err
   492  		}
   493  	}
   494  
   495  	newpdf := i.pdf //copy
   496  
   497  	err = newpdf.injectFontsToPDF(i.fontDatas)
   498  	if err != nil {
   499  		return nil, 0, err
   500  	}
   501  
   502  	//ยัด subsetfont obj กลับไป
   503  	for _, fontData := range i.fontDatas {
   504  
   505  		var fontobj, cidObj, unicodeMapObj, fontDescObj, dictionaryObj PDFObjData
   506  
   507  		fontobj.objID = fontData.fontID
   508  		fontobj.data = fontData.fontStream.Bytes()
   509  
   510  		cidObj.objID = fontData.cidID
   511  		cidObj.data = fontData.cidStream.Bytes()
   512  
   513  		unicodeMapObj.objID = fontData.unicodeMapID
   514  		unicodeMapObj.data = fontData.unicodeMapStream.Bytes()
   515  
   516  		fontDescObj.objID = fontData.fontDescID
   517  		fontDescObj.data = fontData.fontDescStream.Bytes()
   518  
   519  		dictionaryObj.objID = fontData.dictionaryID
   520  		dictionaryObj.data = fontData.dictionaryStream.Bytes()
   521  
   522  		newpdf.put(fontobj)
   523  		newpdf.put(cidObj)
   524  		newpdf.put(unicodeMapObj)
   525  		newpdf.put(fontDescObj)
   526  		newpdf.put(dictionaryObj)
   527  	}
   528  
   529  	for j, pdfImg := range i.pdfImgs {
   530  		nextID++
   531  		var obj PDFObjData
   532  		obj.objID = nextID
   533  		obj.data = pdfImg.imgObj.GetObjBuff().Bytes()
   534  		i.pdfImgs[j].objID = obj.objID
   535  		//fmt.Printf("---->%d\n", obj.objID)
   536  		newpdf.put(obj)
   537  	}
   538  
   539  	err = newpdf.injectImgsToPDF(i.pdfImgs)
   540  	if err != nil {
   541  		return nil, 0, err
   542  	}
   543  
   544  	err = newpdf.injectContentToPDF(&i.contenters)
   545  	if err != nil {
   546  		return nil, 0, err
   547  	}
   548  
   549  	//set for protection
   550  	if i.protection() != nil {
   551  		max := newpdf.Len()
   552  		x := 0
   553  		for x < max {
   554  			newpdf.objs[x].encrypt(i.protection())
   555  			x++
   556  		}
   557  	}
   558  
   559  	return &newpdf, nextID, nil
   560  }
   561  
   562  func (i *PDFt) toStream(newpdf *PDFData, lastID int) (*bytes.Buffer, error) {
   563  
   564  	//set for protection
   565  	encryptionObjID := -1
   566  	if i.protection() != nil {
   567  		lastID++
   568  		encryptionObjID = lastID
   569  		enObj := i.protection().EncryptionObj()
   570  		err := enObj.Build(lastID)
   571  		if err != nil {
   572  			return nil, err
   573  		}
   574  		buff := enObj.GetObjBuff()
   575  		var enPDFObjData PDFObjData
   576  		enPDFObjData.data = buff.Bytes()
   577  		enPDFObjData.objID = lastID
   578  		newpdf.put(enPDFObjData)
   579  	}
   580  
   581  	var buff bytes.Buffer
   582  	buff.WriteString("%PDF-1.7\n\n")
   583  	xrefs := make(map[int]int)
   584  	for _, obj := range newpdf.objs {
   585  		//xrefs = append(xrefs, buff.Len())
   586  		//fmt.Printf("%d\n", obj.objID)
   587  		xrefs[obj.objID] = buff.Len()
   588  		buff.WriteString(fmt.Sprintf("\n%d 0 obj\n", obj.objID))
   589  		buff.WriteString(strings.TrimSpace(string(obj.data)))
   590  		buff.WriteString("\nendobj\n")
   591  	}
   592  	i.xref(xrefs, &buff, lastID, newpdf.trailer.rootObjID, encryptionObjID)
   593  
   594  	return &buff, nil
   595  }
   596  
   597  type xrefrow struct {
   598  	offset int
   599  	gen    string
   600  	flag   string
   601  }
   602  
   603  func (i *PDFt) xref(linelens map[int]int, buff *bytes.Buffer, size int, rootID int, encryptionObjID int) {
   604  	xrefbyteoffset := buff.Len()
   605  
   606  	//start xref
   607  	buff.WriteString("\nxref\n")
   608  	buff.WriteString(fmt.Sprintf("0 %d\r\n", size+1))
   609  	var xrefrows []xrefrow
   610  	xrefrows = append(xrefrows, xrefrow{offset: 0, flag: "f", gen: "65535"})
   611  	lastIndexOfF := 0
   612  	j := 1
   613  	//fmt.Printf("size:%d\n", size)
   614  	for j <= size {
   615  		if linelen, ok := linelens[j]; ok {
   616  			xrefrows = append(xrefrows, xrefrow{offset: linelen, flag: "n", gen: "00000"})
   617  		} else {
   618  			xrefrows = append(xrefrows, xrefrow{offset: 0, flag: "f", gen: "65535"})
   619  			offset := len(xrefrows) - 1
   620  			xrefrows[lastIndexOfF].offset = offset
   621  			lastIndexOfF = offset
   622  		}
   623  		j++
   624  	}
   625  
   626  	for _, xrefrow := range xrefrows {
   627  		buff.WriteString(i.formatXrefline(xrefrow.offset) + " " + xrefrow.gen + " " + xrefrow.flag + " \n")
   628  	}
   629  	//end xref
   630  
   631  	buff.WriteString("trailer\n")
   632  	buff.WriteString("<<\n")
   633  	buff.WriteString(fmt.Sprintf("/Size %d\n", size+1))
   634  	buff.WriteString(fmt.Sprintf("/Root %d 0 R\n", rootID))
   635  	if i.protection() != nil {
   636  		buff.WriteString(fmt.Sprintf("/Encrypt %d 0 R\n", encryptionObjID))
   637  		buff.WriteString("/ID [()()]\n")
   638  	}
   639  	buff.WriteString(">>\n")
   640  
   641  	buff.WriteString("startxref\n")
   642  	buff.WriteString(strconv.Itoa(xrefbyteoffset))
   643  	buff.WriteString("\n%%EOF\n")
   644  }
   645  
   646  func (i *PDFt) formatXrefline(n int) string {
   647  	str := strconv.Itoa(n)
   648  	for len(str) < 10 {
   649  		str = "0" + str
   650  	}
   651  	return str
   652  }
   653  
   654  // SetProtection set pdf protection
   655  func (i *PDFt) SetProtection(
   656  	permissions int,
   657  	userPass []byte,
   658  	ownerPass []byte,
   659  ) error {
   660  	var p gopdf.PDFProtection
   661  	err := p.SetProtection(permissions, userPass, ownerPass)
   662  	if err != nil {
   663  		return err
   664  	}
   665  	i.pdfProtection = &p
   666  	return nil
   667  }
   668  
   669  // Regular - font style regular
   670  const Regular = 0 //000000
   671  // Italic - font style italic
   672  const Italic = 1 //000001
   673  // Bold - font style bold
   674  const Bold = 2 //000010
   675  // Underline - font style underline
   676  const Underline = 4 //000100
   677  
   678  func getConvertedStyle(fontStyle string) (style int) {
   679  	fontStyle = strings.ToUpper(fontStyle)
   680  	if strings.Contains(fontStyle, "B") {
   681  		style = style | Bold
   682  	}
   683  	if strings.Contains(fontStyle, "I") {
   684  		style = style | Italic
   685  	}
   686  	if strings.Contains(fontStyle, "U") {
   687  		style = style | Underline
   688  	}
   689  	return
   690  }