Full Code of sopov/resumeio2pdf for AI

main 528274d3c22e cached
108 files
300.1 KB
96.1k tokens
794 symbols
1 requests
Download .txt
Showing preview only (330K chars total). Download the full file or copy to clipboard to get everything.
Repository: sopov/resumeio2pdf
Branch: main
Commit: 528274d3c22e
Files: 108
Total size: 300.1 KB

Directory structure:
gitextract_c0w8xc36/

├── .github/
│   └── workflows/
│       ├── codeql-analysis.yml
│       ├── go.yml
│       └── golangci-lint.yml
├── .gitignore
├── LICENSE
├── README.md
├── go.mod
├── go.sum
├── main.go
└── vendor/
    ├── github.com/
    │   ├── phpdave11/
    │   │   └── gofpdi/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── const.go
    │   │       ├── go.mod
    │   │       ├── go.sum
    │   │       ├── gofpdi.go
    │   │       ├── helper.go
    │   │       ├── importer.go
    │   │       ├── reader.go
    │   │       └── writer.go
    │   ├── pkg/
    │   │   └── errors/
    │   │       ├── .gitignore
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── appveyor.yml
    │   │       ├── errors.go
    │   │       └── stack.go
    │   └── signintech/
    │       └── gopdf/
    │           ├── .gitignore
    │           ├── Changelog.md
    │           ├── LICENSE
    │           ├── README.md
    │           ├── box.go
    │           ├── buff.go
    │           ├── buff_write.go
    │           ├── buffer_pool.go
    │           ├── cache_contact_color.go
    │           ├── cache_content_gray.go
    │           ├── cache_content_image.go
    │           ├── cache_content_imported_object.go
    │           ├── cache_content_line.go
    │           ├── cache_content_line_type.go
    │           ├── cache_content_line_width.go
    │           ├── cache_content_oval.go
    │           ├── cache_content_polygon.go
    │           ├── cache_content_rectangle.go
    │           ├── cache_content_rotate.go
    │           ├── cache_content_text.go
    │           ├── cache_contnent_curve.go
    │           ├── catalog_obj.go
    │           ├── cell_option.go
    │           ├── cid_font_obj.go
    │           ├── config.go
    │           ├── content_obj.go
    │           ├── current.go
    │           ├── device_rgb_obj.go
    │           ├── embedfont_obj.go
    │           ├── encoding_obj.go
    │           ├── encryption_obj.go
    │           ├── ext_g_state_obj.go
    │           ├── font_obj.go
    │           ├── font_option.go
    │           ├── fontconverthelper.go
    │           ├── fontdescriptor_obj.go
    │           ├── fontmaker/
    │           │   └── core/
    │           │       ├── fontmaker.go
    │           │       ├── fontmap.go
    │           │       ├── kern_table.go
    │           │       ├── math.go
    │           │       ├── table_directory_entry.go
    │           │       ├── ttf_info.go
    │           │       ├── ttfparser.go
    │           │       ├── ttfparser_cmap_other_format.go
    │           │       └── ttfparser_kern.go
    │           ├── func_kern_override.go
    │           ├── go.mod
    │           ├── go.sum
    │           ├── gopdf.go
    │           ├── i_cache_contneter.go
    │           ├── ifont.go
    │           ├── image_holder.go
    │           ├── image_obj.go
    │           ├── image_obj_parse.go
    │           ├── img_info.go
    │           ├── imported_obj.go
    │           ├── iobj.go
    │           ├── link_option.go
    │           ├── list_cache_content.go
    │           ├── map_of_character_To_glyph_index.go
    │           ├── margin.go
    │           ├── outlines_obj.go
    │           ├── page_obj.go
    │           ├── page_option.go
    │           ├── page_sizes.go
    │           ├── pages_obj.go
    │           ├── pdf_dictionary_obj.go
    │           ├── pdf_info_obj.go
    │           ├── pdf_protection.go
    │           ├── point.go
    │           ├── procset_obj.go
    │           ├── rect.go
    │           ├── smask_obj.go
    │           ├── strhelper.go
    │           ├── style.go
    │           ├── subfont_descriptor_obj.go
    │           ├── subset_font_obj.go
    │           ├── transparency.go
    │           ├── transparency_xobject_group.go
    │           ├── ttf_option.go
    │           └── unicode_map.go
    └── modules.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
  push:
    branches: [ main ]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ main ]
  schedule:
    - cron: '43 20 * * 5'

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ 'go' ]
        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
        # Learn more:
        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v1
      with:
        languages: ${{ matrix.language }}
        # If you wish to specify custom queries, you can do so here or in a config file.
        # By default, queries listed here will override any specified in a config file.
        # Prefix the list here with "+" to use these queries and those in the config file.
        # queries: ./path/to/local/query, your-org/your-repo/queries@main

    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
    # If this step fails, then you should remove it and run the build manually (see below)
    - name: Autobuild
      uses: github/codeql-action/autobuild@v1

    # ℹ️ Command-line programs to run using the OS shell.
    # 📚 https://git.io/JvXDl

    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
    #    and modify them (or add more) to build your code if your project
    #    uses a compiled language

    #- run: |
    #   make bootstrap
    #   make release

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v1


================================================
FILE: .github/workflows/go.yml
================================================
name: Go

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:

  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - name: Set up Go
      uses: actions/setup-go@v2
      with:
        go-version: 1.17

    - name: Build
      run: go build -v ./...

    - name: Test
      run: go test -v ./...


================================================
FILE: .github/workflows/golangci-lint.yml
================================================
name: golangci-lint
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v2
        with:
          version: latest


================================================
FILE: .gitignore
================================================
# PDF files
*.pdf

# Test binary, built with `go test -c`
*.test

.idea/

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 Leonid Sopov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# resumeio2pdf

> ⚠️ This project is no longer maintained.  
> Resume.io made changes on their side, so the tool no longer works.

A progam that allows users to download their resumes from [resume.io](https://resume.io/) as PDFs, including links.

## Usage

```bash
./resumeio2pdf [options] [ID or URL]
./resumeio2pdf https://resume.io/r/SecureID
```

Options:
*  `-pdf` (string)  name of pdf file (default: `SecureID` + `.pdf`)
*  `-sid` (string) SecureID of resume
*  `-url` (string) link to resume of the format: https://resume.io/r/SecureID
*  `-verbose` show detail information
*  `-version` show version
*  `-y`	overwrite PDF file

## Quick Instructions
1. Run `go build` to generate the executable.
2. Run `./resumeio2pdf https://resume.io/r/[SecureID]` where the provided URL is that generated by the **Share Link** on resume.io.

## Step-by-Step Instructions
1. Download the application by clicking the **<> Code** button and choosing **Download ZIP**.
 
2. Once the download has been completed, extract the files. You will end up with a **resumeio2pdf-main/** folder.

3. Open your terminal and navigate to the **resumeio2pdf-main/** folder that you have just extracted.
- You may have the option to skip this by simply choosing the **New Terminal at Folder** after right clicking on the folder.

4. With your terminal still open, type the command `go version` to see if you already have Go installed.
- If you get a message with version information that looks something like `go version go1.17.6 …` then you can skip to Step 6.
- Otherwise, continue on to the next step.

5. Open your web browser and navigate to the [Go Downloads Page](https://go.dev/dl/) and choose your operating system from the **Featured Downloads** section. Download the package and follow the installation instructions.
- Upon completion, restart your terminal and navigate back to the **resumeio2pdf-main/** folder. You should now see version information after typing in the `go version` command. If you have issues with this step, try visiting the [Go Download and Install Page](https://go.dev/doc/install) for the official instructions. 

6. With Go installed, you can now run the `go build` command to build the executable file that will download your PDF.
- A successful build will not display any confirmation in the terminal. However, you can check the files in the **resumeio2pdf-main/** folder to confirm that a **resumeio2pdf** executable file has been generated by the command. 
- If you received an error in the terminal, make sure you are still in the **resumeio2pdf-main/** folder before running the command. Otherwise, trace back through the above steps and give it another shot.

7. Finally, you can run the `./resumeio2pdf https://resume.io/r/[SecureID]` where the provided URL is that generated by the **Share Link** on resume.io. When the process is complete, you will receive a message in the terminal that your file has been stored as **\[SecureID].pdf**. Check the **resumeio2pdf-main/** folder for your file.

## Alternative Methods
Repository with binary files: https://github.com/sopov/resumeio2pdf.bin

## Other Questions and Concerns
* I don't understand how to install and/or use Go.
* Can you download my resume for me? 
* Can you make a video tutorial?

Please visit the [pricing page on Resume.io](https://resume.io/pricing) which provides fair and affordable prices for this service, including an easy method of downloading your resume without the use of this software.


================================================
FILE: go.mod
================================================
module github.com/sopov/resumeio2pdf

go 1.16

require github.com/signintech/gopdf v0.9.20


================================================
FILE: go.sum
================================================
github.com/phpdave11/gofpdi v1.0.11 h1:wsBNx+3S0wy1dEp6fzv281S74ogZGgIdYWV2PugWgho=
github.com/phpdave11/gofpdi v1.0.11/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/signintech/gopdf v0.9.20 h1:UJInJStc5NpkSCSZCmkSrUy7JR/BqRWpoH50c7hJJ5w=
github.com/signintech/gopdf v0.9.20/go.mod h1:PXwitUSeFWEWs+wHVjSS3cUmD4PTXB686ozqfDIQQoQ=


================================================
FILE: main.go
================================================
package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"time"

	"github.com/signintech/gopdf"
)

const (
	Version       = "1.0"
	NameOfProgram = "resumeio2pdf"
	Copy          = "Copyright (c) 2021, Leonid Sopov <leonid@sopov.org>"
	CopyURL       = "https://github.com/sopov/resumeio2pdf/"

	resumePage = "https://resume.io/r/%s"
	resumeMeta = "https://ssr.resume.tools/meta/ssid-%s?cache=%s"
	resumeExt  = "png" // png, jpeg
	resumeIMG  = "https://ssr.resume.tools/to-image/ssid-%s-%d.%s?cache=%s&size=%d"
	resumeSize = 1800
	Timeout    = 60 * time.Second

	exitCodeMisuseArgs = 2
)

var (
	url         = flag.String("url", "", "link to resume of the format: https://resume.io/r/SecureID")
	sid         = flag.String("sid", "", "SecureID of resume")
	showVersion = flag.Bool("version", false, "show version")
	verbose     = flag.Bool("verbose", false, "show detail information")
	overWrite   = flag.Bool("y", false, "overwrite PDF file")
	pdfFileName = flag.String("pdf", "", "name of pdf file (default: SecureID + .pdf)")

	httpClient = &http.Client{Timeout: Timeout}
	reSID      = regexp.MustCompile(`^[[:alnum:]]+$`)
	reID       = regexp.MustCompile(`^\d+$`)
	reURL      = regexp.MustCompile(`^https://resume[.]io/r/([[:alnum:]]+)`)
	reIDURL    = regexp.MustCompile(`^https://resume[.]io/(?:app|api)/.*?/(\d+)`)
)

type metaLink struct {
	URL    string  `json:"url"`
	Left   float64 `json:"left"`
	Top    float64 `json:"top"`
	Height float64 `json:"height"`
	Width  float64 `json:"width"`
}

type metaViewPort struct {
	Height float64 `json:"height"`
	Width  float64 `json:"width"`
}

type metaPageInfo struct {
	Links    []metaLink   `json:"links"`
	ViewPort metaViewPort `json:"viewport"`
}

type metaInfo struct {
	Pages []metaPageInfo `json:"pages"`
}

func main() {
	if !readFlags() || *sid == "" {
		os.Exit(exitCodeMisuseArgs)
	}

	loggerf("SecureID: %s", *sid)
	loggerf("URL: %s", *url)
	loggerf("PDF: %s", *pdfFileName)

	meta, err := getMeta()
	if err != nil {
		log.Fatalln(err)
	}

	images, err := getResumeImages(len(meta.Pages))
	if err != nil {
		log.Fatalln(err)
	}

	err = generatePDF(meta, images)
	if err != nil {
		log.Fatalln(err)
	}

	cleanup(images)

	fmt.Printf("Resume stored to %s\n", *pdfFileName)
}

func cleanup(images []string) {
	for _, file := range images {
		if _, err := os.Stat(file); os.IsNotExist(err) {
			continue
		}

		if err := os.Remove(file); err != nil {
			fmt.Printf("Error on remove `%s': %s", file, err.Error())
		} else {
			loggerf("Image `%s' successfully deleted.", file)
		}
	}
}

func generatePDF(info *metaInfo, images []string) error {
	pdf := gopdf.GoPdf{}

	logger("Start Generate PDF")

	pageSize := gopdf.Rect{
		W: info.Pages[0].ViewPort.Width,
		H: info.Pages[0].ViewPort.Height,
	}

	pdf.Start(gopdf.Config{PageSize: pageSize})

	for i, image := range images {
		loggerf("Add page #%d", i+1)

		pageSize := gopdf.Rect{
			W: info.Pages[i].ViewPort.Width,
			H: info.Pages[i].ViewPort.Height,
		}

		opt := gopdf.PageOption{
			PageSize: &pageSize,
		}
		pdf.AddPageWithOption(opt)

		err := pdf.Image(image, 0, 0, &pageSize)
		if err != nil {
			return err
		}

		for _, link := range info.Pages[i].Links {
			loggerf("Add link to %s", link.URL)

			x := link.Left
			y := pageSize.H - link.Top - link.Height
			pdf.AddExternalLink(link.URL, x, y, link.Width, link.Height)
		}
	}

	loggerf("Store PDF to `%s'", *pdfFileName)

	return pdf.WritePdf(*pdfFileName)
}

func getResumeImages(p int) (pages []string, err error) {
	if p < 1 {
		return nil, errors.New("required one or more pages")
	}

	for pID := 1; pID <= p; pID++ {
		pageFile := fmt.Sprintf("%s-%d.%s", *sid, pID, resumeExt)
		if _, err := os.Stat(pageFile); os.IsNotExist(err) {
			loggerf("Download image #%d/%d", pID, p)
			imgURL := fmt.Sprintf(resumeIMG, *sid, pID, resumeExt, time.Now().UTC().Format(time.RFC3339), resumeSize)

			if err := downloadPage(imgURL, pageFile); err != nil {
				return pages, err
			}
		}

		pages = append(pages, pageFile)
	}

	loggerf("Total %d pages", len(pages))

	return pages, nil
}

func downloadPage(imgURL, imgFile string) error {
	r, err := httpClient.Get(imgURL)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	if r.StatusCode != http.StatusOK {
		return errors.New(r.Status)
	}

	file, err := os.Create(imgFile)
	if err != nil {
		return err
	}

	defer file.Close()

	_, err = io.Copy(file, r.Body)
	if err != nil {
		return err
	}

	return nil
}

func getJSON(url string, target interface{}) error {
	logger("Download meta information")

	r, err := httpClient.Get(url)
	if err != nil {
		return err
	}

	defer r.Body.Close()

	if r.StatusCode != http.StatusOK {
		return fmt.Errorf("Can't download information from the site resume.io. Please, check URL.\n\nError: %s", r.Status)
	}

	decoder := json.NewDecoder(r.Body)

	err = decoder.Decode(&target)
	if err != nil {
		return err
	}

	return nil
}

func getMeta() (meta *metaInfo, err error) {
	metaURL := fmt.Sprintf(resumeMeta, *sid, time.Now().UTC().Format(time.RFC3339))
	meta = &metaInfo{}
	err = getJSON(metaURL, meta)

	return meta, err
}

func readFlags() bool {
	flag.Parse()

	if *showVersion {
		fmt.Printf("Version: %s\n", Version)

		return false
	}

	if !extractArg() {
		return false
	}

	if *sid == "" && *url == "" {
		usages()
		return false
	}

	if *sid != "" {
		if !reSID.MatchString(*sid) {
			fmt.Println("The ID must be as alphanumeric")
			return false
		}

		*url = fmt.Sprintf(resumePage, *sid)
	}

	if reIDURL.MatchString(*url) {
		usageID()
		return false
	}

	if !reURL.MatchString(*url) {
		msg := fmt.Sprintf("The URL must be in the format %s\n", resumePage)
		fmt.Printf(msg, "SecureID")

		return false
	}

	if *sid == "" {
		m := reURL.FindSubmatch([]byte(*url))
		*sid = string(m[1])
	}

	if *pdfFileName == "" {
		*pdfFileName = fmt.Sprintf("%s.pdf", *sid)
	}

	rePDF := regexp.MustCompile(`(?i)[.]pdf$`)
	if !rePDF.MatchString(*pdfFileName) {
		*pdfFileName = fmt.Sprintf("%s.pdf", *pdfFileName)
	}

	if _, err := os.Stat(*pdfFileName); !*overWrite && !os.IsNotExist(err) {
		fmt.Printf("File `%s' already exists.\n\nFor overwrite run with `-y' flag\n", *pdfFileName)

		return false
	}

	return true
}

func extractArg() bool {
	arg := flag.Arg(0)

	if arg == "" {
		return true
	}

	if reID.MatchString(arg) {
		usageID()
		return false
	}

	if reIDURL.MatchString(arg) {
		usageID()
		return false
	}

	if reSID.MatchString(arg) {
		*sid = arg
		return true
	}

	if reURL.MatchString(arg) {
		*url = arg
		return true
	}

	return true
}

func usages() {
	fileExec, err := os.Executable()
	if err == nil {
		fileExec = filepath.Base(fileExec)
	}

	if fileExec == "" {
		fileExec = NameOfProgram
	}

	fmt.Println("Syntax:")
	fmt.Println("  ", fileExec, "[options] [ID or URL]")

	fmt.Println()
	fmt.Println("Options:")
	flag.PrintDefaults()

	fmt.Println()
	fmt.Println(Copy)
	fmt.Println(CopyURL)
}

func usageID() {
	fmt.Println("Open in browser: https://resume.io/app/resumes")
	fmt.Println("Click on `...More' / `Share a link', and lunch with private URL.")
}

func logger(v ...interface{}) {
	if !*verbose {
		return
	}

	log.Println(v...)
}

func loggerf(format string, a ...interface{}) {
	if !*verbose {
		return
	}

	log.Printf(format, a...)
}


================================================
FILE: vendor/github.com/phpdave11/gofpdi/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2019-2020 David Barnes
Copyright (c) 2017 Setasign - Jan Slabon, https://www.setasign.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: vendor/github.com/phpdave11/gofpdi/README.md
================================================
# gofpdi
[![MIT
licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/phpdave11/gofpdi/master/LICENSE)
[![Report](https://goreportcard.com/badge/github.com/phpdave11/gofpdi)](https://goreportcard.com/report/github.com/phpdave11/gofpdi)
[![GoDoc](https://img.shields.io/badge/godoc-gofpdi-blue.svg)](https://godoc.org/github.com/phpdave11/gofpdi)

## Go Free PDF Document Importer

gofpdi allows you to import an existing PDF into a new PDF.  The following PDF generation libraries are supported:

- [gopdf](https://github.com/signintech/gopdf)

- [gofpdf](https://github.com/phpdave11/gofpdf)

## Acknowledgments
This package’s code is derived from the [fpdi](https://github.com/Setasign/FPDI/tree/1.6.x-legacy) library created by [Jan Slabon](https://github.com/JanSlabon).
[mrtsbt](https://github.com/mrtsbt) added support for reading a PDF from an `io.ReadSeeker` stream and also added support for using gofpdi concurrently.  [Asher Tuggle](https://github.com/awesomeunleashed) added support for reading PDFs that have split xref tables.

## Examples

### gopdf example

```go
package main

import (
        "github.com/signintech/gopdf"
        "io"
        "net/http"
        "os"
)

func main() {
        var err error

        // Download a Font
        fontUrl := "https://github.com/google/fonts/raw/master/ofl/daysone/DaysOne-Regular.ttf"
        if err = DownloadFile("example-font.ttf", fontUrl); err != nil {
                panic(err)
        }

        // Download a PDF
        fileUrl := "https://tcpdf.org/files/examples/example_012.pdf"
        if err = DownloadFile("example-pdf.pdf", fileUrl); err != nil {
                panic(err)
        }

        pdf := gopdf.GoPdf{}
        pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4

        pdf.AddPage()

        err = pdf.AddTTFFont("daysone", "example-font.ttf")
        if err != nil {
                panic(err)
        }

        err = pdf.SetFont("daysone", "", 20)
        if err != nil {
                panic(err)
        }

        // Color the page
        pdf.SetLineWidth(0.1)
        pdf.SetFillColor(124, 252, 0) //setup fill color
        pdf.RectFromUpperLeftWithStyle(50, 100, 400, 600, "FD")
        pdf.SetFillColor(0, 0, 0)

        pdf.SetX(50)
        pdf.SetY(50)
        pdf.Cell(nil, "Import existing PDF into GoPDF Document")

        // Import page 1
        tpl1 := pdf.ImportPage("example-pdf.pdf", 1, "/MediaBox")

        // Draw pdf onto page
        pdf.UseImportedTemplate(tpl1, 50, 100, 400, 0)

        pdf.WritePdf("example.pdf")

}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {
        // Get the data
        resp, err := http.Get(url)
        if err != nil {
                return err
        }
        defer resp.Body.Close()

        // Create the file
        out, err := os.Create(filepath)
        if err != nil {
                return err
        }
        defer out.Close()

        // Write the body to file
        _, err = io.Copy(out, resp.Body)
        return err
}
```

Generated PDF: [example.pdf](https://github.com/signintech/gopdf/files/3144466/example.pdf)

Screenshot of PDF:

![example](https://user-images.githubusercontent.com/9421180/57180557-4c1dbd80-6e4f-11e9-8f47-9d40217805be.jpg)

### gofpdf example #1 - import PDF from file

```go
package main

import (
	"github.com/phpdave11/gofpdf"
	"github.com/phpdave11/gofpdf/contrib/gofpdi"
	"io"
	"net/http"
	"os"
)

func main() {
	var err error

	pdf := gofpdf.New("P", "mm", "A4", "")

	// Download a PDF
	fileUrl := "https://tcpdf.org/files/examples/example_026.pdf"
	if err = DownloadFile("example-pdf.pdf", fileUrl); err != nil {
		panic(err)
	}

	// Import example-pdf.pdf with gofpdi free pdf document importer
	tpl1 := gofpdi.ImportPage(pdf, "example-pdf.pdf", 1, "/MediaBox")

	pdf.AddPage()

	pdf.SetFillColor(200, 700, 220)
	pdf.Rect(20, 50, 150, 215, "F")

	// Draw imported template onto page
	gofpdi.UseImportedTemplate(pdf, tpl1, 20, 50, 150, 0)

	pdf.SetFont("Helvetica", "", 20)
	pdf.Cell(0, 0, "Import existing PDF into gofpdf document with gofpdi")

	err = pdf.OutputFileAndClose("example.pdf")
	if err != nil {
		panic(err)
	}
}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {
	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Create the file
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Write the body to file
	_, err = io.Copy(out, resp.Body)
	return err
}
```

Generated PDF:  [example.pdf](https://github.com/phpdave11/gofpdf/files/3178770/example.pdf)

Screenshot of PDF:
![example](https://user-images.githubusercontent.com/9421180/57713804-ca8d1300-7638-11e9-9f8e-e3f803374803.jpg)



### gofpdf example #2 - import PDF from stream

```go
package main

import (
    "bytes"
    "github.com/phpdave11/gofpdf"
    "github.com/phpdave11/gofpdf/contrib/gofpdi"
    "io"
    "io/ioutil"
    "net/http"
)

func main() {
    var err error

    pdf := gofpdf.New("P", "mm", "A4", "")

    // Download a PDF into memory                                                                                                                     
    res, err := http.Get("https://tcpdf.org/files/examples/example_038.pdf")
    if err != nil {
        panic(err)
    }
    pdfBytes, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        panic(err)
    }

    // convert []byte to io.ReadSeeker                                                                                                                
    rs := io.ReadSeeker(bytes.NewReader(pdfBytes))

    // Import in-memory PDF stream with gofpdi free pdf document importer                                                                             
    tpl1 := gofpdi.ImportPageFromStream(pdf, &rs, 1, "/TrimBox")

    pdf.AddPage()

    pdf.SetFillColor(200, 700, 220)
    pdf.Rect(20, 50, 150, 215, "F")

    // Draw imported template onto page                                                                                                               
    gofpdi.UseImportedTemplate(pdf, tpl1, 20, 50, 150, 0)

    pdf.SetFont("Helvetica", "", 20)
    pdf.Cell(0, 0, "Import PDF stream into gofpdf document with gofpdi")

    err = pdf.OutputFileAndClose("example.pdf")
    if err != nil {
        panic(err)
    }
}
```

Generated PDF:

[example.pdf](https://github.com/phpdave11/gofpdi/files/3483219/example.pdf)

Screenshot of PDF:

![example.jpg](https://user-images.githubusercontent.com/9421180/62728726-18b87500-b9e2-11e9-885c-7c68b7ac6222.jpg)


================================================
FILE: vendor/github.com/phpdave11/gofpdi/const.go
================================================
package gofpdi

const (
	PDF_TYPE_NULL = iota
	PDF_TYPE_NUMERIC
	PDF_TYPE_TOKEN
	PDF_TYPE_HEX
	PDF_TYPE_STRING
	PDF_TYPE_DICTIONARY
	PDF_TYPE_ARRAY
	PDF_TYPE_OBJDEC
	PDF_TYPE_OBJREF
	PDF_TYPE_OBJECT
	PDF_TYPE_STREAM
	PDF_TYPE_BOOLEAN
	PDF_TYPE_REAL
)


================================================
FILE: vendor/github.com/phpdave11/gofpdi/go.mod
================================================
module github.com/phpdave11/gofpdi

go 1.12

require github.com/pkg/errors v0.8.1


================================================
FILE: vendor/github.com/phpdave11/gofpdi/go.sum
================================================
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=


================================================
FILE: vendor/github.com/phpdave11/gofpdi/gofpdi.go
================================================
package gofpdi


================================================
FILE: vendor/github.com/phpdave11/gofpdi/helper.go
================================================
package gofpdi

import (
	"strings"
)

// Determine if a value is numeric
// Courtesy of https://github.com/syyongx/php2go/blob/master/php.go
func is_numeric(val interface{}) bool {
	switch val.(type) {
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
	case float32, float64, complex64, complex128:
		return true
	case string:
		str := val.(string)
		if str == "" {
			return false
		}
		// Trim any whitespace
		str = strings.TrimSpace(str)
		//fmt.Println(str)
		if str[0] == '-' || str[0] == '+' {
			if len(str) == 1 {
				return false
			}
			str = str[1:]
		}
		// hex
		if len(str) > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') {
			for _, h := range str[2:] {
				if !((h >= '0' && h <= '9') || (h >= 'a' && h <= 'f') || (h >= 'A' && h <= 'F')) {
					return false
				}
			}
			return true
		}
		// 0-9,Point,Scientific
		p, s, l := 0, 0, len(str)
		for i, v := range str {
			if v == '.' { // Point
				if p > 0 || s > 0 || i+1 == l {
					return false
				}
				p = i
			} else if v == 'e' || v == 'E' { // Scientific
				if i == 0 || s > 0 || i+1 == l {
					return false
				}
				s = i
			} else if v < '0' || v > '9' {
				return false
			}
		}
		return true
	}

	return false
}

func in_array(needle interface{}, hystack interface{}) bool {
	switch key := needle.(type) {
	case string:
		for _, item := range hystack.([]string) {
			if key == item {
				return true
			}
		}
	case int:
		for _, item := range hystack.([]int) {
			if key == item {
				return true
			}
		}
	case int64:
		for _, item := range hystack.([]int64) {
			if key == item {
				return true
			}
		}
	default:
		return false
	}
	return false
}

// Taken from png library

// intSize is either 32 or 64.
const intSize = 32 << (^uint(0) >> 63)

func abs(x int) int {
	// m := -1 if x < 0. m := 0 otherwise.
	m := x >> (intSize - 1)

	// In two's complement representation, the negative number
	// of any number (except the smallest one) can be computed
	// by flipping all the bits and add 1. This is faster than
	// code with a branch.
	// See Hacker's Delight, section 2-4.
	return (x ^ m) - m
}

// filterPaeth applies the Paeth filter to the cdat slice.
// cdat is the current row's data, pdat is the previous row's data.
func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
	var a, b, c, pa, pb, pc int
	for i := 0; i < bytesPerPixel; i++ {
		a, c = 0, 0
		for j := i; j < len(cdat); j += bytesPerPixel {
			b = int(pdat[j])
			pa = b - c
			pb = a - c
			pc = abs(pa + pb)
			pa = abs(pa)
			pb = abs(pb)
			if pa <= pb && pa <= pc {
				// No-op.
			} else if pb <= pc {
				a = b
			} else {
				a = c
			}
			a += int(cdat[j])
			a &= 0xff
			cdat[j] = uint8(a)
			c = b
		}
	}
}


================================================
FILE: vendor/github.com/phpdave11/gofpdi/importer.go
================================================
package gofpdi

import (
	"fmt"
	"io"
)

// The Importer class to be used by a pdf generation library
type Importer struct {
	sourceFile string
	readers    map[string]*PdfReader
	writers    map[string]*PdfWriter
	tplMap     map[int]*TplInfo
	tplN       int
	writer     *PdfWriter
}

type TplInfo struct {
	SourceFile string
	Writer     *PdfWriter
	TemplateId int
}

func (this *Importer) GetReader() *PdfReader {
	return this.GetReaderForFile(this.sourceFile)
}

func (this *Importer) GetWriter() *PdfWriter {
	return this.GetWriterForFile(this.sourceFile)
}

func (this *Importer) GetReaderForFile(file string) *PdfReader {
	if _, ok := this.readers[file]; ok {
		return this.readers[file]
	}

	return nil
}

func (this *Importer) GetWriterForFile(file string) *PdfWriter {
	if _, ok := this.writers[file]; ok {
		return this.writers[file]
	}

	return nil
}

func NewImporter() *Importer {
	importer := &Importer{}
	importer.init()

	return importer
}

func (this *Importer) init() {
	this.readers = make(map[string]*PdfReader, 0)
	this.writers = make(map[string]*PdfWriter, 0)
	this.tplMap = make(map[int]*TplInfo, 0)
	this.writer, _ = NewPdfWriter("")
}

func (this *Importer) SetSourceFile(f string) {
	this.sourceFile = f

	// If reader hasn't been instantiated, do that now
	if _, ok := this.readers[this.sourceFile]; !ok {
		reader, err := NewPdfReader(this.sourceFile)
		if err != nil {
			panic(err)
		}
		this.readers[this.sourceFile] = reader
	}

	// If writer hasn't been instantiated, do that now
	if _, ok := this.writers[this.sourceFile]; !ok {
		writer, err := NewPdfWriter("")
		if err != nil {
			panic(err)
		}

		// Make the next writer start template numbers at this.tplN
		writer.SetTplIdOffset(this.tplN)
		this.writers[this.sourceFile] = writer
	}
}

func (this *Importer) SetSourceStream(rs *io.ReadSeeker) {
	this.sourceFile = fmt.Sprintf("%v", rs)

	if _, ok := this.readers[this.sourceFile]; !ok {
		reader, err := NewPdfReaderFromStream(*rs)
		if err != nil {
			panic(err)
		}
		this.readers[this.sourceFile] = reader
	}

	// If writer hasn't been instantiated, do that now
	if _, ok := this.writers[this.sourceFile]; !ok {
		writer, err := NewPdfWriter("")
		if err != nil {
			panic(err)
		}

		// Make the next writer start template numbers at this.tplN
		writer.SetTplIdOffset(this.tplN)
		this.writers[this.sourceFile] = writer
	}
}

func (this *Importer) GetPageSizes() map[int]map[string]map[string]float64 {
	result, err := this.GetReader().getAllPageBoxes(1.0)

	if err != nil {
		panic(err)
	}

	return result
}

func (this *Importer) ImportPage(pageno int, box string) int {
	res, err := this.GetWriter().ImportPage(this.GetReader(), pageno, box)
	if err != nil {
		panic(err)
	}

	// Get current template id
	tplN := this.tplN

	// Set tpl info
	this.tplMap[tplN] = &TplInfo{SourceFile: this.sourceFile, TemplateId: res, Writer: this.GetWriter()}

	// Increment template id
	this.tplN++

	return tplN
}

func (this *Importer) SetNextObjectID(objId int) {
	this.GetWriter().SetNextObjectID(objId)
}

// Put form xobjects and get back a map of template names (e.g. /GOFPDITPL1) and their object ids (int)
func (this *Importer) PutFormXobjects() map[string]int {
	res := make(map[string]int, 0)
	tplNamesIds, err := this.GetWriter().PutFormXobjects(this.GetReader())
	if err != nil {
		panic(err)
	}
	for tplName, pdfObjId := range tplNamesIds {
		res[tplName] = pdfObjId.id
	}
	return res
}

// Put form xobjects and get back a map of template names (e.g. /GOFPDITPL1) and their object ids (sha1 hash)
func (this *Importer) PutFormXobjectsUnordered() map[string]string {
	this.GetWriter().SetUseHash(true)
	res := make(map[string]string, 0)
	tplNamesIds, err := this.GetWriter().PutFormXobjects(this.GetReader())
	if err != nil {
		panic(err)
	}
	for tplName, pdfObjId := range tplNamesIds {
		res[tplName] = pdfObjId.hash
	}
	return res
}

// Get object ids (int) and their contents (string)
func (this *Importer) GetImportedObjects() map[int]string {
	res := make(map[int]string, 0)
	pdfObjIdBytes := this.GetWriter().GetImportedObjects()
	for pdfObjId, bytes := range pdfObjIdBytes {
		res[pdfObjId.id] = string(bytes)
	}
	return res
}

// Get object ids (sha1 hash) and their contents ([]byte)
// The contents may have references to other object hashes which will need to be replaced by the pdf generator library
// The positions of the hashes (sha1 - 40 characters) can be obtained by calling GetImportedObjHashPos()
func (this *Importer) GetImportedObjectsUnordered() map[string][]byte {
	res := make(map[string][]byte, 0)
	pdfObjIdBytes := this.GetWriter().GetImportedObjects()
	for pdfObjId, bytes := range pdfObjIdBytes {
		res[pdfObjId.hash] = bytes
	}
	return res
}

// Get the positions of the hashes (sha1 - 40 characters) within each object, to be replaced with
// actual objects ids by the pdf generator library
func (this *Importer) GetImportedObjHashPos() map[string]map[int]string {
	res := make(map[string]map[int]string, 0)
	pdfObjIdPosHash := this.GetWriter().GetImportedObjHashPos()
	for pdfObjId, posHashMap := range pdfObjIdPosHash {
		res[pdfObjId.hash] = posHashMap
	}
	return res
}

// For a given template id (returned from ImportPage), get the template name (e.g. /GOFPDITPL1) and
// the 4 float64 values necessary to draw the template a x,y for a given width and height.
func (this *Importer) UseTemplate(tplid int, _x float64, _y float64, _w float64, _h float64) (string, float64, float64, float64, float64) {
	// Look up template id in importer tpl map
	tplInfo := this.tplMap[tplid]
	return tplInfo.Writer.UseTemplate(tplInfo.TemplateId, _x, _y, _w, _h)
}


================================================
FILE: vendor/github.com/phpdave11/gofpdi/reader.go
================================================
package gofpdi

import (
	"bufio"
	"bytes"
	"compress/zlib"
	"encoding/binary"
	"fmt"
	"github.com/pkg/errors"
	"io"
	"io/ioutil"
	"math"
	"os"
	"strconv"
)

type PdfReader struct {
	availableBoxes []string
	stack          []string
	trailer        *PdfValue
	catalog        *PdfValue
	pages          []*PdfValue
	xrefPos        int
	xref           map[int]map[int]int
	xrefStream     map[int][2]int
	f              io.ReadSeeker
	nBytes         int64
	sourceFile     string
}

func NewPdfReaderFromStream(rs io.ReadSeeker) (*PdfReader, error) {
	length, err := rs.Seek(0, 2)
	if err != nil {
		return nil, errors.Wrapf(err, "Failed to determine stream length")
	}
	parser := &PdfReader{f: rs, nBytes: length}
	if err := parser.init(); err != nil {
		return nil, errors.Wrap(err, "Failed to initialize parser")
	}
	if err := parser.read(); err != nil {
		return nil, errors.Wrap(err, "Failed to read pdf from stream")
	}
	return parser, nil
}

func NewPdfReader(filename string) (*PdfReader, error) {
	var err error
	f, err := os.Open(filename)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to open file")
	}
	info, err := f.Stat()
	if err != nil {
		return nil, errors.Wrap(err, "Failed to obtain file information")
	}

	parser := &PdfReader{f: f, sourceFile: filename, nBytes: info.Size()}
	if err = parser.init(); err != nil {
		return nil, errors.Wrap(err, "Failed to initialize parser")
	}
	if err = parser.read(); err != nil {
		return nil, errors.Wrap(err, "Failed to read pdf")
	}

	return parser, nil
}

func (this *PdfReader) init() error {
	this.availableBoxes = []string{"/MediaBox", "/CropBox", "/BleedBox", "/TrimBox", "/ArtBox"}
	this.xref = make(map[int]map[int]int, 0)
	this.xrefStream = make(map[int][2]int, 0)
	err := this.read()
	if err != nil {
		return errors.Wrap(err, "Failed to read pdf")
	}
	return nil
}

type PdfValue struct {
	Type       int
	String     string
	Token      string
	Int        int
	Real       float64
	Bool       bool
	Dictionary map[string]*PdfValue
	Array      []*PdfValue
	Id         int
	NewId      int
	Gen        int
	Value      *PdfValue
	Stream     *PdfValue
	Bytes      []byte
}

// Jump over comments
func (this *PdfReader) skipComments(r *bufio.Reader) error {
	var err error
	var b byte

	for {
		b, err = r.ReadByte()
		if err != nil {
			return errors.Wrap(err, "Failed to ReadByte while skipping comments")
		}

		if b == '\n' || b == '\r' {
			if b == '\r' {
				// Peek and see if next char is \n
				b2, err := r.ReadByte()
				if err != nil {
					return errors.Wrap(err, "Failed to read byte")
				}
				if b2 != '\n' {
					r.UnreadByte()
				}
			}
			break
		}
	}

	return nil
}

// Advance reader so that whitespace is ignored
func (this *PdfReader) skipWhitespace(r *bufio.Reader) error {
	var err error
	var b byte

	for {
		b, err = r.ReadByte()
		if err != nil {
			if err == io.EOF {
				break
			}
			return errors.Wrap(err, "Failed to read byte")
		}

		if b == ' ' || b == '\n' || b == '\r' || b == '\t' {
			continue
		} else {
			r.UnreadByte()
			break
		}
	}

	return nil
}

// Read a token
func (this *PdfReader) readToken(r *bufio.Reader) (string, error) {
	var err error

	// If there is a token available on the stack, pop it out and return it.
	if len(this.stack) > 0 {
		var popped string
		popped, this.stack = this.stack[len(this.stack)-1], this.stack[:len(this.stack)-1]
		return popped, nil
	}

	err = this.skipWhitespace(r)
	if err != nil {
		return "", errors.Wrap(err, "Failed to skip whitespace")
	}

	b, err := r.ReadByte()
	if err != nil {
		if err == io.EOF {
			return "", nil
		}
		return "", errors.Wrap(err, "Failed to read byte")
	}

	switch b {
	case '[', ']', '(', ')':
		// This is either an array or literal string delimeter, return it.
		return string(b), nil

	case '<', '>':
		// This could either be a hex string or a dictionary delimiter.
		// Determine the appropriate case and return the token.
		nb, err := r.ReadByte()
		if err != nil {
			return "", errors.Wrap(err, "Failed to read byte")
		}
		if nb == b {
			return string(b) + string(nb), nil
		} else {
			r.UnreadByte()
			return string(b), nil
		}

	case '%':
		err = this.skipComments(r)
		if err != nil {
			return "", errors.Wrap(err, "Failed to skip comments")
		}
		return this.readToken(r)

	default:
		// FIXME this may not be performant to create new strings for each byte
		// Is it probably better to create a buffer and then convert to a string at the end.
		str := string(b)

	loop:
		for {
			b, err := r.ReadByte()
			if err != nil {
				return "", errors.Wrap(err, "Failed to read byte")
			}
			switch b {
			case ' ', '%', '[', ']', '<', '>', '(', ')', '\r', '\n', '\t', '/':
				r.UnreadByte()
				break loop
			default:
				str += string(b)
			}
		}
		return str, nil
	}

	return "", nil
}

// Read a value based on a token
func (this *PdfReader) readValue(r *bufio.Reader, t string) (*PdfValue, error) {
	var err error
	var b byte

	result := &PdfValue{}
	result.Type = -1
	result.Token = t
	result.Dictionary = make(map[string]*PdfValue, 0)
	result.Array = make([]*PdfValue, 0)

	switch t {
	case "<":
		// This is a hex string

		// Read bytes until '>' is found
		var s string
		for {
			b, err = r.ReadByte()
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read byte")
			}
			if b != '>' {
				s += string(b)
			} else {
				break
			}
		}

		result.Type = PDF_TYPE_HEX
		result.String = s

	case "<<":
		// This is a dictionary

		// Recurse into this function until we reach the end of the dictionary.
		for {
			key, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if key == "" {
				return nil, errors.New("Token is empty")
			}

			if key == ">>" {
				break
			}

			// read next token
			newKey, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}

			value, err := this.readValue(r, newKey)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read value for token: "+newKey)
			}

			if value.Type == -1 {
				return result, nil
			}

			// Catch missing value
			if value.Type == PDF_TYPE_TOKEN && value.String == ">>" {
				result.Type = PDF_TYPE_NULL
				result.Dictionary[key] = value
				break
			}

			// Set value in dictionary
			result.Dictionary[key] = value
		}

		result.Type = PDF_TYPE_DICTIONARY
		return result, nil

	case "[":
		// This is an array

		tmpResult := make([]*PdfValue, 0)

		// Recurse into this function until we reach the end of the array
		for {
			key, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if key == "" {
				return nil, errors.New("Token is empty")
			}

			if key == "]" {
				break
			}

			value, err := this.readValue(r, key)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read value for token: "+key)
			}

			if value.Type == -1 {
				return result, nil
			}

			tmpResult = append(tmpResult, value)
		}

		result.Type = PDF_TYPE_ARRAY
		result.Array = tmpResult

	case "(":
		// This is a string

		openBrackets := 1

		// Create new buffer
		var buf bytes.Buffer

		// Read bytes until brackets are balanced
		for openBrackets > 0 {
			b, err := r.ReadByte()

			if err != nil {
				return nil, errors.Wrap(err, "Failed to read byte")
			}

			switch b {
			case '(':
				openBrackets++

			case ')':
				openBrackets--

			case '\\':
				nb, err := r.ReadByte()
				if err != nil {
					return nil, errors.Wrap(err, "Failed to read byte")
				}

				buf.WriteByte(b)
				buf.WriteByte(nb)

				continue
			}

			if openBrackets > 0 {
				buf.WriteByte(b)
			}
		}

		result.Type = PDF_TYPE_STRING
		result.String = buf.String()

	case "stream":
		return nil, errors.New("Stream not implemented")

	default:
		result.Type = PDF_TYPE_TOKEN
		result.Token = t

		if is_numeric(t) {
			// A numeric token.  Make sure that it is not part of something else
			t2, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if t2 != "" {
				if is_numeric(t2) {
					// Two numeric tokens in a row.
					// In this case, we're probably in front of either an object reference
					// or an object specification.
					// Determine the case and return the data.
					t3, err := this.readToken(r)
					if err != nil {
						return nil, errors.Wrap(err, "Failed to read token")
					}

					if t3 != "" {
						switch t3 {
						case "obj":
							result.Type = PDF_TYPE_OBJDEC
							result.Id, _ = strconv.Atoi(t)
							result.Gen, _ = strconv.Atoi(t2)
							return result, nil

						case "R":
							result.Type = PDF_TYPE_OBJREF
							result.Id, _ = strconv.Atoi(t)
							result.Gen, _ = strconv.Atoi(t2)
							return result, nil
						}

						// If we get to this point, that numeric value up there was just a numeric value.
						// Push the extra tokens back into the stack and return the value.
						this.stack = append(this.stack, t3)
					}
				}

				this.stack = append(this.stack, t2)
			}

			if n, err := strconv.Atoi(t); err == nil {
				result.Type = PDF_TYPE_NUMERIC
				result.Int = n
				result.Real = float64(n) // Also assign Real value here to fix page box parsing bugs
			} else {
				result.Type = PDF_TYPE_REAL
				result.Real, _ = strconv.ParseFloat(t, 64)
			}
		} else if t == "true" || t == "false" {
			result.Type = PDF_TYPE_BOOLEAN
			result.Bool = t == "true"
		} else if t == "null" {
			result.Type = PDF_TYPE_NULL
		} else {
			result.Type = PDF_TYPE_TOKEN
			result.Token = t
		}
	}

	return result, nil
}

// Resolve a compressed object (PDF 1.5)
func (this *PdfReader) resolveCompressedObject(objSpec *PdfValue) (*PdfValue, error) {
	var err error

	// Make sure object reference exists in xrefStream
	if _, ok := this.xrefStream[objSpec.Id]; !ok {
		return nil, errors.New(fmt.Sprintf("Could not find object ID %d in xref stream or xref table.", objSpec.Id))
	}

	// Get object id and index
	objectId := this.xrefStream[objSpec.Id][0]
	objectIndex := this.xrefStream[objSpec.Id][1]

	// Read compressed object
	compressedObjSpec := &PdfValue{Type: PDF_TYPE_OBJREF, Id: objectId, Gen: 0}

	// Resolve compressed object
	compressedObj, err := this.resolveObject(compressedObjSpec)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to resolve compressed object")
	}

	// Verify object type is /ObjStm
	if _, ok := compressedObj.Value.Dictionary["/Type"]; ok {
		if compressedObj.Value.Dictionary["/Type"].Token != "/ObjStm" {
			return nil, errors.New("Expected compressed object type to be /ObjStm")
		}
	} else {
		return nil, errors.New("Could not determine compressed object type.")
	}

	// Get number of sub-objects in compressed object
	n := compressedObj.Value.Dictionary["/N"].Int
	if n <= 0 {
		return nil, errors.New("No sub objects in compressed object")
	}

	// Get offset of first object
	first := compressedObj.Value.Dictionary["/First"].Int

	// Get length
	//length := compressedObj.Value.Dictionary["/Length"].Int

	// Check for filter
	filter := ""
	if _, ok := compressedObj.Value.Dictionary["/Filter"]; ok {
		filter = compressedObj.Value.Dictionary["/Filter"].Token
		if filter != "/FlateDecode" {
			return nil, errors.New("Unsupported filter - expected /FlateDecode, got: " + filter)
		}
	}

	if filter == "/FlateDecode" {
		// Decompress if filter is /FlateDecode
		// Uncompress zlib compressed data
		var out bytes.Buffer
		zlibReader, _ := zlib.NewReader(bytes.NewBuffer(compressedObj.Stream.Bytes))
		defer zlibReader.Close()
		io.Copy(&out, zlibReader)

		// Set stream to uncompressed data
		compressedObj.Stream.Bytes = out.Bytes()
	}

	// Get io.Reader for bytes
	r := bufio.NewReader(bytes.NewBuffer(compressedObj.Stream.Bytes))

	subObjId := 0
	subObjPos := 0

	// Read sub-object indeces and their positions within the (un)compressed object
	for i := 0; i < n; i++ {
		var token string
		var _objidx int
		var _objpos int

		// Read first token (object index)
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}

		// Convert line (string) into int
		_objidx, err = strconv.Atoi(token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to convert token into integer: "+token)
		}

		// Read first token (object index)
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}

		// Convert line (string) into int
		_objpos, err = strconv.Atoi(token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to convert token into integer: "+token)
		}

		if i == objectIndex {
			subObjId = _objidx
			subObjPos = _objpos
		}
	}

	// Now create an io.ReadSeeker
	rs := io.ReadSeeker(bytes.NewReader(compressedObj.Stream.Bytes))

	// Determine where to seek to (sub-object position + /First)
	seekTo := int64(subObjPos + first)

	// Fast forward to the object
	rs.Seek(seekTo, 0)

	// Create a new io.Reader
	r = bufio.NewReader(rs)

	// Read token
	token, err := this.readToken(r)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to read token")
	}

	// Read object
	obj, err := this.readValue(r, token)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to read value for token: "+token)
	}

	result := &PdfValue{}
	result.Id = subObjId
	result.Gen = 0
	result.Type = PDF_TYPE_OBJECT
	result.Value = obj

	return result, nil
}

func (this *PdfReader) resolveObject(objSpec *PdfValue) (*PdfValue, error) {
	var err error
	var old_pos int64

	// Create new bufio.Reader
	r := bufio.NewReader(this.f)

	if objSpec.Type == PDF_TYPE_OBJREF {
		// This is a reference, resolve it.
		offset := this.xref[objSpec.Id][objSpec.Gen]

		if _, ok := this.xref[objSpec.Id]; !ok {
			// This may be a compressed object
			return this.resolveCompressedObject(objSpec)
		}

		// Save current file position
		// This is needed if you want to resolve reference while you're reading another object.
		// (e.g.: if you need to determine the length of a stream)
		old_pos, err = this.f.Seek(0, os.SEEK_CUR)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to get current position of file")
		}

		// Reposition the file pointer and load the object header
		_, err = this.f.Seek(int64(offset), 0)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to set position of file")
		}

		token, err := this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}

		obj, err := this.readValue(r, token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read value for token: "+token)
		}

		if obj.Type != PDF_TYPE_OBJDEC {
			return nil, errors.New(fmt.Sprintf("Expected type to be PDF_TYPE_OBJDEC, got: %d", obj.Type))
		}

		if obj.Id != objSpec.Id {
			return nil, errors.New(fmt.Sprintf("Object ID (%d) does not match ObjSpec ID (%d)", obj.Id, objSpec.Id))
		}

		if obj.Gen != objSpec.Gen {
			return nil, errors.New("Object Gen does not match ObjSpec Gen")
		}

		// Read next token
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}

		// Read actual object value
		value, err := this.readValue(r, token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read value for token: "+token)
		}

		// Read next token
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}

		result := &PdfValue{}
		result.Id = obj.Id
		result.Gen = obj.Gen
		result.Type = PDF_TYPE_OBJECT
		result.Value = value

		if token == "stream" {
			result.Type = PDF_TYPE_STREAM

			err = this.skipWhitespace(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to skip whitespace")
			}

			// Get stream length dictionary
			lengthDict := value.Dictionary["/Length"]

			// Get number of bytes of stream
			length := lengthDict.Int

			// If lengthDict is an object reference, resolve the object and set length
			if lengthDict.Type == PDF_TYPE_OBJREF {
				lengthDict, err = this.resolveObject(lengthDict)

				if err != nil {
					return nil, errors.Wrap(err, "Failed to resolve length object of stream")
				}

				// Set length to resolved object value
				length = lengthDict.Value.Int
			}

			// Read length bytes
			bytes := make([]byte, length)

			// Cannot use reader.Read() because that may not read all the bytes
			_, err := io.ReadFull(r, bytes)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read bytes from buffer")
			}

			token, err = this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if token != "endstream" {
				return nil, errors.New("Expected next token to be: endstream, got: " + token)
			}

			token, err = this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}

			streamObj := &PdfValue{}
			streamObj.Type = PDF_TYPE_STREAM
			streamObj.Bytes = bytes

			result.Stream = streamObj
		}

		if token != "endobj" {
			return nil, errors.New("Expected next token to be: endobj, got: " + token)
		}

		// Reposition the file pointer to previous position
		_, err = this.f.Seek(old_pos, 0)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to set position of file")
		}

		return result, nil

	} else {
		return objSpec, nil
	}

	return &PdfValue{}, nil
}

// Find the xref offset (should be at the end of the PDF)
func (this *PdfReader) findXref() error {
	var result int
	var err error
	var toRead int64

	toRead = 1500

	// If PDF is smaller than 1500 bytes, be sure to only read the number of bytes that are in the file
	fileSize := this.nBytes
	if fileSize < toRead {
		toRead = fileSize
	}

	// 0 means relative to the origin of the file,
	// 1 means relative to the current offset,
	// and 2 means relative to the end.
	whence := 2

	// Perform seek operation
	_, err = this.f.Seek(-toRead, whence)
	if err != nil {
		return errors.Wrap(err, "Failed to set position of file")
	}

	// Create new bufio.Reader
	r := bufio.NewReader(this.f)
	for {
		// Read all tokens until "startxref" is found
		token, err := this.readToken(r)
		if err != nil {
			return errors.Wrap(err, "Failed to read token")
		}

		if token == "startxref" {
			token, err = this.readToken(r)
			// Probably EOF before finding startxref
			if err != nil {
				return errors.Wrap(err, "Failed to find startxref token")
			}

			// Convert line (string) into int
			result, err = strconv.Atoi(token)
			if err != nil {
				return errors.Wrap(err, "Failed to convert xref position into integer: "+token)
			}

			// Successfully read the xref position
			this.xrefPos = result
			break
		}
	}

	// Rewind file pointer
	whence = 0
	_, err = this.f.Seek(0, whence)
	if err != nil {
		return errors.Wrap(err, "Failed to set position of file")
	}

	this.xrefPos = result

	return nil
}

// Read and parse the xref table
func (this *PdfReader) readXref() error {
	var err error

	// Create new bufio.Reader
	r := bufio.NewReader(this.f)

	// Set file pointer to xref start
	_, err = this.f.Seek(int64(this.xrefPos), 0)
	if err != nil {
		return errors.Wrap(err, "Failed to set position of file")
	}

	// Xref should start with 'xref'
	t, err := this.readToken(r)
	if err != nil {
		return errors.Wrap(err, "Failed to read token")
	}
	if t != "xref" {
		// Maybe this is an XRef stream ...
		v, err := this.readValue(r, t)
		if err != nil {
			return errors.Wrap(err, "Failed to read XRef stream")
		}

		if v.Type == PDF_TYPE_OBJDEC {
			// Read next token
			t, err = this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}

			// Read actual object value
			v, err := this.readValue(r, t)
			if err != nil {
				return errors.Wrap(err, "Failed to read value for token: "+t)
			}

			// If /Type is set, check to see if it is XRef
			if _, ok := v.Dictionary["/Type"]; ok {
				if v.Dictionary["/Type"].Token == "/XRef" {
					// Continue reading xref stream data now that it is confirmed that it is an xref stream

					// Check for /DecodeParms
					paethDecode := false
					if _, ok := v.Dictionary["/DecodeParms"]; ok {
						columns := 0
						predictor := 0

						if _, ok2 := v.Dictionary["/DecodeParms"].Dictionary["/Columns"]; ok2 {
							columns = v.Dictionary["/DecodeParms"].Dictionary["/Columns"].Int
						}
						if _, ok2 := v.Dictionary["/DecodeParms"].Dictionary["/Predictor"]; ok2 {
							predictor = v.Dictionary["/DecodeParms"].Dictionary["/Predictor"].Int
						}

						if columns != 4 || predictor != 12 {
							return errors.New("Unsupported /DecodeParms - only tested with /Columns 4 /Predictor 12")
						}
						paethDecode = true
					}

					// Check to make sure field size is [1 2 1] - not yet tested with other field sizes
					if v.Dictionary["/W"].Array[0].Int != 1 || v.Dictionary["/W"].Array[1].Int > 4 || v.Dictionary["/W"].Array[2].Int != 1 {
						return errors.New(fmt.Sprintf("Unsupported field sizes in cross-reference stream dictionary: /W [%d %d %d]",
							v.Dictionary["/W"].Array[0].Int,
							v.Dictionary["/W"].Array[1].Int,
							v.Dictionary["/W"].Array[2].Int))
					}

					index := make([]int, 2)

					// If /Index is not set, this is an error
					if _, ok := v.Dictionary["/Index"]; ok {
						if len(v.Dictionary["/Index"].Array) < 2 {
							return errors.Wrap(err, "Index array does not contain 2 elements")
						}

						index[0] = v.Dictionary["/Index"].Array[0].Int
						index[1] = v.Dictionary["/Index"].Array[1].Int
					} else {
						index[0] = 0
					}

					prevXref := 0

					// Check for previous xref stream
					if _, ok := v.Dictionary["/Prev"]; ok {
						prevXref = v.Dictionary["/Prev"].Int
					}

					// Set root object
					if _, ok := v.Dictionary["/Root"]; ok {
						// Just set the whole dictionary with /Root key to keep compatibiltiy with existing code
						this.trailer = v
					} else {
						// Don't return an error here.  The trailer could be in another XRef stream.
						//return errors.New("Did not set root object")
					}

					startObject := index[0]

					err = this.skipWhitespace(r)
					if err != nil {
						return errors.Wrap(err, "Failed to skip whitespace")
					}

					// Get stream length dictionary
					lengthDict := v.Dictionary["/Length"]

					// Get number of bytes of stream
					length := lengthDict.Int

					// If lengthDict is an object reference, resolve the object and set length
					if lengthDict.Type == PDF_TYPE_OBJREF {
						lengthDict, err = this.resolveObject(lengthDict)

						if err != nil {
							return errors.Wrap(err, "Failed to resolve length object of stream")
						}

						// Set length to resolved object value
						length = lengthDict.Value.Int
					}

					t, err = this.readToken(r)
					if err != nil {
						return errors.Wrap(err, "Failed to read token")
					}
					if t != "stream" {
						return errors.New("Expected next token to be: stream, got: " + t)
					}

					err = this.skipWhitespace(r)
					if err != nil {
						return errors.Wrap(err, "Failed to skip whitespace")
					}

					// Read length bytes
					data := make([]byte, length)

					// Cannot use reader.Read() because that may not read all the bytes
					_, err := io.ReadFull(r, data)
					if err != nil {
						return errors.Wrap(err, "Failed to read bytes from buffer")
					}

					// Look for endstream token
					t, err = this.readToken(r)
					if err != nil {
						return errors.Wrap(err, "Failed to read token")
					}
					if t != "endstream" {
						return errors.New("Expected next token to be: endstream, got: " + t)
					}

					// Look for endobj token
					t, err = this.readToken(r)
					if err != nil {
						return errors.Wrap(err, "Failed to read token")
					}
					if t != "endobj" {
						return errors.New("Expected next token to be: endobj, got: " + t)
					}

					// Now decode zlib data
					b := bytes.NewReader(data)

					z, err := zlib.NewReader(b)
					if err != nil {
						return errors.Wrap(err, "zlib.NewReader error")
					}
					defer z.Close()

					p, err := ioutil.ReadAll(z)
					if err != nil {
						return errors.Wrap(err, "ioutil.ReadAll error")
					}

					objPos := 0
					objGen := 0
					i := startObject

					// Decode result with paeth algorithm
					var result []byte
					b = bytes.NewReader(p)

					firstFieldSize := v.Dictionary["/W"].Array[0].Int
					middleFieldSize := v.Dictionary["/W"].Array[1].Int
					lastFieldSize := v.Dictionary["/W"].Array[2].Int

					fieldSize := firstFieldSize + middleFieldSize + lastFieldSize
					if paethDecode {
						fieldSize++
					}

					prevRow := make([]byte, fieldSize)
					for {
						result = make([]byte, fieldSize)
						_, err := io.ReadFull(b, result)
						if err != nil {
							if err == io.EOF {
								break
							} else {
								return errors.Wrap(err, "io.ReadFull error")
							}
						}

						if paethDecode {
							filterPaeth(result, prevRow, fieldSize)
							copy(prevRow, result)
						}

						objectData := make([]byte, fieldSize)
						if paethDecode {
							copy(objectData, result[1:fieldSize])
						} else {
							copy(objectData, result[0:fieldSize])
						}

						if objectData[0] == 1 {
							// Regular objects
							b := make([]byte, 4)
							copy(b[4-middleFieldSize:], objectData[1:1+middleFieldSize])

							objPos = int(binary.BigEndian.Uint32(b))
							objGen = int(objectData[firstFieldSize+middleFieldSize])

							// Append map[int]int
							this.xref[i] = make(map[int]int, 1)

							// Set object id, generation, and position
							this.xref[i][objGen] = objPos
						} else if objectData[0] == 2 {
							// Compressed objects
							b := make([]byte, 4)
							copy(b[4-middleFieldSize:], objectData[1:1+middleFieldSize])

							objId := int(binary.BigEndian.Uint32(b))
							objIdx := int(objectData[firstFieldSize+middleFieldSize])

							// object id (i) is located in StmObj (objId) at index (objIdx)
							this.xrefStream[i] = [2]int{objId, objIdx}
						}

						i++
					}

					// Check for previous xref stream
					if prevXref > 0 {
						// Set xrefPos to /Prev xref
						this.xrefPos = prevXref

						// Read preivous xref
						xrefErr := this.readXref()
						if xrefErr != nil {
							return errors.Wrap(xrefErr, "Failed to read prev xref")
						}
					}
				}
			}

			return nil
		}

		return errors.New("Expected xref to start with 'xref'.  Got: " + t)
	}

	for {
		// Next value will be the starting object id (usually 0, but not always) or the trailer
		t, err = this.readToken(r)
		if err != nil {
			return errors.Wrap(err, "Failed to read token")
		}

		// Check for trailer
		if t == "trailer" {
			break
		}

		// Convert token to int
		startObject, err := strconv.Atoi(t)
		if err != nil {
			return errors.Wrap(err, "Failed to convert start object to integer: "+t)
		}

		// Determine how many objects there are
		t, err = this.readToken(r)
		if err != nil {
			return errors.Wrap(err, "Failed to read token")
		}

		// Convert token to int
		numObject, err := strconv.Atoi(t)
		if err != nil {
			return errors.Wrap(err, "Failed to convert num object to integer: "+t)
		}

		// For all objects in xref, read object position, object generation, and status (free or new)
		for i := startObject; i < startObject+numObject; i++ {
			t, err = this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}

			// Get object position as int
			objPos, err := strconv.Atoi(t)
			if err != nil {
				return errors.Wrap(err, "Failed to convert object position to integer: "+t)
			}

			t, err = this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}

			// Get object generation as int
			objGen, err := strconv.Atoi(t)
			if err != nil {
				return errors.Wrap(err, "Failed to convert object generation to integer: "+t)
			}

			// Get object status (free or new)
			objStatus, err := this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}
			if objStatus != "f" && objStatus != "n" {
				return errors.New("Expected objStatus to be 'n' or 'f', got: " + objStatus)
			}

			// Append map[int]int
			this.xref[i] = make(map[int]int, 1)

			// Set object id, generation, and position
			this.xref[i][objGen] = objPos
		}
	}

	// Read trailer dictionary
	t, err = this.readToken(r)
	if err != nil {
		return errors.Wrap(err, "Failed to read token")
	}

	trailer, err := this.readValue(r, t)
	if err != nil {
		return errors.Wrap(err, "Failed to read value for token: "+t)
	}

	// If /Root is set, then set trailer object so that /Root can be read later
	if _, ok := trailer.Dictionary["/Root"]; ok {
		this.trailer = trailer
	}

	// If a /Prev xref trailer is specified, parse that
	if tr, ok := trailer.Dictionary["/Prev"]; ok {
		// Resolve parent xref table
		this.xrefPos = tr.Int
		return this.readXref()
	}

	return nil
}

// Read root (catalog object)
func (this *PdfReader) readRoot() error {
	var err error

	rootObjSpec := this.trailer.Dictionary["/Root"]

	// Read root (catalog)
	this.catalog, err = this.resolveObject(rootObjSpec)
	if err != nil {
		return errors.Wrap(err, "Failed to resolve root object")
	}

	return nil
}

// Read all pages in PDF
func (this *PdfReader) readPages() error {
	var err error

	// resolve_pages_dict
	pagesDict, err := this.resolveObject(this.catalog.Value.Dictionary["/Pages"])
	if err != nil {
		return errors.Wrap(err, "Failed to resolve pages object")
	}

	// This will normally return itself
	kids, err := this.resolveObject(pagesDict.Value.Dictionary["/Kids"])
	if err != nil {
		return errors.Wrap(err, "Failed to resolve kids object")
	}

	// Allocate pages
	this.pages = make([]*PdfValue, len(kids.Array))

	// Loop through pages and add to result
	for i := 0; i < len(kids.Array); i++ {
		page, err := this.resolveObject(kids.Array[i])
		if err != nil {
			return errors.Wrap(err, "Failed to resolve kid object")
		}

		// Set page
		this.pages[i] = page
	}

	return nil
}

// Get references to page resources for a given page number
func (this *PdfReader) getPageResources(pageno int) (*PdfValue, error) {
	var err error

	// Check to make sure page exists in pages slice
	if len(this.pages) < pageno {
		return nil, errors.New(fmt.Sprintf("Page %d does not exist!!", pageno))
	}

	// Resolve page object
	page, err := this.resolveObject(this.pages[pageno-1])
	if err != nil {
		return nil, errors.Wrap(err, "Failed to resolve page object")
	}

	// Check to see if /Resources exists in Dictionary
	if _, ok := page.Value.Dictionary["/Resources"]; ok {
		// Resolve /Resources object
		res, err := this.resolveObject(page.Value.Dictionary["/Resources"])
		if err != nil {
			return nil, errors.Wrap(err, "Failed to resolve resources object")
		}

		// If type is PDF_TYPE_OBJECT, return its Value
		if res.Type == PDF_TYPE_OBJECT {
			return res.Value, nil
		}

		// Otherwise, returned the resolved object
		return res, nil
	} else {
		// If /Resources does not exist, check to see if /Parent exists and return that
		if _, ok := page.Value.Dictionary["/Parent"]; ok {
			// Resolve parent object
			res, err := this.resolveObject(page.Value.Dictionary["/Parent"])
			if err != nil {
				return nil, errors.Wrap(err, "Failed to resolve parent object")
			}

			// If /Parent object type is PDF_TYPE_OBJECT, return its Value
			if res.Type == PDF_TYPE_OBJECT {
				return res.Value, nil
			}

			// Otherwise, return the resolved parent object
			return res, nil
		}
	}

	// Return an empty PdfValue if we got here
	// TODO:  Improve error handling
	return &PdfValue{}, nil
}

// Get page content and return a slice of PdfValue objects
func (this *PdfReader) getPageContent(objSpec *PdfValue) ([]*PdfValue, error) {
	var err error
	var content *PdfValue

	// Allocate slice
	contents := make([]*PdfValue, 0)

	if objSpec.Type == PDF_TYPE_OBJREF {
		// If objSpec is an object reference, resolve the object and append it to contents
		content, err = this.resolveObject(objSpec)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to resolve object")
		}
		contents = append(contents, content)
	} else if objSpec.Type == PDF_TYPE_ARRAY {
		// If objSpec is an array, loop through the array and recursively get page content and append to contents
		for i := 0; i < len(objSpec.Array); i++ {
			tmpContents, err := this.getPageContent(objSpec.Array[i])
			if err != nil {
				return nil, errors.Wrap(err, "Failed to get page content")
			}
			for j := 0; j < len(tmpContents); j++ {
				contents = append(contents, tmpContents[j])
			}
		}
	}

	return contents, nil
}

// Get content (i.e. PDF drawing instructions)
func (this *PdfReader) getContent(pageno int) (string, error) {
	var err error
	var contents []*PdfValue

	// Check to make sure page exists in pages slice
	if len(this.pages) < pageno {
		return "", errors.New(fmt.Sprintf("Page %d does not exist.", pageno))
	}

	// Get page
	page := this.pages[pageno-1]

	// FIXME: This could be slow, converting []byte to string and appending many times
	buffer := ""

	// Check to make sure /Contents exists in page dictionary
	if _, ok := page.Value.Dictionary["/Contents"]; ok {
		// Get an array of page content
		contents, err = this.getPageContent(page.Value.Dictionary["/Contents"])
		if err != nil {
			return "", errors.Wrap(err, "Failed to get page content")
		}

		for i := 0; i < len(contents); i++ {
			// Decode content if one or more /Filter is specified.
			// Most common filter is FlateDecode which can be uncompressed with zlib
			tmpBuffer, err := this.rebuildContentStream(contents[i])
			if err != nil {
				return "", errors.Wrap(err, "Failed to rebuild content stream")
			}

			// FIXME:  This is probably slow
			buffer += string(tmpBuffer)
		}
	}

	return buffer, nil
}

// Rebuild content stream
// This will decode content if one or more /Filter (such as FlateDecode) is specified.
// If there are multiple filters, they will be decoded in the order in which they were specified.
func (this *PdfReader) rebuildContentStream(content *PdfValue) ([]byte, error) {
	var err error
	var tmpFilter *PdfValue

	// Allocate slice of PdfValue
	filters := make([]*PdfValue, 0)

	// If content has a /Filter, append it to filters slice
	if _, ok := content.Value.Dictionary["/Filter"]; ok {
		filter := content.Value.Dictionary["/Filter"]

		// If filter type is a reference, resolve it
		if filter.Type == PDF_TYPE_OBJREF {
			tmpFilter, err = this.resolveObject(filter)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to resolve object")
			}
			filter = tmpFilter.Value
		}

		if filter.Type == PDF_TYPE_TOKEN {
			// If filter type is a token (e.g. FlateDecode), appent it to filters slice
			filters = append(filters, filter)
		} else if filter.Type == PDF_TYPE_ARRAY {
			// If filter type is an array, then there are multiple filters.  Set filters variable to array value.
			filters = filter.Array
		}

	}

	// Set stream variable to content bytes
	stream := content.Stream.Bytes

	// Loop through filters and apply each filter to stream
	for i := 0; i < len(filters); i++ {
		switch filters[i].Token {
		case "/FlateDecode":
			// Uncompress zlib compressed data
			var out bytes.Buffer
			zlibReader, _ := zlib.NewReader(bytes.NewBuffer(stream))
			defer zlibReader.Close()
			io.Copy(&out, zlibReader)

			// Set stream to uncompressed data
			stream = out.Bytes()
		default:
			return nil, errors.New("Unspported filter: " + filters[i].Token)
		}
	}

	return stream, nil
}

func (this *PdfReader) getAllPageBoxes(k float64) (map[int]map[string]map[string]float64, error) {
	var err error

	// Allocate result with the number of available boxes
	result := make(map[int]map[string]map[string]float64, len(this.pages))

	for i := 1; i <= len(this.pages); i++ {
		result[i], err = this.getPageBoxes(i, k)
		if result[i] == nil {
			return nil, errors.Wrap(err, "Unable to get page box")
		}
	}

	return result, nil
}

// Get all page box data
func (this *PdfReader) getPageBoxes(pageno int, k float64) (map[string]map[string]float64, error) {
	var err error

	// Allocate result with the number of available boxes
	result := make(map[string]map[string]float64, len(this.availableBoxes))

	// Check to make sure page exists in pages slice
	if len(this.pages) < pageno {
		return nil, errors.New(fmt.Sprintf("Page %d does not exist?", pageno))
	}

	// Resolve page object
	page, err := this.resolveObject(this.pages[pageno-1])
	if err != nil {
		return nil, errors.New("Failed to resolve page object")
	}

	// Loop through available boxes and add to result
	for i := 0; i < len(this.availableBoxes); i++ {
		box, err := this.getPageBox(page, this.availableBoxes[i], k)
		if err != nil {
			return nil, errors.New("Failed to get page box")
		}

		result[this.availableBoxes[i]] = box
	}

	return result, nil
}

// Get a specific page box value (e.g. MediaBox) and return its values
func (this *PdfReader) getPageBox(page *PdfValue, box_index string, k float64) (map[string]float64, error) {
	var err error
	var tmpBox *PdfValue

	// Allocate 8 fields in result
	result := make(map[string]float64, 8)

	// Check to make sure box_index (e.g. MediaBox) exists in page dictionary
	if _, ok := page.Value.Dictionary[box_index]; ok {
		box := page.Value.Dictionary[box_index]

		// If the box type is a reference, resolve it
		if box.Type == PDF_TYPE_OBJREF {
			tmpBox, err = this.resolveObject(box)
			if err != nil {
				return nil, errors.New("Failed to resolve object")
			}
			box = tmpBox.Value
		}

		if box.Type == PDF_TYPE_ARRAY {
			// If the box type is an array, calculate scaled value based on k
			result["x"] = box.Array[0].Real / k
			result["y"] = box.Array[1].Real / k
			result["w"] = math.Abs(box.Array[0].Real-box.Array[2].Real) / k
			result["h"] = math.Abs(box.Array[1].Real-box.Array[3].Real) / k
			result["llx"] = math.Min(box.Array[0].Real, box.Array[2].Real)
			result["lly"] = math.Min(box.Array[1].Real, box.Array[3].Real)
			result["urx"] = math.Max(box.Array[0].Real, box.Array[2].Real)
			result["ury"] = math.Max(box.Array[1].Real, box.Array[3].Real)
		} else {
			// TODO: Improve error handling
			return nil, errors.New("Could not get page box")
		}
	} else if _, ok := page.Value.Dictionary["/Parent"]; ok {
		parentObj, err := this.resolveObject(page.Value.Dictionary["/Parent"])
		if err != nil {
			return nil, errors.Wrap(err, "Could not resolve parent object")
		}

		// If the page box is inherited from /Parent, recursively return page box of parent
		return this.getPageBox(parentObj, box_index, k)
	}

	return result, nil
}

// Get page rotation for a page number
func (this *PdfReader) getPageRotation(pageno int) (*PdfValue, error) {
	// Check to make sure page exists in pages slice
	if len(this.pages) < pageno {
		return nil, errors.New(fmt.Sprintf("Page %d does not exist!!!!", pageno))
	}

	return this._getPageRotation(this.pages[pageno-1])
}

// Get page rotation for a page object spec
func (this *PdfReader) _getPageRotation(page *PdfValue) (*PdfValue, error) {
	var err error

	// Resolve page object
	page, err = this.resolveObject(page)
	if err != nil {
		return nil, errors.New("Failed to resolve page object")
	}

	// Check to make sure /Rotate exists in page dictionary
	if _, ok := page.Value.Dictionary["/Rotate"]; ok {
		res, err := this.resolveObject(page.Value.Dictionary["/Rotate"])
		if err != nil {
			return nil, errors.New("Failed to resolve rotate object")
		}

		// If the type is PDF_TYPE_OBJECT, return its value
		if res.Type == PDF_TYPE_OBJECT {
			return res.Value, nil
		}

		// Otherwise, return the object
		return res, nil
	} else {
		// Check to see if parent has a rotation
		if _, ok := page.Value.Dictionary["/Parent"]; ok {
			// Recursively return /Parent page rotation
			res, err := this._getPageRotation(page.Value.Dictionary["/Parent"])
			if err != nil {
				return nil, errors.Wrap(err, "Failed to get page rotation for parent")
			}

			// If the type is PDF_TYPE_OBJECT, return its value
			if res.Type == PDF_TYPE_OBJECT {
				return res.Value, nil
			}

			// Otherwise, return the object
			return res, nil
		}
	}

	return &PdfValue{Int: 0}, nil
}

func (this *PdfReader) read() error {
	var err error

	// Find xref position
	err = this.findXref()
	if err != nil {
		return errors.Wrap(err, "Failed to find xref position")
	}

	// Parse xref table
	err = this.readXref()
	if err != nil {
		return errors.Wrap(err, "Failed to read xref table")
	}

	// Read catalog
	err = this.readRoot()
	if err != nil {
		return errors.Wrap(err, "Failed to read root")
	}

	// Read pages
	err = this.readPages()
	if err != nil {
		return errors.Wrap(err, "Failed to to read pages")
	}

	return nil
}


================================================
FILE: vendor/github.com/phpdave11/gofpdi/writer.go
================================================
package gofpdi

import (
	"bufio"
	"bytes"
	"compress/zlib"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"github.com/pkg/errors"
	"math"
	"os"
)

type PdfWriter struct {
	f       *os.File
	w       *bufio.Writer
	r       *PdfReader
	k       float64
	tpls    []*PdfTemplate
	m       int
	n       int
	offsets map[int]int
	offset  int
	result  map[int]string
	// Keep track of which objects have already been written
	obj_stack       map[int]*PdfValue
	don_obj_stack   map[int]*PdfValue
	written_objs    map[*PdfObjectId][]byte
	written_obj_pos map[*PdfObjectId]map[int]string
	current_obj     *PdfObject
	current_obj_id  int
	tpl_id_offset   int
	use_hash        bool
}

type PdfObjectId struct {
	id   int
	hash string
}

type PdfObject struct {
	id     *PdfObjectId
	buffer *bytes.Buffer
}

func (this *PdfWriter) SetTplIdOffset(n int) {
	this.tpl_id_offset = n
}

func (this *PdfWriter) Init() {
	this.k = 1
	this.obj_stack = make(map[int]*PdfValue, 0)
	this.don_obj_stack = make(map[int]*PdfValue, 0)
	this.tpls = make([]*PdfTemplate, 0)
	this.written_objs = make(map[*PdfObjectId][]byte, 0)
	this.written_obj_pos = make(map[*PdfObjectId]map[int]string, 0)
	this.current_obj = new(PdfObject)
}

func (this *PdfWriter) SetUseHash(b bool) {
	this.use_hash = b
}

func (this *PdfWriter) SetNextObjectID(id int) {
	this.n = id - 1
}

func NewPdfWriter(filename string) (*PdfWriter, error) {
	writer := &PdfWriter{}
	writer.Init()

	if filename != "" {
		var err error
		f, err := os.Create(filename)
		if err != nil {
			return nil, errors.Wrap(err, "Unable to create filename: "+filename)
		}
		writer.f = f
		writer.w = bufio.NewWriter(f)
	}
	return writer, nil
}

// Done with parsing.  Now, create templates.
type PdfTemplate struct {
	Id        int
	Reader    *PdfReader
	Resources *PdfValue
	Buffer    string
	Box       map[string]float64
	Boxes     map[string]map[string]float64
	X         float64
	Y         float64
	W         float64
	H         float64
	Rotation  int
	N         int
}

func (this *PdfWriter) GetImportedObjects() map[*PdfObjectId][]byte {
	return this.written_objs
}

// For each object (uniquely identified by a sha1 hash), return the positions
// of each hash within the object, to be replaced with pdf object ids (integers)
func (this *PdfWriter) GetImportedObjHashPos() map[*PdfObjectId]map[int]string {
	return this.written_obj_pos
}

func (this *PdfWriter) ClearImportedObjects() {
	this.written_objs = make(map[*PdfObjectId][]byte, 0)
}

// Create a PdfTemplate object from a page number (e.g. 1) and a boxName (e.g. MediaBox)
func (this *PdfWriter) ImportPage(reader *PdfReader, pageno int, boxName string) (int, error) {
	var err error

	// Set default scale to 1
	this.k = 1

	// Get all page boxes
	pageBoxes, err := reader.getPageBoxes(1, this.k)
	if err != nil {
		return -1, errors.Wrap(err, "Failed to get page boxes")
	}

	// If requested box name does not exist for this page, use an alternate box
	if _, ok := pageBoxes[boxName]; !ok {
		if boxName == "/BleedBox" || boxName == "/TrimBox" || boxName == "ArtBox" {
			boxName = "/CropBox"
		} else if boxName == "/CropBox" {
			boxName = "/MediaBox"
		}
	}

	// If the requested box name or an alternate box name cannot be found, trigger an error
	// TODO: Improve error handling
	if _, ok := pageBoxes[boxName]; !ok {
		return -1, errors.New("Box not found: " + boxName)
	}

	pageResources, err := reader.getPageResources(pageno)
	if err != nil {
		return -1, errors.Wrap(err, "Failed to get page resources")
	}

	content, err := reader.getContent(pageno)
	if err != nil {
		return -1, errors.Wrap(err, "Failed to get content")
	}

	// Set template values
	tpl := &PdfTemplate{}
	tpl.Reader = reader
	tpl.Resources = pageResources
	tpl.Buffer = content
	tpl.Box = pageBoxes[boxName]
	tpl.Boxes = pageBoxes
	tpl.X = 0
	tpl.Y = 0
	tpl.W = tpl.Box["w"]
	tpl.H = tpl.Box["h"]

	// Set template rotation
	rotation, err := reader.getPageRotation(pageno)
	if err != nil {
		return -1, errors.Wrap(err, "Failed to get page rotation")
	}
	angle := rotation.Int % 360

	// Normalize angle
	if angle != 0 {
		steps := angle / 90
		w := tpl.W
		h := tpl.H

		if steps%2 == 0 {
			tpl.W = w
			tpl.H = h
		} else {
			tpl.W = h
			tpl.H = w
		}

		if angle < 0 {
			angle += 360
		}

		tpl.Rotation = angle * -1
	}

	this.tpls = append(this.tpls, tpl)

	// Return last template id
	return len(this.tpls) - 1, nil
}

// Create a new object and keep track of the offset for the xref table
func (this *PdfWriter) newObj(objId int, onlyNewObj bool) {
	if objId < 0 {
		this.n++
		objId = this.n
	}

	if !onlyNewObj {
		// set current object id integer
		this.current_obj_id = objId

		// Create new PdfObject and PdfObjectId
		this.current_obj = new(PdfObject)
		this.current_obj.buffer = new(bytes.Buffer)
		this.current_obj.id = new(PdfObjectId)
		this.current_obj.id.id = objId
		this.current_obj.id.hash = this.shaOfInt(objId)

		this.written_obj_pos[this.current_obj.id] = make(map[int]string, 0)
	}
}

func (this *PdfWriter) endObj() {
	this.out("endobj")

	this.written_objs[this.current_obj.id] = this.current_obj.buffer.Bytes()
	this.current_obj_id = -1
}

func (this *PdfWriter) shaOfInt(i int) string {
	hasher := sha1.New()
	hasher.Write([]byte(fmt.Sprintf("%s-%s", i, this.r.sourceFile)))
	sha := hex.EncodeToString(hasher.Sum(nil))
	return sha
}

func (this *PdfWriter) outObjRef(objId int) {
	sha := this.shaOfInt(objId)

	// Keep track of object hash and position - to be replaced with actual object id (integer)
	this.written_obj_pos[this.current_obj.id][this.current_obj.buffer.Len()] = sha

	if this.use_hash {
		this.current_obj.buffer.WriteString(sha)
	} else {
		this.current_obj.buffer.WriteString(fmt.Sprintf("%d", objId))
	}
	this.current_obj.buffer.WriteString(" 0 R ")
}

// Output PDF data with a newline
func (this *PdfWriter) out(s string) {
	this.current_obj.buffer.WriteString(s)
	this.current_obj.buffer.WriteString("\n")
}

// Output PDF data
func (this *PdfWriter) straightOut(s string) {
	this.current_obj.buffer.WriteString(s)
}

// Output a PdfValue
func (this *PdfWriter) writeValue(value *PdfValue) {
	switch value.Type {
	case PDF_TYPE_TOKEN:
		this.straightOut(value.Token + " ")
		break

	case PDF_TYPE_NUMERIC:
		this.straightOut(fmt.Sprintf("%d", value.Int) + " ")
		break

	case PDF_TYPE_REAL:
		this.straightOut(fmt.Sprintf("%F", value.Real) + " ")
		break

	case PDF_TYPE_ARRAY:
		this.straightOut("[")
		for i := 0; i < len(value.Array); i++ {
			this.writeValue(value.Array[i])
		}
		this.out("]")
		break

	case PDF_TYPE_DICTIONARY:
		this.straightOut("<<")
		for k, v := range value.Dictionary {
			this.straightOut(k + " ")
			this.writeValue(v)
		}
		this.straightOut(">>")
		break

	case PDF_TYPE_OBJREF:
		// An indirect object reference.  Fill the object stack if needed.
		// Check to see if object already exists on the don_obj_stack.
		if _, ok := this.don_obj_stack[value.Id]; !ok {
			this.newObj(-1, true)
			this.obj_stack[value.Id] = &PdfValue{Type: PDF_TYPE_OBJREF, Gen: value.Gen, Id: value.Id, NewId: this.n}
			this.don_obj_stack[value.Id] = &PdfValue{Type: PDF_TYPE_OBJREF, Gen: value.Gen, Id: value.Id, NewId: this.n}
		}

		// Get object ID from don_obj_stack
		objId := this.don_obj_stack[value.Id].NewId
		this.outObjRef(objId)
		//this.out(fmt.Sprintf("%d 0 R", objId))
		break

	case PDF_TYPE_STRING:
		// A string
		this.straightOut("(" + value.String + ")")
		break

	case PDF_TYPE_STREAM:
		// A stream.  First, output the stream dictionary, then the stream data itself.
		this.writeValue(value.Value)
		this.out("stream")
		this.out(string(value.Stream.Bytes))
		this.out("endstream")
		break

	case PDF_TYPE_HEX:
		this.straightOut("<" + value.String + ">")
		break

	case PDF_TYPE_BOOLEAN:
		if value.Bool {
			this.straightOut("true")
		} else {
			this.straightOut("false")
		}
		break

	case PDF_TYPE_NULL:
		// The null object
		this.straightOut("null ")
		break
	}
}

// Output Form XObjects (1 for each template)
// returns a map of template names (e.g. /GOFPDITPL1) to PdfObjectId
func (this *PdfWriter) PutFormXobjects(reader *PdfReader) (map[string]*PdfObjectId, error) {
	// Set current reader
	this.r = reader

	var err error
	var result = make(map[string]*PdfObjectId, 0)

	compress := true
	filter := ""
	if compress {
		filter = "/Filter /FlateDecode "
	}

	for i := 0; i < len(this.tpls); i++ {
		tpl := this.tpls[i]
		if tpl == nil {
			return nil, errors.New("Template is nil")
		}
		var p string
		if compress {
			var b bytes.Buffer
			w := zlib.NewWriter(&b)
			w.Write([]byte(tpl.Buffer))
			w.Close()

			p = b.String()
		} else {
			p = tpl.Buffer
		}

		// Create new PDF object
		this.newObj(-1, false)

		cN := this.n // remember current "n"

		tpl.N = this.n

		// Return xobject form name and object position
		pdfObjId := new(PdfObjectId)
		pdfObjId.id = cN
		pdfObjId.hash = this.shaOfInt(cN)
		result[fmt.Sprintf("/GOFPDITPL%d", i+this.tpl_id_offset)] = pdfObjId

		this.out("<<" + filter + "/Type /XObject")
		this.out("/Subtype /Form")
		this.out("/FormType 1")

		this.out(fmt.Sprintf("/BBox [%.2F %.2F %.2F %.2F]", tpl.Box["llx"]*this.k, tpl.Box["lly"]*this.k, (tpl.Box["urx"]+tpl.X)*this.k, (tpl.Box["ury"]-tpl.Y)*this.k))

		var c, s, tx, ty float64
		c = 1

		// Handle rotated pages
		if tpl.Box != nil {
			tx = -tpl.Box["llx"]
			ty = -tpl.Box["lly"]

			if tpl.Rotation != 0 {
				angle := float64(tpl.Rotation) * math.Pi / 180.0
				c = math.Cos(float64(angle))
				s = math.Sin(float64(angle))

				switch tpl.Rotation {
				case -90:
					tx = -tpl.Box["lly"]
					ty = tpl.Box["urx"]
					break

				case -180:
					tx = tpl.Box["urx"]
					ty = tpl.Box["ury"]
					break

				case -270:
					tx = tpl.Box["ury"]
					ty = -tpl.Box["llx"]
				}
			}
		} else {
			tx = -tpl.Box["x"] * 2
			ty = tpl.Box["y"] * 2
		}

		tx *= this.k
		ty *= this.k

		if c != 1 || s != 0 || tx != 0 || ty != 0 {
			this.out(fmt.Sprintf("/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]", c, s, -s, c, tx, ty))
		}

		// Now write resources
		this.out("/Resources ")

		if tpl.Resources != nil {
			this.writeValue(tpl.Resources) // "n" will be changed
		} else {
			return nil, errors.New("Template resources are empty")
		}

		nN := this.n // remember new "n"
		this.n = cN  // reset to current "n"

		this.out("/Length " + fmt.Sprintf("%d", len(p)) + " >>")

		this.out("stream")
		this.out(p)
		this.out("endstream")

		this.endObj()

		this.n = nN // reset to new "n"

		// Put imported objects, starting with the ones from the XObject's Resources,
		// then from dependencies of those resources).
		err = this.putImportedObjects(reader)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to put imported objects")
		}
	}

	return result, nil
}

func (this *PdfWriter) putImportedObjects(reader *PdfReader) error {
	var err error
	var nObj *PdfValue

	// obj_stack will have new items added to it in the inner loop, so do another loop to check for extras
	// TODO make the order of this the same every time
	for {
		atLeastOne := false

		// FIXME:  How to determine number of objects before this loop?
		for i := 0; i < 9999; i++ {
			k := i
			v := this.obj_stack[i]

			if v == nil {
				continue
			}

			atLeastOne = true

			nObj, err = reader.resolveObject(v)
			if err != nil {
				return errors.Wrap(err, "Unable to resolve object")
			}

			// New object with "NewId" field
			this.newObj(v.NewId, false)

			if nObj.Type == PDF_TYPE_STREAM {
				this.writeValue(nObj)
			} else {
				this.writeValue(nObj.Value)
			}

			this.endObj()

			// Remove from stack
			this.obj_stack[k] = nil
		}

		if !atLeastOne {
			break
		}
	}

	return nil
}

// Get the calculated size of a template
// If one size is given, this method calculates the other one
func (this *PdfWriter) getTemplateSize(tplid int, _w float64, _h float64) map[string]float64 {
	result := make(map[string]float64, 2)

	tpl := this.tpls[tplid]

	w := tpl.W
	h := tpl.H

	if _w == 0 && _h == 0 {
		_w = w
		_h = h
	}

	if _w == 0 {
		_w = _h * w / h
	}

	if _h == 0 {
		_h = _w * h / w
	}

	result["w"] = _w
	result["h"] = _h

	return result
}

func (this *PdfWriter) UseTemplate(tplid int, _x float64, _y float64, _w float64, _h float64) (string, float64, float64, float64, float64) {
	tpl := this.tpls[tplid]

	w := tpl.W
	h := tpl.H

	_x += tpl.X
	_y += tpl.Y

	wh := this.getTemplateSize(0, _w, _h)

	_w = wh["w"]
	_h = wh["h"]

	tData := make(map[string]float64, 9)
	tData["x"] = 0.0
	tData["y"] = 0.0
	tData["w"] = _w
	tData["h"] = _h
	tData["scaleX"] = (_w / w)
	tData["scaleY"] = (_h / h)
	tData["tx"] = _x
	tData["ty"] = (0 - _y - _h)
	tData["lty"] = (0 - _y - _h) - (0-h)*(_h/h)

	return fmt.Sprintf("/GOFPDITPL%d", tplid+this.tpl_id_offset), tData["scaleX"], tData["scaleY"], tData["tx"] * this.k, tData["ty"] * this.k
}


================================================
FILE: vendor/github.com/pkg/errors/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof


================================================
FILE: vendor/github.com/pkg/errors/.travis.yml
================================================
language: go
go_import_path: github.com/pkg/errors
go:
  - 1.4.x
  - 1.5.x
  - 1.6.x
  - 1.7.x
  - 1.8.x
  - 1.9.x
  - 1.10.x
  - 1.11.x
  - tip

script:
  - go test -v ./...


================================================
FILE: vendor/github.com/pkg/errors/LICENSE
================================================
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: vendor/github.com/pkg/errors/README.md
================================================
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)

Package errors provides simple error handling primitives.

`go get github.com/pkg/errors`

The traditional error handling idiom in Go is roughly akin to
```go
if err != nil {
        return err
}
```
which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.

## Adding context to an error

The errors.Wrap function returns a new error that adds context to the original error. For example
```go
_, err := ioutil.ReadAll(r)
if err != nil {
        return errors.Wrap(err, "read failed")
}
```
## Retrieving the cause of an error

Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
```go
type causer interface {
        Cause() error
}
```
`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
```go
switch err := errors.Cause(err).(type) {
case *MyError:
        // handle specifically
default:
        // unknown error
}
```

[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).

## Contributing

We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.

Before proposing a change, please discuss your change by raising an issue.

## License

BSD-2-Clause


================================================
FILE: vendor/github.com/pkg/errors/appveyor.yml
================================================
version: build-{build}.{branch}

clone_folder: C:\gopath\src\github.com\pkg\errors
shallow_clone: true # for startup speed

environment:
  GOPATH: C:\gopath

platform:
  - x64

# http://www.appveyor.com/docs/installed-software
install:
  # some helpful output for debugging builds
  - go version
  - go env
  # pre-installed MinGW at C:\MinGW is 32bit only
  # but MSYS2 at C:\msys64 has mingw64
  - set PATH=C:\msys64\mingw64\bin;%PATH%
  - gcc --version
  - g++ --version

build_script:
  - go install -v ./...

test_script:
  - set PATH=C:\gopath\bin;%PATH%
  - go test -v ./...

#artifacts:
#  - path: '%GOPATH%\bin\*.exe'
deploy: off


================================================
FILE: vendor/github.com/pkg/errors/errors.go
================================================
// Package errors provides simple error handling primitives.
//
// The traditional error handling idiom in Go is roughly akin to
//
//     if err != nil {
//             return err
//     }
//
// which when applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error.
//
// Adding context to an error
//
// The errors.Wrap function returns a new error that adds context to the
// original error by recording a stack trace at the point Wrap is called,
// together with the supplied message. For example
//
//     _, err := ioutil.ReadAll(r)
//     if err != nil {
//             return errors.Wrap(err, "read failed")
//     }
//
// If additional control is required, the errors.WithStack and
// errors.WithMessage functions destructure errors.Wrap into its component
// operations: annotating an error with a stack trace and with a message,
// respectively.
//
// Retrieving the cause of an error
//
// Using errors.Wrap constructs a stack of errors, adding context to the
// preceding error. Depending on the nature of the error it may be necessary
// to reverse the operation of errors.Wrap to retrieve the original error
// for inspection. Any error value which implements this interface
//
//     type causer interface {
//             Cause() error
//     }
//
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error that does not implement causer, which is assumed to be
// the original cause. For example:
//
//     switch err := errors.Cause(err).(type) {
//     case *MyError:
//             // handle specifically
//     default:
//             // unknown error
//     }
//
// Although the causer interface is not exported by this package, it is
// considered a part of its stable public interface.
//
// Formatted printing of errors
//
// All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported:
//
//     %s    print the error. If the error has a Cause it will be
//           printed recursively.
//     %v    see %s
//     %+v   extended format. Each Frame of the error's StackTrace will
//           be printed in detail.
//
// Retrieving the stack trace of an error or wrapper
//
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface:
//
//     type stackTracer interface {
//             StackTrace() errors.StackTrace
//     }
//
// The returned errors.StackTrace type is defined as
//
//     type StackTrace []Frame
//
// The Frame type represents a call site in the stack trace. Frame supports
// the fmt.Formatter interface that can be used for printing information about
// the stack trace of this error. For example:
//
//     if err, ok := err.(stackTracer); ok {
//             for _, f := range err.StackTrace() {
//                     fmt.Printf("%+s:%d", f)
//             }
//     }
//
// Although the stackTracer interface is not exported by this package, it is
// considered a part of its stable public interface.
//
// See the documentation for Frame.Format for more details.
package errors

import (
	"fmt"
	"io"
)

// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(message string) error {
	return &fundamental{
		msg:   message,
		stack: callers(),
	}
}

// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// Errorf also records the stack trace at the point it was called.
func Errorf(format string, args ...interface{}) error {
	return &fundamental{
		msg:   fmt.Sprintf(format, args...),
		stack: callers(),
	}
}

// fundamental is an error that has a message and a stack, but no caller.
type fundamental struct {
	msg string
	*stack
}

func (f *fundamental) Error() string { return f.msg }

func (f *fundamental) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			io.WriteString(s, f.msg)
			f.stack.Format(s, verb)
			return
		}
		fallthrough
	case 's':
		io.WriteString(s, f.msg)
	case 'q':
		fmt.Fprintf(s, "%q", f.msg)
	}
}

// WithStack annotates err with a stack trace at the point WithStack was called.
// If err is nil, WithStack returns nil.
func WithStack(err error) error {
	if err == nil {
		return nil
	}
	return &withStack{
		err,
		callers(),
	}
}

type withStack struct {
	error
	*stack
}

func (w *withStack) Cause() error { return w.error }

func (w *withStack) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			fmt.Fprintf(s, "%+v", w.Cause())
			w.stack.Format(s, verb)
			return
		}
		fallthrough
	case 's':
		io.WriteString(s, w.Error())
	case 'q':
		fmt.Fprintf(s, "%q", w.Error())
	}
}

// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
	if err == nil {
		return nil
	}
	err = &withMessage{
		cause: err,
		msg:   message,
	}
	return &withStack{
		err,
		callers(),
	}
}

// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
	if err == nil {
		return nil
	}
	err = &withMessage{
		cause: err,
		msg:   fmt.Sprintf(format, args...),
	}
	return &withStack{
		err,
		callers(),
	}
}

// WithMessage annotates err with a new message.
// If err is nil, WithMessage returns nil.
func WithMessage(err error, message string) error {
	if err == nil {
		return nil
	}
	return &withMessage{
		cause: err,
		msg:   message,
	}
}

// WithMessagef annotates err with the format specifier.
// If err is nil, WithMessagef returns nil.
func WithMessagef(err error, format string, args ...interface{}) error {
	if err == nil {
		return nil
	}
	return &withMessage{
		cause: err,
		msg:   fmt.Sprintf(format, args...),
	}
}

type withMessage struct {
	cause error
	msg   string
}

func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
func (w *withMessage) Cause() error  { return w.cause }

func (w *withMessage) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			fmt.Fprintf(s, "%+v\n", w.Cause())
			io.WriteString(s, w.msg)
			return
		}
		fallthrough
	case 's', 'q':
		io.WriteString(s, w.Error())
	}
}

// Cause returns the underlying cause of the error, if possible.
// An error value has a cause if it implements the following
// interface:
//
//     type causer interface {
//            Cause() error
//     }
//
// If the error does not implement Cause, the original error will
// be returned. If the error is nil, nil will be returned without further
// investigation.
func Cause(err error) error {
	type causer interface {
		Cause() error
	}

	for err != nil {
		cause, ok := err.(causer)
		if !ok {
			break
		}
		err = cause.Cause()
	}
	return err
}


================================================
FILE: vendor/github.com/pkg/errors/stack.go
================================================
package errors

import (
	"fmt"
	"io"
	"path"
	"runtime"
	"strings"
)

// Frame represents a program counter inside a stack frame.
type Frame uintptr

// pc returns the program counter for this frame;
// multiple frames may have the same PC value.
func (f Frame) pc() uintptr { return uintptr(f) - 1 }

// file returns the full path to the file that contains the
// function for this Frame's pc.
func (f Frame) file() string {
	fn := runtime.FuncForPC(f.pc())
	if fn == nil {
		return "unknown"
	}
	file, _ := fn.FileLine(f.pc())
	return file
}

// line returns the line number of source code of the
// function for this Frame's pc.
func (f Frame) line() int {
	fn := runtime.FuncForPC(f.pc())
	if fn == nil {
		return 0
	}
	_, line := fn.FileLine(f.pc())
	return line
}

// Format formats the frame according to the fmt.Formatter interface.
//
//    %s    source file
//    %d    source line
//    %n    function name
//    %v    equivalent to %s:%d
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
//    %+s   function name and path of source file relative to the compile time
//          GOPATH separated by \n\t (<funcname>\n\t<path>)
//    %+v   equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) {
	switch verb {
	case 's':
		switch {
		case s.Flag('+'):
			pc := f.pc()
			fn := runtime.FuncForPC(pc)
			if fn == nil {
				io.WriteString(s, "unknown")
			} else {
				file, _ := fn.FileLine(pc)
				fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
			}
		default:
			io.WriteString(s, path.Base(f.file()))
		}
	case 'd':
		fmt.Fprintf(s, "%d", f.line())
	case 'n':
		name := runtime.FuncForPC(f.pc()).Name()
		io.WriteString(s, funcname(name))
	case 'v':
		f.Format(s, 's')
		io.WriteString(s, ":")
		f.Format(s, 'd')
	}
}

// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame

// Format formats the stack of Frames according to the fmt.Formatter interface.
//
//    %s	lists source files for each Frame in the stack
//    %v	lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
//    %+v   Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		switch {
		case s.Flag('+'):
			for _, f := range st {
				fmt.Fprintf(s, "\n%+v", f)
			}
		case s.Flag('#'):
			fmt.Fprintf(s, "%#v", []Frame(st))
		default:
			fmt.Fprintf(s, "%v", []Frame(st))
		}
	case 's':
		fmt.Fprintf(s, "%s", []Frame(st))
	}
}

// stack represents a stack of program counters.
type stack []uintptr

func (s *stack) Format(st fmt.State, verb rune) {
	switch verb {
	case 'v':
		switch {
		case st.Flag('+'):
			for _, pc := range *s {
				f := Frame(pc)
				fmt.Fprintf(st, "\n%+v", f)
			}
		}
	}
}

func (s *stack) StackTrace() StackTrace {
	f := make([]Frame, len(*s))
	for i := 0; i < len(f); i++ {
		f[i] = Frame((*s)[i])
	}
	return f
}

func callers() *stack {
	const depth = 32
	var pcs [depth]uintptr
	n := runtime.Callers(3, pcs[:])
	var st stack = pcs[0:n]
	return &st
}

// funcname removes the path prefix component of a function's name reported by func.Name().
func funcname(name string) string {
	i := strings.LastIndex(name, "/")
	name = name[i+1:]
	i = strings.Index(name, ".")
	return name[i+1:]
}


================================================
FILE: vendor/github.com/signintech/gopdf/.gitignore
================================================
##android
# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
bin/
gen/
pkg/
*.jar
# Local configuration file (sdk path, etc)
local.properties

##eclipse
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# PDT-specific
.buildpath

##tmp
*~
*.bak

proguard-project.txt
/project.properties
lint.xml
.bzr

fontmaker/tmp/
fontmaker/fontmaker
fontmaker/ttf/

*.orig

.vscode
test/out/
test/debug.test
*.test
*.out
.DS_Store
.idea
.scannerwork


================================================
FILE: vendor/github.com/signintech/gopdf/Changelog.md
================================================
### May 2016

Remove old function
- ```GoPdf.AddFont(family string, ifont IFont, zfontpath string)```.
- Remove all font map file.


================================================
FILE: vendor/github.com/signintech/gopdf/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 signintech

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.



================================================
FILE: vendor/github.com/signintech/gopdf/README.md
================================================
gopdf
====

gopdf is a simple library for generating PDF document written in Go lang.


#### Features

- Unicode subfont embedding. (Chinese, Japanese, Korean, etc.)
- Draw line, oval, rect, curve
- Draw image ( jpg, png )
  - Set image mask
- Password protection
- Font [kerning](https://en.wikipedia.org/wiki/Kerning)


## Installation
 ```
 go get -u github.com/signintech/gopdf
 ```


### Print text 

```go
  
package main
import (
	"log"
	"github.com/signintech/gopdf"
)

func main() {

	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 })  
	pdf.AddPage()
	err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf")
	if err != nil {
		log.Print(err.Error())
		return
	}

	err = pdf.SetFont("wts11", "", 14)
	if err != nil {
		log.Print(err.Error())
		return
	}
	pdf.Cell(nil, "您好")
	pdf.WritePdf("hello.pdf")

}

```
  
### Image
  
```go

package main
import (
	"log"
	"github.com/signintech/gopdf"
)

func main() {
	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4 })  
	pdf.AddPage()
	var err error
	err = pdf.AddTTFFont("loma", "../ttf/Loma.ttf")
	if err != nil {
		log.Print(err.Error())
		return
	}
	
	pdf.Image("../imgs/gopher.jpg", 200, 50, nil) //print image
	err = pdf.SetFont("loma", "", 14)
	if err != nil {
		log.Print(err.Error())
		return
	}
	pdf.SetX(250) //move current location
	pdf.SetY(200)
	pdf.Cell(nil, "gopher and gopher") //print text

	pdf.WritePdf("image.pdf")
}
``` 

### Links

```go

package main

import (
	"log"
	"github.com/signintech/gopdf"
)

func main()  {
	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 }) //595.28, 841.89 = A4
	pdf.AddPage()
	err := pdf.AddTTFFont("times", "./test/res/times.ttf")
	if err != nil {
		log.Print(err.Error())
		return
	}

	err = pdf.SetFont("times", "", 14)
	if err != nil {
		log.Print(err.Error())
		return
	}

	pdf.SetX(30)
	pdf.SetY(40)
	pdf.Text("Link to example.com")
	pdf.AddExternalLink("http://example.com/", 27.5, 28, 125, 15)

	pdf.SetX(30)
	pdf.SetY(70)
	pdf.Text("Link to second page")
	pdf.AddInternalLink("anchor", 27.5, 58, 120, 15)

	pdf.AddPage()
	pdf.SetX(30)
	pdf.SetY(100)
	pdf.SetAnchor("anchor")
	pdf.Text("Anchor position")

	pdf.WritePdf("hello.tmp.pdf")

}
```

### Draw line
```go
pdf.SetLineWidth(2)
pdf.SetLineType("dashed")
pdf.Line(10, 30, 585, 30)
```

### Draw oval
```go
pdf.SetLineWidth(1)
pdf.Oval(100, 200, 500, 500)
```

### Draw polygon
```go
pdf.SetStrokeColor(255, 0, 0)
pdf.SetLineWidth(2)
pdf.SetFillColor(0, 255, 0)
pdf.Polygon([]gopdf.Point{{X: 10, Y: 30}, {X: 585, Y: 200}, {X: 585, Y: 250}}, "DF")
```

### Rotation text or image
```go
pdf.SetX(100)
pdf.SetY(100)
pdf.Rotate(270.0, 100.0, 100.0)
pdf.Text("Hello...")
pdf.RotateReset() //reset
```

### Set transparency
Read about [transparency in pdf](https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf) `(page 320, section 11)`
```go
// alpha - value of transparency, can be between `0` and `1`
// blendMode - default value is `/Normal` - read about [blendMode and kinds of its](https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf) `(page 325, section 11.3.5)`

transparency := Transparency{
	Alpha: 0.5,
	BlendModeType: "",
}
pdf.SetTransparency(transparency Transparency)
```

### Password protection
```go
package main

import (
	"log"

	"github.com/signintech/gopdf"
)


func main() {

	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{
		PageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4
		Protection: gopdf.PDFProtectionConfig{
			UseProtection: true,
			Permissions: gopdf.PermissionsPrint | gopdf.PermissionsCopy | gopdf.PermissionsModify,
			OwnerPass:   []byte("123456"),
			UserPass:    []byte("123456789")},
	})

	pdf.AddPage()
	pdf.AddTTFFont("loma", "../ttf/loma.ttf")
	pdf.Cell(nil,"Hi")
	pdf.WritePdf("protect.pdf")
}

```
### Import existing PDF 
Import existing PDF power by package [gofpdi](https://github.com/phpdave11/gofpdi) created by @phpdave11 (thank you :smile:)
```go
package main

import (
        "github.com/signintech/gopdf"
        "io"
        "net/http"
        "os"
)

func main() {
        var err error

        // Download a Font
        fontUrl := "https://github.com/google/fonts/raw/master/ofl/daysone/DaysOne-Regular.ttf"
        if err = DownloadFile("example-font.ttf", fontUrl); err != nil {
            panic(err)
        }

        // Download a PDF
        fileUrl := "https://tcpdf.org/files/examples/example_012.pdf"
        if err = DownloadFile("example-pdf.pdf", fileUrl); err != nil {
            panic(err)
        }

        pdf := gopdf.GoPdf{}
        pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4

        pdf.AddPage()

        err = pdf.AddTTFFont("daysone", "example-font.ttf")
        if err != nil {
            panic(err)
        }

        err = pdf.SetFont("daysone", "", 20)
        if err != nil {
            panic(err)
        }

        // Color the page
        pdf.SetLineWidth(0.1)
        pdf.SetFillColor(124, 252, 0) //setup fill color
        pdf.RectFromUpperLeftWithStyle(50, 100, 400, 600, "FD")
        pdf.SetFillColor(0, 0, 0)

        pdf.SetX(50)
        pdf.SetY(50)
        pdf.Cell(nil, "Import existing PDF into GoPDF Document")

        // Import page 1
        tpl1 := pdf.ImportPage("example-pdf.pdf", 1, "/MediaBox")

        // Draw pdf onto page
        pdf.UseImportedTemplate(tpl1, 50, 100, 400, 0)

        pdf.WritePdf("example.pdf")

}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {
        // Get the data
        resp, err := http.Get(url)
        if err != nil {
            return err
        }
        defer resp.Body.Close()

        // Create the file
        out, err := os.Create(filepath)
        if err != nil {
            return err
        }
        defer out.Close()

        // Write the body to file
        _, err = io.Copy(out, resp.Body)
        return err
}

```

### Possible to set [Trim-box](https://wiki.scribus.net/canvas/PDF_Boxes_:_mediabox,_cropbox,_bleedbox,_trimbox,_artbox)

```go
package main

import (
	"log"

	"github.com/signintech/gopdf"
)

func main() {
	
    pdf := gopdf.GoPdf{}
    mm6ToPx := 22.68
    
    // Base trim-box
    pdf.Start(gopdf.Config{
        PageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4
        TrimBox: gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},
    })

    // Page trim-box
    opt := gopdf.PageOption{
        PageSize: gopdf.PageSizeA4, //595.28, 841.89 = A4
        TrimBox: &gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},
    }
    pdf.AddPageWithOption(opt)

    if err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf"); err != nil {
        log.Print(err.Error())
        return
    }
    
    if err := pdf.SetFont("wts11", "", 14); err != nil {
        log.Print(err.Error())
        return
    }

    pdf.Cell(nil,"Hi")
    pdf.WritePdf("hello.pdf")
}

```

visit https://github.com/oneplus1000/gopdfsample for more samples.


================================================
FILE: vendor/github.com/signintech/gopdf/box.go
================================================
package gopdf

type Box struct {
	Left, Top, Right, Bottom float64
	unitOverride             int
}

// UnitsToPoints converts the box coordinates to Points. When this is called it is assumed the values of the box are in Units
func (box *Box) UnitsToPoints(t int) (b *Box) {
	if box == nil {
		return
	}

	if box.unitOverride != UnitUnset {
		t = box.unitOverride
	}

	b = &Box{
		Left:   box.Left,
		Top:    box.Top,
		Right:  box.Right,
		Bottom: box.Bottom,
	}
	UnitsToPointsVar(t, &b.Left, &b.Top, &b.Right, &b.Bottom)
	return
}


================================================
FILE: vendor/github.com/signintech/gopdf/buff.go
================================================
package gopdf

//Buff for pdf content
type Buff struct {
	position int
	datas    []byte
}

//Write : write []byte to buffer
func (b *Buff) Write(p []byte) (int, error) {
	for len(b.datas) < b.position+len(p) {
		b.datas = append(b.datas, 0)
	}
	i := 0
	max := len(p)
	for i < max {
		b.datas[i+b.position] = p[i]
		i++
	}
	b.position += i
	return 0, nil
}

//Len : len of buffer
func (b *Buff) Len() int {
	return len(b.datas)
}

//Bytes : get bytes
func (b *Buff) Bytes() []byte {
	return b.datas
}

//Position : get current postion
func (b *Buff) Position() int {
	return b.position
}

//SetPosition : set current postion
func (b *Buff) SetPosition(pos int) {
	b.position = pos
}


================================================
FILE: vendor/github.com/signintech/gopdf/buff_write.go
================================================
package gopdf

import "io"

//WriteUInt32  writes a 32-bit unsigned integer value to w io.Writer
func WriteUInt32(w io.Writer, v uint) error {
	a := byte(v >> 24)
	b := byte(v >> 16)
	c := byte(v >> 8)
	d := byte(v)
	_, err := w.Write([]byte{a, b, c, d})
	if err != nil {
		return err
	}
	return nil
}

//WriteUInt16 writes a 16-bit unsigned integer value to w io.Writer
func WriteUInt16(w io.Writer, v uint) error {

	a := byte(v >> 8)
	b := byte(v)
	_, err := w.Write([]byte{a, b})
	if err != nil {
		return err
	}
	return nil
}

//WriteTag writes string value to w io.Writer
func WriteTag(w io.Writer, tag string) error {
	b := []byte(tag)
	_, err := w.Write(b)
	if err != nil {
		return err
	}
	return nil
}

//WriteBytes writes []byte value to w io.Writer
func WriteBytes(w io.Writer, data []byte, offset int, count int) error {

	_, err := w.Write(data[offset : offset+count])
	if err != nil {
		return err
	}
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/buffer_pool.go
================================================
package gopdf

import (
	"bytes"
	"sync"
)

// buffer pool to reduce GC
var buffers = sync.Pool{
	// New is called when a new instance is needed
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}

// GetBuffer fetches a buffer from the pool
func GetBuffer() *bytes.Buffer {
	return buffers.Get().(*bytes.Buffer)
}

// PutBuffer returns a buffer to the pool
func PutBuffer(buf *bytes.Buffer) {
	buf.Reset()
	buffers.Put(buf)
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_contact_color.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

const colorTypeStroke = "RG"

const colorTypeFill = "rg"

type cacheContentColor struct {
	colorType string
	r, g, b   uint8
}

func (c *cacheContentColor) write(w io.Writer, protection *PDFProtection) error {
	fmt.Fprintf(w, "%.3f %.3f %.3f %s\n", float64(c.r)/255, float64(c.g)/255, float64(c.b)/255, c.colorType)
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_gray.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

const grayTypeFill = "g"
const grayTypeStroke = "G"

type cacheContentGray struct {
	grayType string
	scale    float64
}

func (c *cacheContentGray) write(w io.Writer, protection *PDFProtection) error {
	fmt.Fprintf(w, "%.2f %s\n", c.scale, c.grayType)
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_image.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentImage struct {
	verticalFlip     bool
	horizontalFlip   bool
	index            int
	x                float64
	y                float64
	pageHeight       float64
	rect             Rect
	crop             *CropOptions
	extGStateIndexes []int
}

func (c *cacheContentImage) write(w io.Writer, protection *PDFProtection) error {
	width := c.rect.W
	height := c.rect.H

	contentStream := "q\n"

	for _, extGStateIndex := range c.extGStateIndexes {
		contentStream += fmt.Sprintf("/GS%d gs\n", extGStateIndex)
	}

	if c.horizontalFlip || c.verticalFlip {
		fh := "1"
		if c.horizontalFlip {
			fh = "-1"
		}

		fv := "1"
		if c.verticalFlip {
			fv = "-1"
		}

		contentStream += fmt.Sprintf("%s 0 0 %s 0 0 cm\n", fh, fv)
	}

	if c.crop != nil {
		clippingX := c.x
		if c.horizontalFlip {
			clippingX = -clippingX - c.crop.Width
		}

		clippingY := c.pageHeight - (c.y + c.crop.Height)
		if c.verticalFlip {
			clippingY = -clippingY - c.crop.Height
		}

		startX := c.x - c.crop.X
		if c.horizontalFlip {
			startX = -startX - width
		}

		startY := c.pageHeight - (c.y - c.crop.Y + c.rect.H)
		if c.verticalFlip {
			startY = -startY - height
		}

		contentStream += fmt.Sprintf("%0.2f %0.2f %0.2f %0.2f re W* n\n", clippingX, clippingY, c.crop.Width, c.crop.Height)
		contentStream += fmt.Sprintf("q %0.2f 0 0 %0.2f %0.2f %0.2f cm /I%d Do Q\n", width, height, startX, startY, c.index+1)
	} else {
		x := c.x
		y := c.pageHeight - (c.y + height)

		if c.horizontalFlip {
			x = -x - width
		}

		if c.verticalFlip {
			y = -y - height
		}

		contentStream += fmt.Sprintf("q %0.2f 0 0 %0.2f %0.2f %0.2f cm /I%d Do Q\n", width, height, x, y, c.index+1)
	}

	contentStream += "Q\n"

	if _, err := io.WriteString(w, contentStream); err != nil {
		return err
	}

	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_imported_object.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentImportedTemplate struct {
	pageHeight float64
	tplName    string
	scaleX     float64
	scaleY     float64
	tX         float64
	tY         float64
}

func (c *cacheContentImportedTemplate) write(w io.Writer, protection *PDFProtection) error {
	c.tY += c.pageHeight
	fmt.Fprintf(w, "q 0 J 1 w 0 j 0 G 0 g q %.4F 0 0 %.4F %.4F %.4F cm %s Do Q Q\n", c.scaleX, c.scaleY, c.tX, c.tY, c.tplName)
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_line.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentLine struct {
	pageHeight float64
	x1         float64
	y1         float64
	x2         float64
	y2         float64
}

func (c *cacheContentLine) write(w io.Writer, protection *PDFProtection) error {
	fmt.Fprintf(w, "%0.2f %0.2f m %0.2f %0.2f l S\n", c.x1, c.pageHeight-c.y1, c.x2, c.pageHeight-c.y2)
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_line_type.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentLineType struct {
	lineType string
}

func (c *cacheContentLineType) write(w io.Writer, protection *PDFProtection) error {
	switch c.lineType {
	case "dashed":
		fmt.Fprint(w, "[5] 2 d\n")
	case "dotted":
		fmt.Fprint(w, "[2 3] 11 d\n")
	default:
		fmt.Fprint(w, "[] 0 d\n")
	}
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_line_width.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentLineWidth struct {
	width float64
}

func (c *cacheContentLineWidth) write(w io.Writer, protection *PDFProtection) error {
	fmt.Fprintf(w, "%.2f w\n", c.width)
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_oval.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentOval struct {
	pageHeight float64
	x1         float64
	y1         float64
	x2         float64
	y2         float64
}

func (c *cacheContentOval) write(w io.Writer, protection *PDFProtection) error {

	h := c.pageHeight
	x1 := c.x1
	y1 := c.y1
	x2 := c.x2
	y2 := c.y2

	cp := 0.55228                              // Magnification of the control point
	v1 := [2]float64{x1 + (x2-x1)/2, h - y2}   // Vertex of the lower
	v2 := [2]float64{x2, h - (y1 + (y2-y1)/2)} // .. Right
	v3 := [2]float64{x1 + (x2-x1)/2, h - y1}   // .. Upper
	v4 := [2]float64{x1, h - (y1 + (y2-y1)/2)} // .. Left

	fmt.Fprintf(w, "%0.2f %0.2f m\n", v1[0], v1[1])
	fmt.Fprintf(w,
		"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c\n",
		v1[0]+(x2-x1)/2*cp, v1[1], v2[0], v2[1]-(y2-y1)/2*cp, v2[0], v2[1],
	)
	fmt.Fprintf(w,
		"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c\n",
		v2[0], v2[1]+(y2-y1)/2*cp, v3[0]+(x2-x1)/2*cp, v3[1], v3[0], v3[1],
	)
	fmt.Fprintf(w,
		"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c\n",
		v3[0]-(x2-x1)/2*cp, v3[1], v4[0], v4[1]+(y2-y1)/2*cp, v4[0], v4[1],
	)
	fmt.Fprintf(w,
		"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c S\n",
		v4[0], v4[1]-(y2-y1)/2*cp, v1[0]-(x2-x1)/2*cp, v1[1], v1[0], v1[1],
	)

	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_polygon.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentPolygon struct {
	pageHeight float64
	style      string
	points     []Point
}

func (c *cacheContentPolygon) write(w io.Writer, protection *PDFProtection) error {

	for i, point := range c.points {
		fmt.Fprintf(w, "%.2f %.2f", point.X, c.pageHeight-point.Y)
		if i == 0 {
			fmt.Fprintf(w, " m ")
		} else {
			fmt.Fprintf(w, " l ")
		}

	}

	if c.style == "F" {
		fmt.Fprintf(w, " f\n")
	} else if c.style == "FD" || c.style == "DF" {
		fmt.Fprintf(w, " b\n")
	} else {
		fmt.Fprintf(w, " s\n")
	}

	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_rectangle.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentRectangle struct {
	pageHeight       float64
	x                float64
	y                float64
	width            float64
	height           float64
	style            PaintStyle
	extGStateIndexes []int
}

func NewCacheContentRectangle(pageHeight float64, rectOpts DrawableRectOptions) ICacheContent {
	if rectOpts.PaintStyle == "" {
		rectOpts.PaintStyle = DrawPaintStyle
	}

	return cacheContentRectangle{
		x:                rectOpts.X,
		y:                rectOpts.Y,
		width:            rectOpts.W,
		height:           rectOpts.H,
		pageHeight:       pageHeight,
		style:            rectOpts.PaintStyle,
		extGStateIndexes: rectOpts.extGStateIndexes,
	}
}

func (c cacheContentRectangle) write(w io.Writer, protection *PDFProtection) error {
	stream := "q\n"

	for _, extGStateIndex := range c.extGStateIndexes {
		stream += fmt.Sprintf("/GS%d gs\n", extGStateIndex)
	}

	stream += fmt.Sprintf("%0.2f %0.2f %0.2f %0.2f re %s\n", c.x, c.pageHeight-c.y, c.width, c.height, c.style)

	stream += "Q\n"

	if _, err := io.WriteString(w, stream); err != nil {
		return err
	}

	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_rotate.go
================================================
package gopdf

import (
	"fmt"
	"io"
	"math"
)

type cacheContentRotate struct {
	isReset     bool
	pageHeight  float64
	angle, x, y float64
}

func (cc *cacheContentRotate) write(w io.Writer, protection *PDFProtection) error {
	if cc.isReset == true {
		fmt.Fprintf(w, "Q\n")
		return nil
	}
	angle := (cc.angle * 22.0) / (180.0 * 7.0)
	c := math.Cos(angle)
	s := math.Sin(angle)
	cy := cc.pageHeight - cc.y

	fmt.Fprintf(w, "q %.5f %.5f %.5f %.5f %.2f %.2f cm 1 0 0 1 %.2f %.2f cm\n", c, s, -s, c, cc.x, cy, -cc.x, -cy)
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_content_text.go
================================================
package gopdf

import (
	"errors"
	"fmt"
	"io"
)

//ContentTypeCell cell
const ContentTypeCell = 0

//ContentTypeText text
const ContentTypeText = 1

type cacheContentText struct {
	//---setup---
	rectangle      *Rect
	textColor      Rgb
	grayFill       float64
	txtColorMode   string
	fontCountIndex int //Curr.FontFontCount+1
	fontSize       int
	fontStyle      int
	setXCount      int //จำนวนครั้งที่ใช้ setX
	x, y           float64
	fontSubset     *SubsetFontObj
	pageheight     float64
	contentType    int
	cellOpt        CellOption
	lineWidth      float64
	text           string
	//---result---
	cellWidthPdfUnit, textWidthPdfUnit float64
	cellHeightPdfUnit                  float64
}

func (c *cacheContentText) isSame(cache cacheContentText) bool {
	if c.rectangle != nil {
		//if rectangle != nil we assumes this is not same content
		return false
	}
	if c.textColor.equal(cache.textColor) &&
		c.grayFill == cache.grayFill &&
		c.fontCountIndex == cache.fontCountIndex &&
		c.fontSize == cache.fontSize &&
		c.fontStyle == cache.fontStyle &&
		c.setXCount == cache.setXCount &&
		c.y == cache.y {
		return true
	}

	return false
}

func (c *cacheContentText) setPageHeight(pageheight float64) {
	c.pageheight = pageheight
}

func (c *cacheContentText) pageHeight() float64 {
	return c.pageheight //841.89
}

func convertTypoUnit(val float64, unitsPerEm uint, fontSize float64) float64 {
	val = val * 1000.00 / float64(unitsPerEm)
	return val * fontSize / 1000.0
}

func (c *cacheContentText) calTypoAscender() float64 {
	return convertTypoUnit(float64(c.fontSubset.ttfp.TypoAscender()), c.fontSubset.ttfp.UnitsPerEm(), float64(c.fontSize))
}

func (c *cacheContentText) calTypoDescender() float64 {
	return convertTypoUnit(float64(c.fontSubset.ttfp.TypoDescender()), c.fontSubset.ttfp.UnitsPerEm(), float64(c.fontSize))
}

func (c *cacheContentText) calY() (float64, error) {
	pageHeight := c.pageHeight()
	if c.contentType == ContentTypeText {
		return pageHeight - c.y, nil
	} else if c.contentType == ContentTypeCell {
		y := float64(0.0)
		if c.cellOpt.Align&Bottom == Bottom {
			y = pageHeight - c.y - c.cellHeightPdfUnit - c.calTypoDescender()
		} else if c.cellOpt.Align&Middle == Middle {
			y = pageHeight - c.y - c.cellHeightPdfUnit*0.5 - (c.calTypoDescender()+c.calTypoAscender())*0.5
		} else {
			//top
			y = pageHeight - c.y - c.calTypoAscender()
		}

		return y, nil
	}
	return 0.0, errors.New("contentType not found")
}

func (c *cacheContentText) calX() (float64, error) {
	if c.contentType == ContentTypeText {
		return c.x, nil
	} else if c.contentType == ContentTypeCell {
		x := float64(0.0)
		if c.cellOpt.Align&Right == Right {
			x = c.x + c.cellWidthPdfUnit - c.textWidthPdfUnit
		} else if c.cellOpt.Align&Center == Center {
			x = c.x + c.cellWidthPdfUnit*0.5 - c.textWidthPdfUnit*0.5
		} else {
			x = c.x
		}
		return x, nil
	}
	return 0.0, errors.New("contentType not found")
}

func (c *cacheContentText) write(w io.Writer, protection *PDFProtection) error {
	r := c.textColor.r
	g := c.textColor.g
	b := c.textColor.b
	x, err := c.calX()
	if err != nil {
		return err
	}
	y, err := c.calY()
	if err != nil {
		return err
	}

	for _, extGStateIndex := range c.cellOpt.extGStateIndexes {
		linkToGSObj := fmt.Sprintf("/GS%d gs\n", extGStateIndex)
		if _, err := io.WriteString(w, linkToGSObj); err != nil {
			return err
		}
	}

	if _, err := io.WriteString(w, "BT\n"); err != nil {
		return err
	}

	fmt.Fprintf(w, "%0.2f %0.2f TD\n", x, y)
	fmt.Fprintf(w, "/F%d %d Tf\n", c.fontCountIndex, c.fontSize)
	if c.txtColorMode == "color" {
		fmt.Fprintf(w, "%0.3f %0.3f %0.3f rg\n", float64(r)/255, float64(g)/255, float64(b)/255)
	}
	io.WriteString(w, "[<")

	unitsPerEm := int(c.fontSubset.ttfp.UnitsPerEm())
	var leftRune rune
	var leftRuneIndex uint
	for i, r := range c.text {

		glyphindex, err := c.fontSubset.CharIndex(r)
		if err != nil {
			return err
		}

		pairvalPdfUnit := 0
		if i > 0 && c.fontSubset.ttfFontOption.UseKerning { //kerning
			pairval := kern(c.fontSubset, leftRune, r, leftRuneIndex, glyphindex)
			pairvalPdfUnit = convertTTFUnit2PDFUnit(int(pairval), unitsPerEm)
			if pairvalPdfUnit != 0 {
				fmt.Fprintf(w, ">%d<", (-1)*pairvalPdfUnit)
			}
		}

		fmt.Fprintf(w, "%04X", glyphindex)
		leftRune = r
		leftRuneIndex = glyphindex
	}

	io.WriteString(w, ">] TJ\n")
	io.WriteString(w, "ET\n")

	if c.fontStyle&Underline == Underline {
		err := c.underline(w, c.x, c.y, c.x+c.cellWidthPdfUnit, c.y)
		if err != nil {
			return err
		}
	}

	c.drawBorder(w)

	return nil
}

func (c *cacheContentText) drawBorder(w io.Writer) error {

	//stream.WriteString(fmt.Sprintf("%.2f w\n", 0.1))
	lineOffset := c.lineWidth * 0.5

	if c.cellOpt.Border&Top == Top {

		startX := c.x - lineOffset
		startY := c.pageHeight() - c.y
		endX := c.x + c.cellWidthPdfUnit + lineOffset
		endY := startY
		_, err := fmt.Fprintf(w, "%0.2f %0.2f m %0.2f %0.2f l s\n", startX, startY, endX, endY)
		if err != nil {
			return err
		}
	}

	if c.cellOpt.Border&Left == Left {
		startX := c.x
		startY := c.pageHeight() - c.y
		endX := c.x
		endY := startY - c.cellHeightPdfUnit
		_, err := fmt.Fprintf(w, "%0.2f %0.2f m %0.2f %0.2f l s\n", startX, startY, endX, endY)
		if err != nil {
			return err
		}
	}

	if c.cellOpt.Border&Right == Right {
		startX := c.x + c.cellWidthPdfUnit
		startY := c.pageHeight() - c.y
		endX := c.x + c.cellWidthPdfUnit
		endY := startY - c.cellHeightPdfUnit
		_, err := fmt.Fprintf(w, "%0.2f %0.2f m %0.2f %0.2f l s\n", startX, startY, endX, endY)
		if err != nil {
			return err
		}
	}

	if c.cellOpt.Border&Bottom == Bottom {
		startX := c.x - lineOffset
		startY := c.pageHeight() - c.y - c.cellHeightPdfUnit
		endX := c.x + c.cellWidthPdfUnit + lineOffset
		endY := startY
		_, err := fmt.Fprintf(w, "%0.2f %0.2f m %0.2f %0.2f l s\n", startX, startY, endX, endY)
		if err != nil {
			return err
		}
	}

	return nil
}

func (c *cacheContentText) underline(w io.Writer, startX float64, startY float64, endX float64, endY float64) error {

	if c.fontSubset == nil {
		return errors.New("error AppendUnderline not found font")
	}
	unitsPerEm := float64(c.fontSubset.ttfp.UnitsPerEm())
	h := c.pageHeight()
	ut := float64(c.fontSubset.GetUt())
	up := float64(c.fontSubset.GetUp())
	textH := ContentObjCalTextHeight(c.fontSize)
	arg3 := float64(h) - (float64(startY) - ((up / unitsPerEm) * float64(c.fontSize))) - textH
	arg4 := (ut / unitsPerEm) * float64(c.fontSize)
	fmt.Fprintf(w, "%0.2f %0.2f %0.2f -%0.2f re f\n", startX, arg3, endX-startX, arg4)
	//fmt.Printf("arg3=%f arg4=%f\n", arg3, arg4)

	return nil
}

func (c *cacheContentText) createContent() (float64, float64, error) {

	cellWidthPdfUnit, cellHeightPdfUnit, textWidthPdfUnit, err := createContent(c.fontSubset, c.text, c.fontSize, c.rectangle)
	if err != nil {
		return 0, 0, err
	}
	c.cellWidthPdfUnit = cellWidthPdfUnit
	c.cellHeightPdfUnit = cellHeightPdfUnit
	c.textWidthPdfUnit = textWidthPdfUnit
	return cellWidthPdfUnit, cellHeightPdfUnit, nil
}

func createContent(f *SubsetFontObj, text string, fontSize int, rectangle *Rect) (float64, float64, float64, error) {

	unitsPerEm := int(f.ttfp.UnitsPerEm())
	var leftRune rune
	var leftRuneIndex uint
	sumWidth := int(0)
	//fmt.Printf("unitsPerEm = %d", unitsPerEm)
	for i, r := range text {

		glyphindex, err := f.CharIndex(r)
		if err != nil {
			return 0, 0, 0, err
		}

		pairvalPdfUnit := 0
		if i > 0 && f.ttfFontOption.UseKerning { //kerning
			pairval := kern(f, leftRune, r, leftRuneIndex, glyphindex)
			pairvalPdfUnit = convertTTFUnit2PDFUnit(int(pairval), unitsPerEm)
		}

		width, err := f.CharWidth(r)
		if err != nil {
			return 0, 0, 0, err
		}

		sumWidth += int(width) + int(pairvalPdfUnit)
		leftRune = r
		leftRuneIndex = glyphindex
	}

	cellWidthPdfUnit := float64(0)
	cellHeightPdfUnit := float64(0)
	if rectangle == nil {
		cellWidthPdfUnit = float64(sumWidth) * (float64(fontSize) / 1000.0)
		typoAscender := convertTypoUnit(float64(f.ttfp.TypoAscender()), f.ttfp.UnitsPerEm(), float64(fontSize))
		typoDescender := convertTypoUnit(float64(f.ttfp.TypoDescender()), f.ttfp.UnitsPerEm(), float64(fontSize))
		cellHeightPdfUnit = typoAscender - typoDescender
	} else {
		cellWidthPdfUnit = rectangle.W
		cellHeightPdfUnit = rectangle.H
	}
	textWidthPdfUnit := float64(sumWidth) * (float64(fontSize) / 1000.0)
	return cellWidthPdfUnit, cellHeightPdfUnit, textWidthPdfUnit, nil
}

func kern(f *SubsetFontObj, leftRune rune, rightRune rune, leftIndex uint, rightIndex uint) int16 {

	pairVal := int16(0)
	if haveKerning, kval := f.KernValueByLeft(leftIndex); haveKerning {
		if ok, v := kval.ValueByRight(rightIndex); ok {
			pairVal = v
		}
	}

	if f.funcKernOverride != nil {
		pairVal = f.funcKernOverride(
			leftRune,
			rightRune,
			leftIndex,
			rightIndex,
			pairVal,
		)
	}
	return pairVal
}

//CacheContent Export cacheContent
type CacheContent struct {
	cacheContentText
}

//Setup setup all information for cacheContent
func (c *CacheContent) Setup(rectangle *Rect,
	textColor Rgb,
	grayFill float64,
	fontCountIndex int, //Curr.FontFontCount+1
	fontSize int,
	fontStyle int,
	setXCount int, //จำนวนครั้งที่ใช้ setX
	x, y float64,
	fontSubset *SubsetFontObj,
	pageheight float64,
	contentType int,
	cellOpt CellOption,
	lineWidth float64,
) {
	c.cacheContentText = cacheContentText{
		fontSubset:     fontSubset,
		rectangle:      rectangle,
		textColor:      textColor,
		grayFill:       grayFill,
		fontCountIndex: fontCountIndex,
		fontSize:       fontSize,
		fontStyle:      fontStyle,
		setXCount:      setXCount,
		x:              x,
		y:              y,
		pageheight:     pageheight,
		contentType:    ContentTypeCell,
		cellOpt:        cellOpt,
		lineWidth:      lineWidth,
	}
}

//WriteTextToContent write text to content
func (c *CacheContent) WriteTextToContent(text string) {
	c.cacheContentText.text += text
}


================================================
FILE: vendor/github.com/signintech/gopdf/cache_contnent_curve.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

type cacheContentCurve struct {
	pageHeight float64
	x0         float64
	y0         float64
	x1         float64
	y1         float64
	x2         float64
	y2         float64
	x3         float64
	y3         float64
	style      string
}

func (c *cacheContentCurve) write(w io.Writer, protection *PDFProtection) error {

	h := c.pageHeight
	x0 := c.x0
	y0 := c.y0
	x1 := c.x1
	y1 := c.y1
	x2 := c.x2
	y2 := c.y2
	x3 := c.x3
	y3 := c.y3
	style := c.style

	//cp := 0.55228
	fmt.Fprintf(w, "%0.2f %0.2f m\n", x0, h-y0)
	fmt.Fprintf(w,
		"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c",
		x1, h-y1, x2, h-y2, x3, h-y3,
	)
	op := "S"
	if style == "F" {
		op = "f"
	} else if style == "FD" || style == "DF" {
		op = "B"
	}
	fmt.Fprintf(w, " %s\n", op)
	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/catalog_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

//CatalogObj : catalog dictionary
type CatalogObj struct { //impl IObj
	outlinesObjID int
}

func (c *CatalogObj) init(funcGetRoot func() *GoPdf) {
	c.outlinesObjID = -1

}

func (c *CatalogObj) getType() string {
	return "Catalog"
}

func (c *CatalogObj) write(w io.Writer, objID int) error {
	io.WriteString(w, "<<\n")
	fmt.Fprintf(w, "  /Type /%s\n", c.getType())
	io.WriteString(w, "  /Pages 2 0 R\n")
	if c.outlinesObjID >= 0 {
		io.WriteString(w, "  /PageMode /UseOutlines\n")
		fmt.Fprintf(w, "  /Outlines %d 0 R\n", c.outlinesObjID)
	}
	io.WriteString(w, ">>\n")
	return nil
}

func (c *CatalogObj) SetIndexObjOutlines(index int) {
	c.outlinesObjID = index + 1
}


================================================
FILE: vendor/github.com/signintech/gopdf/cell_option.go
================================================
package gopdf

//Left left
const Left = 8 //001000
//Top top
const Top = 4 //000100
//Right right
const Right = 2 //000010
//Bottom bottom
const Bottom = 1 //000001
//Center center
const Center = 16 //010000
//Middle middle
const Middle = 32 //100000
//AllBorders allborders
const AllBorders = 15 //001111

//CellOption cell option
type CellOption struct {
	Align        int //Allows to align the text. Possible values are: Left,Center,Right,Top,Bottom,Middle
	Border       int //Indicates if borders must be drawn around the cell. Possible values are: Left, Top, Right, Bottom, ALL
	Float        int //Indicates where the current position should go after the call. Possible values are: Right, Bottom
	Transparency *Transparency

	extGStateIndexes []int
}


================================================
FILE: vendor/github.com/signintech/gopdf/cid_font_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

// CIDFontObj is a CID-keyed font.
// cf. https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5014.CIDFont_Spec.pdf
type CIDFontObj struct {
	PtrToSubsetFontObj        *SubsetFontObj
	indexObjSubfontDescriptor int
}

func (ci *CIDFontObj) init(funcGetRoot func() *GoPdf) {
}

//SetIndexObjSubfontDescriptor set  indexObjSubfontDescriptor
func (ci *CIDFontObj) SetIndexObjSubfontDescriptor(index int) {
	ci.indexObjSubfontDescriptor = index
}

func (ci *CIDFontObj) getType() string {
	return "CIDFont"
}

func (ci *CIDFontObj) write(w io.Writer, objID int) error {
	io.WriteString(w, "<<\n")
	fmt.Fprintf(w, "/BaseFont /%s\n", CreateEmbeddedFontSubsetName(ci.PtrToSubsetFontObj.GetFamily()))
	io.WriteString(w, "/CIDSystemInfo\n")
	io.WriteString(w, "<<\n")
	io.WriteString(w, "  /Ordering (Identity)\n")
	io.WriteString(w, "  /Registry (Adobe)\n")
	io.WriteString(w, "  /Supplement 0\n")
	io.WriteString(w, ">>\n")
	fmt.Fprintf(w, "/FontDescriptor %d 0 R\n", ci.indexObjSubfontDescriptor+1) //TODO fix
	io.WriteString(w, "/Subtype /CIDFontType2\n")
	io.WriteString(w, "/Type /Font\n")
	glyphIndexs := ci.PtrToSubsetFontObj.CharacterToGlyphIndex.AllVals()
	io.WriteString(w, "/W [")
	for _, v := range glyphIndexs {
		width := ci.PtrToSubsetFontObj.GlyphIndexToPdfWidth(v)
		fmt.Fprintf(w, "%d[%d]", v, width)
	}
	io.WriteString(w, "]\n")
	io.WriteString(w, ">>\n")
	return nil
}

//SetPtrToSubsetFontObj set PtrToSubsetFontObj
func (ci *CIDFontObj) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {
	ci.PtrToSubsetFontObj = ptr
}


================================================
FILE: vendor/github.com/signintech/gopdf/config.go
================================================
package gopdf

// The units that can be used in the document
const (
	UnitUnset = iota // No units were set, when conversion is called on nothing will happen
	UnitPT           // Points
	UnitMM           // Millimeters
	UnitCM           // centimeters
	UnitIN           // inches

	// The math needed to convert units to points
	conversionUnitPT = 1.0
	conversionUnitMM = 72.0 / 25.4
	conversionUnitCM = 72.0 / 2.54
	conversionUnitIN = 72.0
)

// The units that can be used in the document (for backward compatibility)
// Deprecated: Use UnitUnset,UnitPT,UnitMM,UnitCM,UnitIN  instead
const (
	Unit_Unset = UnitUnset // No units were set, when conversion is called on nothing will happen
	Unit_PT    = UnitPT    // Points
	Unit_MM    = UnitMM    // Millimeters
	Unit_CM    = UnitCM    // centimeters
	Unit_IN    = UnitIN    // inches
)

//Config static config
type Config struct {
	Unit       int                 // The unit type to use when composing the document.
	TrimBox    Box                 // The default trim box for all pages in the document
	PageSize   Rect                // The default page size for all pages in the document
	K          float64             // Not sure
	Protection PDFProtectionConfig // Protection settings
}

//PDFProtectionConfig config of pdf protection
type PDFProtectionConfig struct {
	UseProtection bool
	Permissions   int
	UserPass      []byte
	OwnerPass     []byte
}

// UnitsToPoints converts units of the provided type to points
func UnitsToPoints(t int, u float64) float64 {
	switch t {
	case UnitPT:
		return u * conversionUnitPT
	case UnitMM:
		return u * conversionUnitMM
	case UnitCM:
		return u * conversionUnitCM
	case UnitIN:
		return u * conversionUnitIN
	default:
		return u
	}
}

// PointsToUnits converts points to the provided units
func PointsToUnits(t int, u float64) float64 {
	switch t {
	case UnitPT:
		return u / conversionUnitPT
	case UnitMM:
		return u / conversionUnitMM
	case UnitCM:
		return u / conversionUnitCM
	case UnitIN:
		return u / conversionUnitIN
	default:
		return u
	}
}

// UnitsToPointsVar converts units of the provided type to points for all variables supplied
func UnitsToPointsVar(t int, u ...*float64) {
	for x := 0; x < len(u); x++ {
		*u[x] = UnitsToPoints(t, *u[x])
	}
}

// PointsToUnitsVar converts points to the provided units for all variables supplied
func PointsToUnitsVar(t int, u ...*float64) {
	for x := 0; x < len(u); x++ {
		*u[x] = PointsToUnits(t, *u[x])
	}
}


================================================
FILE: vendor/github.com/signintech/gopdf/content_obj.go
================================================
package gopdf

import (
	"compress/zlib"
	"fmt"
	"io"
	"strings"
)

//ContentObj content object
type ContentObj struct { //impl IObj
	listCache listCacheContent
	//text bytes.Buffer
	getRoot func() *GoPdf
}

func (c *ContentObj) protection() *PDFProtection {
	return c.getRoot().protection()
}

func (c *ContentObj) init(funcGetRoot func() *GoPdf) {
	c.getRoot = funcGetRoot
}

func (c *ContentObj) write(w io.Writer, objID int) error {
	buff := GetBuffer()
	defer PutBuffer(buff)

	isFlate := (c.getRoot().compressLevel != zlib.NoCompression)
	if isFlate {
		ww, err := zlib.NewWriterLevel(buff, c.getRoot().compressLevel)
		if err != nil {
			// should never happen...
			return err
		}
		if err := c.listCache.write(ww, c.protection()); err != nil {
			return err
		}
		if err := ww.Close(); err != nil {
			return err
		}
	} else {
		if err := c.listCache.write(buff, c.protection()); err != nil {
			return err
		}
	}

	if _, err := io.WriteString(w, "<<\n"); err != nil {
		return err
	}

	if isFlate {
		if _, err := io.WriteString(w, "/Filter/FlateDecode"); err != nil {
			return err
		}
	}
	if _, err := fmt.Fprintf(w, "/Length %d\n", buff.Len()); err != nil {
		return err
	}
	if _, err := io.WriteString(w, ">>\n"); err != nil {
		return err
	}
	if _, err := io.WriteString(w, "stream\n"); err != nil {
		return err
	}

	if c.protection() != nil {
		tmp, err := rc4Cip(c.protection().objectkey(objID), buff.Bytes())
		if err != nil {
			return err
		}

		if _, err := w.Write(tmp); err != nil {
			return err
		}
		if _, err := io.WriteString(w, "\n"); err != nil {
			return err
		}
	} else {
		if _, err := buff.WriteTo(w); err != nil {
			return err
		}

		if isFlate {
			if _, err := io.WriteString(w, "\n"); err != nil {
				return err
			}
		}
	}
	if _, err := io.WriteString(w, "endstream\n"); err != nil {
		return err
	}

	return nil
}

func (c *ContentObj) getType() string {
	return "Content"
}

//AppendStreamText append text
func (c *ContentObj) AppendStreamText(text string) error {

	//support only CURRENT_FONT_TYPE_SUBSET
	textColor := c.getRoot().curr.textColor()
	grayFill := c.getRoot().curr.grayFill
	fontCountIndex := c.getRoot().curr.FontFontCount + 1
	fontSize := c.getRoot().curr.FontSize
	fontStyle := c.getRoot().curr.FontStyle
	x := c.getRoot().curr.X
	y := c.getRoot().curr.Y
	setXCount := c.getRoot().curr.setXCount
	fontSubset := c.getRoot().curr.FontISubset

	cellOption := CellOption{Transparency: c.getRoot().curr.transparency}

	cache := cacheContentText{
		fontSubset:     fontSubset,
		rectangle:      nil,
		textColor:      textColor,
		grayFill:       grayFill,
		fontCountIndex: fontCountIndex,
		fontSize:       fontSize,
		fontStyle:      fontStyle,
		setXCount:      setXCount,
		x:              x,
		y:              y,
		cellOpt:        cellOption,
		pageheight:     c.getRoot().curr.pageSize.H,
		contentType:    ContentTypeText,
		lineWidth:      c.getRoot().curr.lineWidth,
		txtColorMode:   c.getRoot().curr.txtColorMode,
	}

	var err error
	c.getRoot().curr.X, c.getRoot().curr.Y, err = c.listCache.appendContentText(cache, text)
	if err != nil {
		return err
	}

	return nil
}

//AppendStreamSubsetFont add stream of text
func (c *ContentObj) AppendStreamSubsetFont(rectangle *Rect, text string, cellOpt CellOption) error {

	textColor := c.getRoot().curr.textColor()
	grayFill := c.getRoot().curr.grayFill
	fontCountIndex := c.getRoot().curr.FontFontCount + 1
	fontSize := c.getRoot().curr.FontSize
	fontStyle := c.getRoot().curr.FontStyle
	x := c.getRoot().curr.X
	y := c.getRoot().curr.Y
	setXCount := c.getRoot().curr.setXCount
	fontSubset := c.getRoot().curr.FontISubset

	cache := cacheContentText{
		fontSubset:     fontSubset,
		rectangle:      rectangle,
		textColor:      textColor,
		grayFill:       grayFill,
		fontCountIndex: fontCountIndex,
		fontSize:       fontSize,
		fontStyle:      fontStyle,
		setXCount:      setXCount,
		x:              x,
		y:              y,
		pageheight:     c.getRoot().curr.pageSize.H,
		contentType:    ContentTypeCell,
		cellOpt:        cellOpt,
		lineWidth:      c.getRoot().curr.lineWidth,
		txtColorMode:   c.getRoot().curr.txtColorMode,
	}
	var err error
	c.getRoot().curr.X, c.getRoot().curr.Y, err = c.listCache.appendContentText(cache, text)
	if err != nil {
		return err
	}
	return nil
}

//AppendStreamLine append line
func (c *ContentObj) AppendStreamLine(x1 float64, y1 float64, x2 float64, y2 float64) {
	//h := c.getRoot().config.PageSize.H
	//c.stream.WriteString(fmt.Sprintf("%0.2f %0.2f m %0.2f %0.2f l s\n", x1, h-y1, x2, h-y2))
	var cache cacheContentLine
	cache.pageHeight = c.getRoot().curr.pageSize.H
	cache.x1 = x1
	cache.y1 = y1
	cache.x2 = x2
	cache.y2 = y2
	c.listCache.append(&cache)
}

//AppendStreamImportedTemplate append imported template
func (c *ContentObj) AppendStreamImportedTemplate(tplName string, scaleX float64, scaleY float64, tX float64, tY float64) {
	var cache cacheContentImportedTemplate
	cache.pageHeight = c.getRoot().curr.pageSize.H
	cache.tplName = tplName
	cache.scaleX = scaleX
	cache.scaleY = scaleY
	cache.tX = tX
	cache.tY = tY
	c.listCache.append(&cache)
}

func (c *ContentObj) AppendStreamRectangle(opts DrawableRectOptions) {
	cache := NewCacheContentRectangle(c.getRoot().curr.pageSize.H, opts)
	c.listCache.append(cache)
}

//AppendStreamOval append oval
func (c *ContentObj) AppendStreamOval(x1 float64, y1 float64, x2 float64, y2 float64) {
	var cache cacheContentOval
	cache.pageHeight = c.getRoot().curr.pageSize.H
	cache.x1 = x1
	cache.y1 = y1
	cache.x2 = x2
	cache.y2 = y2
	c.listCache.append(&cache)
}

//AppendStreamCurve draw curve
// - x0, y0: Start point
// - x1, y1: Control point 1
// - x2, y2: Control point 2
// - x3, y3: End point
// - style: Style of rectangule (draw and/or fill: D, F, DF, FD)
//		D or empty string: draw. This is the default value.
//		F: fill
//		DF or FD: draw and fill
func (c *ContentObj) AppendStreamCurve(x0 float64, y0 float64, x1 float64, y1 float64, x2 float64, y2 float64, x3 float64, y3 float64, style string) {
	var cache cacheContentCurve
	cache.pageHeight = c.getRoot().curr.pageSize.H
	cache.x0 = x0
	cache.y0 = y0
	cache.x1 = x1
	cache.y1 = y1
	cache.x2 = x2
	cache.y2 = y2
	cache.x3 = x3
	cache.y3 = y3
	cache.style = strings.ToUpper(strings.TrimSpace(style))
	c.listCache.append(&cache)
}

//AppendStreamSetLineWidth : set line width
func (c *ContentObj) AppendStreamSetLineWidth(w float64) {
	var cache cacheContentLineWidth
	cache.width = w
	c.listCache.append(&cache)
}

//AppendStreamSetLineType : Set linetype [solid, dashed, dotted]
func (c *ContentObj) AppendStreamSetLineType(t string) {
	var cache cacheContentLineType
	cache.lineType = t
	c.listCache.append(&cache)

}

//AppendStreamSetGrayFill  set the grayscale fills
func (c *ContentObj) AppendStreamSetGrayFill(w float64) {
	w = fixRange10(w)
	var cache cacheContentGray
	cache.grayType = grayTypeFill
	cache.scale = w
	c.listCache.append(&cache)
}

//AppendStreamSetGrayStroke  set the grayscale stroke
func (c *ContentObj) AppendStreamSetGrayStroke(w float64) {
	w = fixRange10(w)
	var cache cacheContentGray
	cache.grayType = grayTypeStroke
	cache.scale = w
	c.listCache.append(&cache)
}

//AppendStreamSetColorStroke  set the color stroke
func (c *ContentObj) AppendStreamSetColorStroke(r uint8, g uint8, b uint8) {
	var cache cacheContentColor
	cache.colorType = colorTypeStroke
	cache.r = r
	cache.g = g
	cache.b = b
	c.listCache.append(&cache)
}

//AppendStreamSetColorFill  set the color fill
func (c *ContentObj) AppendStreamSetColorFill(r uint8, g uint8, b uint8) {
	var cache cacheContentColor
	cache.colorType = colorTypeFill
	cache.r = r
	cache.g = g
	cache.b = b
	c.listCache.append(&cache)
}

func (c *ContentObj) GetCacheContentImage(index int, opts ImageOptions) *cacheContentImage {
	h := c.getRoot().curr.pageSize.H

	return &cacheContentImage{
		pageHeight:       h,
		index:            index,
		x:                opts.X,
		y:                opts.Y,
		rect:             *opts.Rect,
		crop:             opts.Crop,
		verticalFlip:     opts.VerticalFlip,
		horizontalFlip:   opts.HorizontalFlip,
		extGStateIndexes: opts.extGStateIndexes,
	}
}

//AppendStreamImage append image
func (c *ContentObj) AppendStreamImage(index int, opts ImageOptions) {
	cache := c.GetCacheContentImage(index, opts)
	c.listCache.append(cache)
}

//AppendStreamPolygon append polygon
func (c *ContentObj) AppendStreamPolygon(points []Point, style string) {
	var cache cacheContentPolygon
	cache.points = points
	cache.style = style
	cache.pageHeight = c.getRoot().curr.pageSize.H
	c.listCache.append(&cache)
}

func (c *ContentObj) appendRotate(angle, x, y float64) {
	var cache cacheContentRotate
	cache.isReset = false
	cache.pageHeight = c.getRoot().curr.pageSize.H
	cache.angle = angle
	cache.x = x
	cache.y = y
	c.listCache.append(&cache)
}

func (c *ContentObj) appendRotateReset() {
	var cache cacheContentRotate
	cache.isReset = true
	c.listCache.append(&cache)
}

//ContentObjCalTextHeight calculates height of text.
func ContentObjCalTextHeight(fontsize int) float64 {
	return (float64(fontsize) * 0.7)
}

// When setting colour and grayscales the value has to be between 0.00 and 1.00
// This function takes a float64 and returns 0.0 if it is less than 0.0 and 1.0 if it
// is more than 1.0
func fixRange10(val float64) float64 {
	if val < 0.0 {
		return 0.0
	}
	if val > 1.0 {
		return 1.0
	}
	return val
}

func convertTTFUnit2PDFUnit(n int, upem int) int {
	var ret int
	if n < 0 {
		rest1 := n % upem
		storrest := 1000 * rest1
		//ledd2 := (storrest != 0 ? rest1 / storrest : 0);
		ledd2 := 0
		if storrest != 0 {
			ledd2 = rest1 / storrest
		} else {
			ledd2 = 0
		}
		ret = -((-1000*n)/upem - int(ledd2))
	} else {
		ret = (n/upem)*1000 + ((n%upem)*1000)/upem
	}
	return ret
}


================================================
FILE: vendor/github.com/signintech/gopdf/current.go
================================================
package gopdf

//Current current state
type Current struct {
	setXCount int //many times we go func SetX()
	X         float64
	Y         float64

	//font
	IndexOfFontObj int
	CountOfFont    int
	CountOfL       int

	FontSize      int
	FontStyle     int // Regular|Bold|Italic|Underline
	FontFontCount int
	FontType      int // CURRENT_FONT_TYPE_IFONT or  CURRENT_FONT_TYPE_SUBSET

	FontISubset *SubsetFontObj // FontType == CURRENT_FONT_TYPE_SUBSET

	//page
	IndexOfPageObj int

	//img
	CountOfImg int
	//cache of image in pdf file
	ImgCaches map[int]ImageCache

	//text color mode
	txtColorMode string //color, gray

	//text color
	txtColor Rgb

	//text grayscale
	grayFill float64
	//draw grayscale
	grayStroke float64

	lineWidth float64

	//current page size
	pageSize *Rect

	//current trim box
	trimBox *Box

	sMasksMap       SMaskMap
	extGStatesMap   ExtGStatesMap
	transparency    *Transparency
	transparencyMap TransparencyMap
}

func (c *Current) setTextColor(rgb Rgb) {
	c.txtColor = rgb
}

func (c *Current) textColor() Rgb {
	return c.txtColor
}

// ImageCache is metadata for caching images.
type ImageCache struct {
	Path  string //ID or Path
	Index int
	Rect  *Rect
}

//Rgb  rgb color
type Rgb struct {
	r uint8
	g uint8
	b uint8
}

//SetR set red
func (rgb *Rgb) SetR(r uint8) {
	rgb.r = r
}

//SetG set green
func (rgb *Rgb) SetG(g uint8) {
	rgb.g = g
}

//SetB set blue
func (rgb *Rgb) SetB(b uint8) {
	rgb.b = b
}

func (rgb Rgb) equal(obj Rgb) bool {
	if rgb.r == obj.r && rgb.g == obj.g && rgb.b == obj.b {
		return true
	}
	return false
}


================================================
FILE: vendor/github.com/signintech/gopdf/device_rgb_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

//DeviceRGBObj  DeviceRGB
type DeviceRGBObj struct {
	data    []byte
	getRoot func() *GoPdf
}

func (d *DeviceRGBObj) init(funcGetRoot func() *GoPdf) {
	d.getRoot = funcGetRoot
}

func (d *DeviceRGBObj) protection() *PDFProtection {
	return d.getRoot().protection()
}

func (d *DeviceRGBObj) getType() string {
	return "devicergb"
}

//สร้าง ข้อมูลใน pdf
func (d *DeviceRGBObj) write(w io.Writer, objID int) error {

	io.WriteString(w, "<<\n")
	fmt.Fprintf(w, "/Length %d\n", len(d.data))
	io.WriteString(w, ">>\n")
	io.WriteString(w, "stream\n")
	if d.protection() != nil {
		tmp, err := rc4Cip(d.protection().objectkey(objID), d.data)
		if err != nil {
			return err
		}
		w.Write(tmp)
		io.WriteString(w, "\n")
	} else {
		w.Write(d.data)
	}
	io.WriteString(w, "endstream\n")

	return nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/embedfont_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
	"io/ioutil"
)

// EmbedFontObj is an embedded font object.
type EmbedFontObj struct {
	Data      string
	zfontpath string
	font      IFont
	getRoot   func() *GoPdf
}

func (e *EmbedFontObj) init(funcGetRoot func() *GoPdf) {
	e.getRoot = funcGetRoot
}

func (e *EmbedFontObj) protection() *PDFProtection {
	return e.getRoot().protection()
}

func (e *EmbedFontObj) write(w io.Writer, objID int) error {
	b, err := ioutil.ReadFile(e.zfontpath)
	if err != nil {
		return err
	}
	fmt.Fprintf(w, "<</Length %d\n", len(b))
	io.WriteString(w, "/Filter /FlateDecode\n")
	fmt.Fprintf(w, "/Length1 %d\n", e.font.GetOriginalsize())
	io.WriteString(w, ">>\n")
	io.WriteString(w, "stream\n")
	if e.protection() != nil {
		tmp, err := rc4Cip(e.protection().objectkey(objID), b)
		if err != nil {
			return err
		}
		w.Write(tmp)
		io.WriteString(w, "\n")
	} else {
		w.Write(b)
	}
	io.WriteString(w, "\nendstream\n")
	return nil
}

func (e *EmbedFontObj) getType() string {
	return "EmbedFont"
}

// SetFont sets the font of an embedded font object.
func (e *EmbedFontObj) SetFont(font IFont, zfontpath string) {
	e.font = font
	e.zfontpath = zfontpath
}


================================================
FILE: vendor/github.com/signintech/gopdf/encoding_obj.go
================================================
package gopdf

import (
	"io"
)

// EncodingObj is a font object.
type EncodingObj struct {
	font IFont
}

func (e *EncodingObj) init(funcGetRoot func() *GoPdf) {

}
func (e *EncodingObj) getType() string {
	return "Encoding"
}
func (e *EncodingObj) write(w io.Writer, objID int) error {
	io.WriteString(w, "<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [")
	io.WriteString(w, e.font.GetDiff())
	io.WriteString(w, "]>>\n")
	return nil
}

// SetFont sets the font of an encoding object.
func (e *EncodingObj) SetFont(font IFont) {
	e.font = font
}

// GetFont gets the font from an encoding object.
func (e *EncodingObj) GetFont() IFont {
	return e.font
}


================================================
FILE: vendor/github.com/signintech/gopdf/encryption_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
	"strings"
)

//EncryptionObj  encryption object res
type EncryptionObj struct {
	uValue []byte //U entry in pdf document
	oValue []byte //O entry in pdf document
	pValue int    //P entry in pdf document
}

func (e *EncryptionObj) init(func() *GoPdf) {

}

func (e *EncryptionObj) getType() string {
	return "Encryption"
}

func (e *EncryptionObj) write(w io.Writer, objID int) error {
	io.WriteString(w, "<<\n")
	io.WriteString(w, "/Filter /Standard\n")
	io.WriteString(w, "/V 1\n")
	io.WriteString(w, "/R 2\n")
	fmt.Fprintf(w, "/O (%s)\n", e.escape(e.oValue))
	fmt.Fprintf(w, "/U (%s)\n", e.escape(e.uValue))
	fmt.Fprintf(w, "/P %d\n", e.pValue)
	io.WriteString(w, ">>\n")
	return nil
}

func (e *EncryptionObj) escape(b []byte) string {
	s := string(b)
	s = strings.Replace(s, "\\", "\\\\", -1)
	s = strings.Replace(s, "(", "\\(", -1)
	s = strings.Replace(s, ")", "\\)", -1)
	s = strings.Replace(s, "\r", "\\r", -1)
	return s
}


================================================
FILE: vendor/github.com/signintech/gopdf/ext_g_state_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
	"sync"

	"github.com/pkg/errors"
)

// TODO: add all fields https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf 8.4.5 page 128
type ExtGState struct {
	Index      int
	ca         *float64
	CA         *float64
	BM         *BlendModeType
	SMaskIndex *int
}

type ExtGStateOptions struct {
	StrokingCA    *float64
	NonStrokingCa *float64
	BlendMode     *BlendModeType
	SMaskIndex    *int
}

func (extOpt ExtGStateOptions) GetId() string {
	id := ""
	if extOpt.StrokingCA != nil {
		id += fmt.Sprintf("CA_%.3f;", *extOpt.StrokingCA)
	}
	if extOpt.NonStrokingCa != nil {
		id += fmt.Sprintf("ca_%.3f;", *extOpt.NonStrokingCa)
	}
	if extOpt.BlendMode != nil {
		id += fmt.Sprintf("BM_%s;", *extOpt.BlendMode)
	}
	if extOpt.SMaskIndex != nil {
		id += fmt.Sprintf("SMask_%d_0_R;", *extOpt.SMaskIndex)
	}

	return id
}

func GetCachedExtGState(opts ExtGStateOptions, gp *GoPdf) (ExtGState, error) {
	extGState, ok := gp.curr.extGStatesMap.Find(opts)
	if !ok {
		extGState = ExtGState{
			BM:         opts.BlendMode,
			CA:         opts.StrokingCA,
			ca:         opts.NonStrokingCa,
			SMaskIndex: opts.SMaskIndex,
		}

		extGState.Index = gp.addObj(extGState)

		pdfObj := gp.pdfObjs[gp.indexOfProcSet]
		procset, ok := pdfObj.(*ProcSetObj)
		if !ok {
			return ExtGState{}, errors.New("can't convert pdfobject to procsetobj")
		}

		procset.ExtGStates = append(procset.ExtGStates, ExtGS{Index: extGState.Index})

		gp.curr.extGStatesMap.Save(opts.GetId(), extGState)

		//extGState = extGState
	}

	return extGState, nil
}

func (egs ExtGState) init(func() *GoPdf) {}

func (egs ExtGState) getType() string {
	return "ExtGState"
}

func (egs ExtGState) write(w io.Writer, objID int) error {
	content := "<<\n"
	content += "\t/Type /ExtGState\n"

	if egs.ca != nil {
		content += fmt.Sprintf("\t/ca %.3F\n", *egs.ca)
	}
	if egs.CA != nil {
		content += fmt.Sprintf("\t/CA %.3F\n", *egs.CA)
	}
	if egs.BM != nil {
		content += fmt.Sprintf("\t/BM %s\n", *egs.BM)
	}

	if egs.SMaskIndex != nil {
		content += fmt.Sprintf("\t/SMask %d 0 R\n", *egs.SMaskIndex+1)
	}

	content += ">>\n"

	if _, err := io.WriteString(w, content); err != nil {
		return err
	}

	return nil
}

type ExtGStatesMap struct {
	syncer sync.Mutex
	table  map[string]ExtGState
}

func NewExtGStatesMap() ExtGStatesMap {
	return ExtGStatesMap{
		syncer: sync.Mutex{},
		table:  make(map[string]ExtGState),
	}
}

func (extm *ExtGStatesMap) Find(extGState ExtGStateOptions) (ExtGState, bool) {
	key := extGState.GetId()

	extm.syncer.Lock()
	defer extm.syncer.Unlock()

	t, ok := extm.table[key]
	if !ok {
		return ExtGState{}, false
	}

	return t, ok

}

func (tm *ExtGStatesMap) Save(id string, extGState ExtGState) ExtGState {
	tm.syncer.Lock()
	defer tm.syncer.Unlock()

	tm.table[id] = extGState

	return extGState
}


================================================
FILE: vendor/github.com/signintech/gopdf/font_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

//FontObj font obj
type FontObj struct {
	Family string
	//Style string
	//Size int
	IsEmbedFont bool

	indexObjWidth          int
	indexObjFontDescriptor int
	indexObjEncoding       int

	Font        IFont
	CountOfFont int
}

func (f *FontObj) init(funcGetRoot func() *GoPdf) {
	f.IsEmbedFont = false
	//me.CountOfFont = -1
}

func (f *FontObj) write(w io.Writer, objID int) error {
	baseFont := f.Family
	if f.Font != nil {
		baseFont = f.Font.GetName()
	}

	io.WriteString(w, "<<\n")
	fmt.Fprintf(w, "  /Type /%s\n", f.getType())
	io.WriteString(w, "  /Subtype /TrueType\n")
	fmt.Fprintf(w, "  /BaseFont /%s\n", baseFont)
	if f.IsEmbedFont {
		io.WriteString(w, "  /FirstChar 32 /LastChar 255\n")
		fmt.Fprintf(w, "  /Widths %d 0 R\n", f.indexObjWidth)
		fmt.Fprintf(w, "  /FontDescriptor %d 0 R\n", f.indexObjFontDescriptor)
		fmt.Fprintf(w, "  /Encoding %d 0 R\n", f.indexObjEncoding)
	}
	io.WriteString(w, ">>\n")
	return nil
}

func (f *FontObj) getType() string {
	return "Font"
}

// SetIndexObjWidth sets the width of a font object.
func (f *FontObj) SetIndexObjWidth(index int) {
	f.indexObjWidth = index
}

// SetIndexObjFontDescriptor sets the font descriptor.
func (f *FontObj) SetIndexObjFontDescriptor(index int) {
	f.indexObjFontDescriptor = index
}

// SetIndexObjEncoding sets the encoding.
func (f *FontObj) SetIndexObjEncoding(index int) {
	f.indexObjEncoding = index
}


================================================
FILE: vendor/github.com/signintech/gopdf/font_option.go
================================================
package gopdf

import (
	"strings"
)

//Regular - font style regular
const Regular = 0 //000000
//Italic - font style italic
const Italic = 1 //000001
//Bold - font style bold
const Bold = 2 //000010
//Underline - font style underline
const Underline = 4 //000100

func getConvertedStyle(fontStyle string) (style int) {
	fontStyle = strings.ToUpper(fontStyle)
	if strings.Contains(fontStyle, "B") {
		style = style | Bold
	}
	if strings.Contains(fontStyle, "I") {
		style = style | Italic
	}
	if strings.Contains(fontStyle, "U") {
		style = style | Underline
	}
	return
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontconverthelper.go
================================================
package gopdf

import (
	"strconv"
	//"fmt"
	"bytes"
)

// FontConvertHelperCw2Str converts main ASCII characters of a FontCW to a string.
func FontConvertHelperCw2Str(cw FontCw) string {
	buff := new(bytes.Buffer)
	buff.WriteString(" ")
	i := 32
	for i <= 255 {
		buff.WriteString(strconv.Itoa(cw[byte(i)]) + " ")
		i++
	}
	return buff.String()
}

// FontConvertHelper_Cw2Str converts main ASCII characters of a FontCW to a string. (for backward compatibility)
// Deprecated: Use FontConvertHelperCw2Str(cw FontCw) instead
func FontConvertHelper_Cw2Str(cw FontCw) string {
	return FontConvertHelperCw2Str(cw)
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontdescriptor_obj.go
================================================
package gopdf

import (
	"fmt"
	"io"
)

// FontDescriptorObj is a font descriptor object.
type FontDescriptorObj struct {
	font              IFont
	fontFileObjRelate string
}

func (f *FontDescriptorObj) init(funcGetRoot func() *GoPdf) {

}

func (f *FontDescriptorObj) write(w io.Writer, objID int) error {

	fmt.Fprintf(w, "<</Type /FontDescriptor /FontName /%s ", f.font.GetName())
	descs := f.font.GetDesc()
	i := 0
	max := len(descs)
	for i < max {
		fmt.Fprintf(w, "/%s %s ", descs[i].Key, descs[i].Val)
		i++
	}

	if f.getType() == "Type1" {
		io.WriteString(w, "/FontFile ")
	} else {
		io.WriteString(w, "/FontFile2 ")
	}

	io.WriteString(w, f.fontFileObjRelate)
	io.WriteString(w, ">>\n")

	return nil
}

func (f *FontDescriptorObj) getType() string {
	return "FontDescriptor"
}

// SetFont sets the font in descriptor.
func (f *FontDescriptorObj) SetFont(font IFont) {
	f.font = font
}

// GetFont gets font from descriptor.
func (f *FontDescriptorObj) GetFont() IFont {
	return f.font
}

// SetFontFileObjRelate ???
func (f *FontDescriptorObj) SetFontFileObjRelate(relate string) {
	f.fontFileObjRelate = relate
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontmaker/core/fontmaker.go
================================================
package core

import (
	"bufio"
	"bytes"
	"compress/zlib"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

//ErrFontLicenseDoesNotAllowEmbedding Font license does not allow embedding
var ErrFontLicenseDoesNotAllowEmbedding = errors.New("Font license does not allow embedding")

//FontMaker font maker
type FontMaker struct {
	results []string
}

//GetResults get result
func (f *FontMaker) GetResults() []string {
	return f.results
}

//NewFontMaker new FontMaker
func NewFontMaker() *FontMaker {
	return new(FontMaker)
}

func (f *FontMaker) MakeFont(fontpath string, mappath string, encode string, outfolderpath string) error {

	encodingpath := mappath + "/" + encode + ".map"

	//read font file
	if _, err := os.Stat(fontpath); os.IsNotExist(err) {
		return err
	}

	fileext := filepath.Ext(fontpath)
	if strings.ToLower(fileext) != ".ttf" {
		//now support only ttf :-P
		return errors.New("support only ttf ")
	}

	fontmaps, err := f.LoadMap(encodingpath)
	if err != nil {
		return err
	}

	info, err := f.GetInfoFromTrueType(fontpath, fontmaps)
	if err != nil {
		return err
	}

	//zip
	basename := filepath.Base(fontpath)
	tmp := strings.Split(basename, ".")
	basename = strings.Replace(tmp[0], " ", "_", -1)
	gzfilename := basename + ".z"

	var buff bytes.Buffer
	gzipwriter := zlib.NewWriter(&buff)

	fontbytes, err := ioutil.ReadFile(fontpath)
	if err != nil {
		return err
	}

	_, err = gzipwriter.Write(fontbytes)
	if err != nil {
		return err
	}
	gzipwriter.Close()
	err = ioutil.WriteFile(outfolderpath+"/"+gzfilename, buff.Bytes(), 0644)
	if err != nil {
		return err
	}
	info.PushString("File", gzfilename)
	f.results = append(f.results, fmt.Sprintf("Save Z file at %s.", outfolderpath+"/"+gzfilename))

	//Definition File
	_, err = f.MakeDefinitionFile(f.GoStructName(basename), mappath, outfolderpath+"/"+basename+".font.go", encode, fontmaps, info)
	if err != nil {
		return err
	}

	return nil
}

func (f *FontMaker) GoStructName(name string) string {
	goname := strings.ToUpper(name[0:1]) + name[1:]
	return goname
}

func (f *FontMaker) MakeDefinitionFile(gofontname string, mappath string, exportfile string, encode string, fontmaps []FontMap, info TtfInfo) (string, error) {

	fonttype := "TrueType"
	str := ""
	str += "package fonts //change this\n"
	str += "import (\n"
	str += "	\"github.com/signintech/gopdf\"\n"
	str += ")\n"
	str += "type " + gofontname + " struct {\n"
	str += "\tfamily string\n"
	str += "\tfonttype string\n"
	str += "\tname string\n"
	str += "\tdesc  []gopdf.FontDescItem\n"
	str += "\tup int\n"
	str += "\tut int\n"
	str += "\tcw gopdf.FontCw\n"
	str += "\tenc string\n"
	str += "\tdiff string\n"
	str += "}\n"

	str += "func (me * " + gofontname + ") Init(){\n"
	widths, err := info.GetMapIntInt64("Widths")
	if err != nil {
		return "", err
	}

	tmpStr, err := f.MakeWidthArray(widths)
	if err != nil {
		return "", err
	}
	str += tmpStr

	tmpInt64, err := info.GetInt64("UnderlinePosition")
	if err != nil {
		return "", err
	}
	str += fmt.Sprintf("\tme.up = %d\n", tmpInt64)

	tmpInt64, err = info.GetInt64("UnderlineThickness")
	if err != nil {
		return "", err
	}
	str += fmt.Sprintf("\tme.ut = %d\n", tmpInt64)

	str += "\tme.fonttype = \"" + fonttype + "\"\n"

	tmpStr, err = info.GetString("FontName")
	if err != nil {
		return "", err
	}
	str += fmt.Sprintf("\tme.name = \"%s\"\n", tmpStr)

	str += "\tme.enc = \"" + encode + "\"\n"
	diff, err := f.MakeFontEncoding(mappath, fontmaps)
	if err != nil {
		return "", err
	}
	if diff != "" {
		str += "\tme.diff = \"" + diff + "\"\n"
	}

	fd, err := f.MakeFontDescriptor(info)
	if err != nil {
		return "", err
	}
	str += fd

	str += "}\n"

	str += "func (me * " + gofontname + ")GetType() string{\n"
	str += "\treturn me.fonttype\n"
	str += "}\n"
	str += "func (me * " + gofontname + ")GetName() string{\n"
	str += "\treturn me.name\n"
	str += "}	\n"
	str += "func (me * " + gofontname + ")GetDesc() []gopdf.FontDescItem{\n"
	str += "\treturn me.desc\n"
	str += "}\n"
	str += "func (me * " + gofontname + ")GetUp() int{\n"
	str += "\treturn me.up\n"
	str += "}\n"
	str += "func (me * " + gofontname + ")GetUt()  int{\n"
	str += "\treturn me.ut\n"
	str += "}\n"
	str += "func (me * " + gofontname + ")GetCw() gopdf.FontCw{\n"
	str += "\treturn me.cw\n"
	str += "}\n"
	str += "func (me * " + gofontname + ")GetEnc() string{\n"
	str += "\treturn me.enc\n"
	str += "}\n"
	str += "func (me * " + gofontname + ")GetDiff() string {\n"
	str += "\treturn me.diff\n"
	str += "}\n"

	str += "func (me * " + gofontname + ") GetOriginalsize() int{\n"
	str += "\treturn 98764\n"
	str += "}\n"

	str += "func (me * " + gofontname + ")  SetFamily(family string){\n"
	str += "\tme.family = family\n"
	str += "}\n"

	str += "func (me * " + gofontname + ") 	GetFamily() string{\n"
	str += "\treturn me.family\n"
	str += "}\n"

	err = ioutil.WriteFile(exportfile, []byte(str), 0666)
	if err != nil {
		return "", err
	}
	f.results = append(f.results, fmt.Sprintf("Save GO file at %s.", exportfile))
	return str, nil
}

func (f *FontMaker) MakeFontDescriptor(info TtfInfo) (string, error) {

	fd := ""
	fd = "\tme.desc = make([]gopdf.FontDescItem,8)\n"

	// Ascent
	ascender, err := info.GetInt64("Ascender")
	if err != nil {
		return "", err
	}
	fd += fmt.Sprintf("\tme.desc[0] =  gopdf.FontDescItem{ Key:\"Ascent\",Val : \"%d\" }\n", ascender)

	// Descent
	descender, err := info.GetInt64("Descender")
	if err != nil {
		return "", err
	}
	fd += fmt.Sprintf("\tme.desc[1] =  gopdf.FontDescItem{ Key: \"Descent\", Val : \"%d\" }\n", descender)

	// CapHeight
	capHeight, err := info.GetInt64("CapHeight")
	if err == nil {
		fd += fmt.Sprintf("\tme.desc[2] =  gopdf.FontDescItem{ Key:\"CapHeight\", Val :  \"%d\" }\n", capHeight)
	} else if err == ERROR_NO_KEY_FOUND {
		fd += fmt.Sprintf("\tme.desc[2] =  gopdf.FontDescItem{ Key:\"CapHeight\", Val :  \"%d\" }\n", ascender)
	} else {
		return "", err
	}

	// Flags
	flags := 0
	isFixedPitch, err := info.GetBool("IsFixedPitch")
	if err != nil {
		return "", err
	}

	if isFixedPitch {
		flags += 1 << 0
	}
	flags += 1 << 5
	italicAngle, err := info.GetInt64("ItalicAngle")
	if italicAngle != 0 {
		flags += 1 << 6
	}
	fd += fmt.Sprintf("\tme.desc[3] =  gopdf.FontDescItem{ Key: \"Flags\", Val :  \"%d\" }\n", flags)
	//fmt.Printf("\n----\n")
	// FontBBox
	fbb, err := info.GetInt64s("FontBBox")
	if err != nil {
		return "", err
	}
	fd += fmt.Sprintf("\tme.desc[4] =  gopdf.FontDescItem{ Key:\"FontBBox\", Val :  \"[%d %d %d %d]\" }\n", fbb[0], fbb[1], fbb[2], fbb[3])

	// ItalicAngle
	fd += fmt.Sprintf("\tme.desc[5] =  gopdf.FontDescItem{ Key:\"ItalicAngle\", Val :  \"%d\" }\n", italicAngle)

	// StemV
	stdVW, err := info.GetInt64("StdVW")
	issetStdVW := false
	if err == nil {
		issetStdVW = true
	} else if err == ERROR_NO_KEY_FOUND {
		issetStdVW = false
	} else {
		return "", err
	}

	bold, err := info.GetBool("Bold")
	if err != nil {
		return "", err
	}

	stemv := int(0)
	if issetStdVW {
		stemv = stdVW
	} else if bold {
		stemv = 120
	} else {
		stemv = 70
	}
	fd += fmt.Sprintf("\tme.desc[6] =  gopdf.FontDescItem{ Key:\"StemV\", Val :  \"%d\" }\n ", stemv)

	// MissingWidth
	missingWidth, err := info.GetInt64("MissingWidth")
	if err != nil {
		return "", err
	}
	fd += fmt.Sprintf("\tme.desc[7] =  gopdf.FontDescItem{ Key:\"MissingWidth\", Val :  \"%d\" } \n ", missingWidth)
	return fd, nil
}

func (f *FontMaker) MakeFontEncoding(mappath string, fontmaps []FontMap) (string, error) {

	refpath := mappath + "/cp1252.map"
	ref, err := f.LoadMap(refpath)
	if err != nil {
		return "", err
	}
	s := ""
	last := 0
	for c := 0; c <= 255; c++ {
		if fontmaps[c].Name != ref[c].Name {
			if c != last+1 {
				s += fmt.Sprintf("%d ", c)
			}
			last = c
			s += "/" + fontmaps[c].Name + " "
		}
	}
	return strings.TrimSpace(s), nil
}

func (f *FontMaker) MakeWidthArray(widths map[int]int) (string, error) {

	str := "\tme.cw = make(gopdf.FontCw)\n"
	for c := 0; c <= 255; c++ {
		str += "\tme.cw["
		chr := string(c)
		if chr == "\"" {
			str += "gopdf.ToByte(\"\\\"\")"
		} else if chr == "\\" {
			str += "gopdf.ToByte(\"\\\\\")"
		} else if c >= 32 && c <= 126 {
			str += "gopdf.ToByte(\"" + chr + "\")"
		} else {
			str += fmt.Sprintf("gopdf.Chr(%d)", c)
		}
		str += fmt.Sprintf("]=%d\n", widths[c])
	}
	return str, nil
}

func (f *FontMaker) FileSize(path string) (int64, error) {

	file, err := os.Open(path)
	if err != nil {
		return -1, err
	}
	defer file.Close()

	// get the file size
	stat, err := file.Stat()
	if err != nil {
		return -1, err
	}
	return stat.Size(), nil
}

func (f *FontMaker) GetInfoFromTrueType(fontpath string, fontmaps []FontMap) (TtfInfo, error) {

	var parser TTFParser
	err := parser.Parse(fontpath)
	if err != nil {
		return nil, err
	}

	if !parser.Embeddable {
		return nil, ErrFontLicenseDoesNotAllowEmbedding
	}

	info := NewTtfInfo()

	fileContent, err := ioutil.ReadFile(fontpath)
	if err != nil {
		return nil, err
	}
	info.PushBytes("Data", fileContent)

	size, err := f.FileSize(fontpath)
	if err != nil {
		return nil, err
	}
	info.PushInt64("OriginalSize", size)

	k := float64(1000.0 / float64(parser.unitsPerEm))
	info.PushString("FontName", parser.postScriptName)
	info.PushBool("Bold", parser.Bold)
	info.PushInt("ItalicAngle", parser.italicAngle)
	info.PushBool("IsFixedPitch", parser.isFixedPitch)
	info.PushInt("Ascender", f.MultiplyAndRound(k, parser.typoAscender))
	info.PushInt("Descender", f.MultiplyAndRound(k, parser.typoDescender))
	info.PushInt("UnderlineThickness", f.MultiplyAndRound(k, parser.underlineThickness))
	info.PushInt("UnderlinePosition", f.MultiplyAndRound(k, parser.underlinePosition))
	fontBBoxs := []int{
		f.MultiplyAndRound(k, parser.xMin),
		f.MultiplyAndRound(k, parser.yMin),
		f.MultiplyAndRound(k, parser.xMax),
		f.MultiplyAndRound(k, parser.yMax),
	}
	info.PushInt64s("FontBBox", fontBBoxs)
	info.PushInt("CapHeight", f.MultiplyAndRound(k, parser.capHeight))
	missingWidth := f.MultiplyAndRoundWithUInt64(k, parser.widths[0])
	info.PushInt("MissingWidth", missingWidth)

	widths := make(map[int]int)
	max := 256
	c := 0
	for c < max {
		widths[c] = missingWidth
		c++
	}

	c = 0 //reset
	for c < max {
		if fontmaps[c].Name != ".notdef" {
			uv := fontmaps[c].Uv
			if val, ok := parser.chars[int(uv)]; ok {
				w := parser.widths[val]
				widths[c] = f.MultiplyAndRoundWithUInt64(k, w)
			} else {
				f.results = append(f.results, fmt.Sprintf("Warning: Character %s (%d) is missing", fontmaps[c].Name, fontmaps[c].Uv))
			}
		}
		c++
	}
	info.PushMapIntInt64("Widths", widths)

	return info, nil
}

func (f *FontMaker) MultiplyAndRoundWithUInt64(k float64, v uint) int {
	r := k * float64(v)
	return f.Round(r)
}

func (f *FontMaker) MultiplyAndRound(k float64, v int) int {
	r := k * float64(v)
	return f.Round(r)
}

func (f *FontMaker) Round(value float64) int {
	return Round(value)
}

func (f *FontMaker) LoadMap(encodingpath string) ([]FontMap, error) {

	if _, err := os.Stat(encodingpath); os.IsNotExist(err) {
		return nil, err
	}

	var fontmaps []FontMap
	i := 0
	max := 256
	for i < max {
		fontmaps = append(fontmaps, FontMap{Uv: -1, Name: ".notdef"})
		i++
	}

	file, err := os.Open(encodingpath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanLines)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		e := strings.Split(line, " ")
		strC := (e[0])[1:]
		strUv := (e[1])[2:]
		c, err := strconv.ParseInt(strC, 16, 0)
		if err != nil {
			return nil, err
		}
		uv, err := strconv.ParseInt(strUv, 16, 0)
		if err != nil {
			return nil, err
		}
		name := e[2]
		//fmt.Println("strC = "+strC+"strUv = "+strUv+" c=%d , uv= %d", c, uv)
		fontmaps[c].Name = name
		fontmaps[c].Uv = int(uv)
	}

	return fontmaps, nil
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontmaker/core/fontmap.go
================================================
package core

type FontMap struct {
	Uv   int
	Name string
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontmaker/core/kern_table.go
================================================
package core

//KernTable https://www.microsoft.com/typography/otspec/kern.htm
type KernTable struct {
	Version uint //for debug
	NTables uint //for debug
	Kerning KernMap
}

//KernMap kerning map   map[left]KernValue
type KernMap map[uint]KernValue

//KernValue kerning values  map[right]value
type KernValue map[uint]int16

//ValueByRight  get value by right
func (k KernValue) ValueByRight(right uint) (bool, int16) {
	if val, ok := k[uint(right)]; ok {
		return true, val
	}
	return false, 0
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontmaker/core/math.go
================================================
package core

func Round(value float64) int {
	if value < 0.0 {
		value -= 0.5
	} else {
		value += 0.5
	}
	return int(value)
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontmaker/core/table_directory_entry.go
================================================
package core

type TableDirectoryEntry struct {
	CheckSum uint
	Offset   uint
	Length   uint
}

func (t TableDirectoryEntry) PaddedLength() int {
	l := int(t.Length)
	return (l + 3) & ^3
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontmaker/core/ttf_info.go
================================================
package core

import (
	"errors"
)

var ERROR_NO_KEY_FOUND = errors.New("no key found")
var ERROR_NO_GET_WRONG_TYPE = errors.New("get wrong type")

type TtfInfo map[string]interface{}

func (t TtfInfo) PushString(key string, val string) {
	t[key] = val
}

func (t TtfInfo) PushBytes(key string, val []byte) {
	t[key] = val
}

func (t TtfInfo) PushInt64(key string, val int64) {
	t[key] = val
}

func (t TtfInfo) PushInt(key string, val int) {
	t[key] = val
}

func (t TtfInfo) PushUInt64(key string, val uint) {
	t[key] = val
}

func (t TtfInfo) PushBool(key string, val bool) {
	t[key] = val
}

func (t TtfInfo) PushInt64s(key string, val []int) {
	t[key] = val
}

func (t TtfInfo) PushMapIntInt64(key string, val map[int]int) {
	t[key] = val
}

func (t TtfInfo) GetBool(key string) (bool, error) {
	if val, ok := t[key]; ok {

		if m, ok := val.(bool); ok {
			/* act on str */
			return m, nil
		} else {
			return false, ERROR_NO_GET_WRONG_TYPE
		}
	} else {
		return false, ERROR_NO_KEY_FOUND
	}
}

func (t TtfInfo) GetString(key string) (string, error) {
	if val, ok := t[key]; ok {

		if m, ok := val.(string); ok {
			/* act on str */
			return m, nil
		} else {
			return "", ERROR_NO_GET_WRONG_TYPE
		}
	} else {
		return "", ERROR_NO_KEY_FOUND
	}
}

func (t TtfInfo) GetInt64(key string) (int, error) {
	if val, ok := t[key]; ok {

		if m, ok := val.(int); ok {
			/* act on str */
			return m, nil
		} else {
			return 0, ERROR_NO_GET_WRONG_TYPE
		}
	} else {
		return 0, ERROR_NO_KEY_FOUND
	}
}

func (t TtfInfo) GetInt64s(key string) ([]int, error) {
	if val, ok := t[key]; ok {

		if m, ok := val.([]int); ok {
			/* act on str */
			return m, nil
		} else {
			return nil, ERROR_NO_GET_WRONG_TYPE
		}
	} else {
		return nil, ERROR_NO_KEY_FOUND
	}
}

func (t TtfInfo) GetMapIntInt64(key string) (map[int]int, error) {
	if val, ok := t[key]; ok {

		if m, ok := val.(map[int]int); ok {
			/* act on str */
			return m, nil
		} else {
			return nil, ERROR_NO_GET_WRONG_TYPE
		}
	} else {
		return nil, ERROR_NO_KEY_FOUND
	}
}

func NewTtfInfo() TtfInfo {
	info := make(TtfInfo)
	return info
}


================================================
FILE: vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser.go
================================================
package core

import (
	//"encoding/binary"
	//"encoding/hex"
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"regexp"
	"strconv"
	"strings"
)

var ERROR_NO_UNICODE_ENCODING_FOUND = errors.New("No Unicode encoding found")
var ERROR_UNEXPECTED_SUBTABLE_FORMAT = errors.New("Unexpected subtable format")
var ERROR_INCORRECT_MAGIC_NUMBER = errors.New("Incorrect magic number")
var ERROR_POSTSCRIPT_NAME_NOT_FOUND = errors.New("PostScript name not found")

//TTFParser true type font parser
type TTFParser struct {
	tables map[string]TableDirectoryEntry
	//head
	unitsPerEm       uint
	xMin             int
	yMin             int
	xMax             int
	yMax             int
	indexToLocFormat int
	//Hhea
	numberOfHMetrics uint
	ascender         int
	descender        int
	//end Hhea

	numGlyphs      uint
	widths         []uint
	chars          map[int]uint
	postScriptName string

	//os2
	os2Version    uint
	Embeddable    bool
	Bold          bool
	typoAscender  int
	typoDescender int
	capHeight     int
	sxHeight      int

	//post
	italicAngle        int
	underlinePosition  int
	underlineThickness int
	isFixedPitch       bool
	sTypoLineGap       int
	usWinAscent        uint
	usWinDescent       uint

	//cmap
	IsShortIndex  bool
	LocaTable     []uint
	SegCount      uint
	StartCount    []uint
	EndCount      []uint
	IdRangeOffset []uint
	IdDelta       []uint
	GlyphIdArray  []uint
	symbol        bool

	//cmap format 12
	groupingTables []CmapFormat12GroupingTable

	//data of font
	cachedFontData []byte

	//kerning
	useKerning bool //user config for use or not use kerning
	kern       *KernTable
}

var Symbolic = 1 << 2
var Nonsymbolic = (1 << 5)

//Kern get KernTable
func (t *TTFParser) Kern() *KernTable {
	return t.kern
}

//UnderlinePosition postion of underline
func (t *TTFParser) UnderlinePosition() int {
	return t.underlinePosition
}

//GroupingTables get cmap format12 grouping table
func (t *TTFParser) GroupingTables() []CmapFormat12GroupingTable {
	return t.groupingTables
}

//UnderlineThickness thickness of underline
func (t *TTFParser) UnderlineThickness() int {
	return t.underlineThickness
}

func (t *TTFParser) XHeight() int {
	if t.os2Version >= 2 && t.sxHeight != 0 {
		return t.sxHeight
	} else {
		return int((0.66) * float64(t.ascender))
	}
}

func (t *TTFParser) XMin() int {
	return t.xMin
}

func (t *TTFParser) YMin() int {
	return t.yMin
}

func (t *TTFParser) XMax() int {
	return t.xMax
}

func (t *TTFParser) YMax() int {
	return t.yMax
}

func (t *TTFParser) ItalicAngle() int {
	return t.italicAngle
}

func (t *TTFParser) Flag() int {
	flag := 0
	if t.symbol {
		flag |= Symbolic
	} else {
		flag |= Nonsymbolic
	}
	return flag
}

func (t *TTFParser) Ascender() int {
	if t.typoAscender == 0 {
		return t.ascender
	}
	return int(t.usWinAscent)
}

func (t *TTFParser) Descender() int {
	if t.typoDescender == 0 {
		return t.descender
	}
	descender := int(t.usWinDescent)
	if t.descender < 0 {
		descender = descender * (-1)
	}
	return descender
}

func (t *TTFParser) TypoAscender() int {
	return t.typoAscender
}

func (t *TTFParser) TypoDescender() int {
	return t.typoDescender
}

//CapHeight https://en.wikipedia.org/wiki/Cap_height
func (t *TTFParser) CapHeight() int {
	return t.capHeight
}

//NumGlyphs number of glyph
func (t *TTFParser) NumGlyphs() uint {
	return t.numGlyphs
}

func (t *TTFParser) UnitsPerEm() uint {
	return t.unitsPerEm
}

func (t *TTFParser) NumberOfHMetrics() uint {
	return t.numberOfHMetrics
}

func (t *TTFParser) Widths() []uint {
	return t.widths
}

func (t *TTFParser) Chars() map[int]uint {
	return t.chars
}

func (t *TTFParser) GetTables() map[string]TableDirectoryEntry {
	return t.tables
}

//SetUseKerning set useKerning must set before Parse
func (t *TTFParser) SetUseKerning(use bool) {
	t.useKerning = use
}

//Parse parse
func (t *TTFParser) Parse(filepath string) error {
	data, err := ioutil.ReadFile(filepath)
	if err != nil {
		return err
	}
	return t.ParseFontData(data)
}

//ParseByReader parse by io.reader
func (t *TTFParser) ParseByReader(rd io.Reader) error {
	fontData, err := ioutil.ReadAll(rd)
	if err != nil {
		return err
	}

	return t.ParseFontData(fontData)
}

// ParseFontData parses font data.
func (t *TTFParser) ParseFontData(fontData []byte) error {
	fd := bytes.NewReader(fontData)

	version, err := t.Read(fd, 4)
	if err != nil {
		return err
	}
	if !bytes.Equal(version, []byte{0x00, 0x01, 0x00, 0x00}) {
		return errors.New("Unrecognized file (font) format")
	}

	i := uint(0)
	numTables, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}
	t.Skip(fd, 3*2) //searchRange, entrySelector, rangeShift
	t.tables = make(map[string]TableDirectoryEntry)
	for i < numTables {

		tag, err := t.Read(fd, 4)
		if err != nil {
			return err
		}

		checksum, err := t.ReadULong(fd)
		if err != nil {
			return err
		}

		offset, err := t.ReadULong(fd)
		if err != nil {
			return err
		}

		length, err := t.ReadULong(fd)
		if err != nil {
			return err
		}
		//fmt.Printf("\n\ntag=%s  \nOffset = %d\n", tag, offset)
		var table TableDirectoryEntry
		table.Offset = uint(offset)
		table.CheckSum = checksum
		table.Length = length
		//fmt.Printf("\n\ntag=%s  \nOffset = %d\nPaddedLength =%d\n\n ", tag, table.Offset, table.PaddedLength())
		t.tables[t.BytesToString(tag)] = table
		i++
	}

	err = t.ParseHead(fd)
	if err != nil {
		return err
	}

	err = t.ParseHhea(fd)
	if err != nil {
		return err
	}

	err = t.ParseMaxp(fd)
	if err != nil {
		return err
	}
	err = t.ParseHmtx(fd)
	if err != nil {
		return err
	}
	err = t.ParseCmap(fd)
	if err != nil {
		return err
	}
	err = t.ParseName(fd)
	if err != nil {
		return err
	}
	err = t.ParseOS2(fd)
	if err != nil {
		return err
	}
	err = t.ParsePost(fd)
	if err != nil {
		return err
	}
	err = t.ParseLoca(fd)
	if err != nil {
		return err
	}

	if t.useKerning {
		err = t.Parsekern(fd)
		if err != nil {
			return err
		}
	}

	t.cachedFontData = fontData

	return nil
}

func (t *TTFParser) FontData() []byte {
	return t.cachedFontData
}

//ParseLoca parse loca table https://www.microsoft.com/typography/otspec/loca.htm
func (t *TTFParser) ParseLoca(fd *bytes.Reader) error {

	t.IsShortIndex = false
	if t.indexToLocFormat == 0 {
		t.IsShortIndex = true
	}

	//fmt.Printf("indexToLocFormat = %d\n", me.indexToLocFormat)
	err := t.Seek(fd, "loca")
	if err != nil {
		return err
	}
	var locaTable []uint
	table := t.tables["loca"]
	if t.IsShortIndex {
		//do ShortIndex
		entries := table.Length / 2
		i := uint(0)
		for i < entries {
			item, err := t.ReadUShort(fd)
			if err != nil {
				return err
			}
			locaTable = append(locaTable, item*2)
			i++
		}
	} else {
		entries := table.Length / 4
		i := uint(0)
		for i < entries {
			item, err := t.ReadULong(fd)
			if err != nil {
				return err
			}
			locaTable = append(locaTable, item)
			i++
		}
	}
	t.LocaTable = locaTable
	return nil
}

//ParsePost parse post table https://www.microsoft.com/typography/otspec/post.htm
func (t *TTFParser) ParsePost(fd *bytes.Reader) error {

	err := t.Seek(fd, "post")
	if err != nil {
		return err
	}

	err = t.Skip(fd, 4) // version
	if err != nil {
		return err
	}

	t.italicAngle, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	err = t.Skip(fd, 2) // Skip decimal part
	if err != nil {
		return err
	}

	t.underlinePosition, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	//fmt.Printf("start>>>>>>>\n")
	t.underlineThickness, err = t.ReadShort(fd)
	if err != nil {
		return err
	}
	//fmt.Printf("underlineThickness=%d\n", t.underlineThickness)
	//fmt.Printf(">>>>>>>%d\n", me.underlineThickness)

	isFixedPitch, err := t.ReadULong(fd)
	if err != nil {
		return err
	}
	t.isFixedPitch = (isFixedPitch != 0)

	return nil
}

//ParseOS2 parse OS2 table https://www.microsoft.com/typography/otspec/OS2.htm
func (t *TTFParser) ParseOS2(fd *bytes.Reader) error {
	err := t.Seek(fd, "OS/2")
	if err != nil {
		return err
	}
	version, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}
	t.os2Version = version

	err = t.Skip(fd, 3*2) // xAvgCharWidth, usWeightClass, usWidthClass
	if err != nil {
		return err
	}
	fsType, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}
	t.Embeddable = (fsType != 2) && ((fsType & 0x200) == 0)

	err = t.Skip(fd, (11*2)+10+(4*4)+4)
	if err != nil {
		return err
	}
	fsSelection, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}
	t.Bold = ((fsSelection & 32) != 0)
	err = t.Skip(fd, 2*2) // usFirstCharIndex, usLastCharIndex
	if err != nil {
		return err
	}
	t.typoAscender, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	t.typoDescender, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	t.sTypoLineGap, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	t.usWinAscent, err = t.ReadUShort(fd)
	if err != nil {
		return err
	}

	t.usWinDescent, err = t.ReadUShort(fd)
	if err != nil {
		return err
	}

	if version >= 2 {

		err = t.Skip(fd, 2*4)
		if err != nil {
			return err
		}

		t.sxHeight, err = t.ReadShort(fd)
		if err != nil {
			return err
		}

		t.capHeight, err = t.ReadShort(fd)
		if err != nil {
			return err
		}

	} else {
		t.capHeight = t.ascender
	}

	return nil
}

//ParseName parse name table https://www.microsoft.com/typography/otspec/name.htm
func (t *TTFParser) ParseName(fd *bytes.Reader) error {

	//$this->Seek('name');
	err := t.Seek(fd, "name")
	if err != nil {
		return err
	}

	tableOffset, err := t.FTell(fd)
	if err != nil {
		return err
	}

	t.postScriptName = ""
	err = t.Skip(fd, 2) // format
	if err != nil {
		return err
	}

	count, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}

	stringOffset, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}

	for i := 0; i < int(count); i++ {
		err = t.Skip(fd, 3*2) // platformID, encodingID, languageID
		if err != nil {
			return err
		}
		nameID, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		length, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		offset, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		if nameID == 6 {
			// PostScript name
			_, err = fd.Seek(int64(tableOffset+stringOffset+offset), 0)
			if err != nil {
				return err
			}

			stmp, err := t.Read(fd, int(length))
			if err != nil {
				return err
			}

			var tmpStmp []byte
			for _, v := range stmp {
				if v != 0 {
					tmpStmp = append(tmpStmp, v)
				}
			}
			s := fmt.Sprintf("%s", string(tmpStmp)) //strings(stmp)
			s = strings.Replace(s, strconv.Itoa(0), "", -1)
			s, err = t.PregReplace("|[ \\[\\](){}<>/%]|", "", s)
			if err != nil {
				return err
			}
			t.postScriptName = s
			break
		}
	}

	if t.postScriptName == "" {
		return ERROR_POSTSCRIPT_NAME_NOT_FOUND
	}

	//fmt.Printf("%s\n", me.postScriptName)
	return nil
}

func (t *TTFParser) PregReplace(pattern string, replacement string, subject string) (string, error) {

	reg, err := regexp.Compile(pattern)
	if err != nil {
		return "", err
	}
	str := reg.ReplaceAllString(subject, replacement)
	return str, nil
}

//ParseCmap parse cmap table format 4 https://www.microsoft.com/typography/otspec/cmap.htm
func (t *TTFParser) ParseCmap(fd *bytes.Reader) error {
	t.Seek(fd, "cmap")
	t.Skip(fd, 2) // version
	numTables, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}

	offset31 := uint(0)
	for i := 0; i < int(numTables); i++ {
		platformID, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		encodingID, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		offset, err := t.ReadULong(fd)
		if err != nil {
			return err
		}

		t.symbol = false //init
		if platformID == 3 && encodingID == 1 {
			if encodingID == 0 {
				t.symbol = true
			}
			offset31 = offset
		}
		//fmt.Printf("me.symbol=%d\n", me.symbol)
	} //end for

	if offset31 == 0 {
		//No Unicode encoding found
		return ERROR_NO_UNICODE_ENCODING_FOUND
	}

	var startCount, endCount, idDelta, idRangeOffset, glyphIDArray []uint

	_, err = fd.Seek(int64(t.tables["cmap"].Offset+offset31), 0)
	if err != nil {
		return err
	}

	format, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}

	if format != 4 {
		//Unexpected subtable format
		return ERROR_UNEXPECTED_SUBTABLE_FORMAT
	}

	length, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}
	//fmt.Printf("\nlength=%d\n", length)

	err = t.Skip(fd, 2) // language
	if err != nil {
		return err
	}
	segCount, err := t.ReadUShort(fd)
	if err != nil {
		return err
	}
	segCount = segCount / 2
	t.SegCount = segCount
	err = t.Skip(fd, 3*2) // searchRange, entrySelector, rangeShift
	if err != nil {
		return err
	}

	glyphCount := (length - (16 + 8*segCount)) / 2
	//fmt.Printf("\nglyphCount=%d\n", glyphCount)

	for i := 0; i < int(segCount); i++ {
		tmp, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		endCount = append(endCount, tmp)
	}
	t.EndCount = endCount

	err = t.Skip(fd, 2) // reservedPad
	if err != nil {
		return err
	}

	for i := 0; i < int(segCount); i++ {
		tmp, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		startCount = append(startCount, tmp)
	}
	t.StartCount = startCount

	for i := 0; i < int(segCount); i++ {
		tmp, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		idDelta = append(idDelta, tmp)
	}
	t.IdDelta = idDelta

	offset, err := t.FTell(fd)
	if err != nil {
		return err
	}
	for i := 0; i < int(segCount); i++ {
		tmp, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		idRangeOffset = append(idRangeOffset, tmp)
	}
	t.IdRangeOffset = idRangeOffset
	//_ = glyphIdArray
	for i := 0; i < int(glyphCount); i++ {
		tmp, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		glyphIDArray = append(glyphIDArray, tmp)
	}
	t.GlyphIdArray = glyphIDArray

	t.chars = make(map[int]uint)
	for i := 0; i < int(segCount); i++ {
		c1 := startCount[i]
		c2 := endCount[i]
		d := idDelta[i]
		ro := idRangeOffset[i]
		if ro > 0 {
			_, err = fd.Seek(int64(offset+uint(2*i)+ro), 0)
			if err != nil {
				return err
			}
		}

		for c := c1; c <= c2; c++ {
			var gid uint
			if c == 0xFFFF {
				break
			}
			if ro > 0 {
				gid, err = t.ReadUShort(fd)
				if err != nil {
					return err
				}
				if gid > 0 {
					gid += d
				}
			} else {
				gid = c + d
			}

			if gid >= 65536 {
				gid -= 65536
			}
			if gid > 0 {
				//fmt.Printf("%d gid = %d, ", int(c), gid)
				t.chars[int(c)] = gid
			}
		}

	}

	_, err = t.ParseCmapFormat12(fd)
	if err != nil {
		return err
	}

	return nil
}

func (t *TTFParser) FTell(fd *bytes.Reader) (uint, error) {
	offset, err := fd.Seek(0, os.SEEK_CUR)
	return uint(offset), err
}

//ParseHmtx parse hmtx table  https://www.microsoft.com/typography/otspec/hmtx.htm
func (t *TTFParser) ParseHmtx(fd *bytes.Reader) error {

	t.Seek(fd, "hmtx")
	i := uint(0)
	for i < t.numberOfHMetrics {
		advanceWidth, err := t.ReadUShort(fd)
		if err != nil {
			return err
		}
		err = t.Skip(fd, 2)
		if err != nil {
			return err
		}
		t.widths = append(t.widths, advanceWidth)
		i++
	}
	if t.numberOfHMetrics < t.numGlyphs {
		var err error
		lastWidth := t.widths[t.numberOfHMetrics-1]
		t.widths, err = t.ArrayPadUint(t.widths, t.numGlyphs, lastWidth)
		if err != nil {
			return err
		}
	}

	return nil
}

func (t *TTFParser) ArrayPadUint(arr []uint, size uint, val uint) ([]uint, error) {
	var result []uint
	i := uint(0)
	for i < size {
		if int(i) < len(arr) {
			result = append(result, arr[i])
		} else {
			result = append(result, val)
		}
		i++
	}

	return result, nil
}

//ParseHead parse head table  https://www.microsoft.com/typography/otspec/Head.htm
func (t *TTFParser) ParseHead(fd *bytes.Reader) error {

	//fmt.Printf("\nParseHead\n")
	err := t.Seek(fd, "head")
	if err != nil {
		return err
	}

	err = t.Skip(fd, 3*4) // version, fontRevision, checkSumAdjustment
	if err != nil {
		return err
	}
	magicNumber, err := t.ReadULong(fd)
	if err != nil {
		return err
	}

	//fmt.Printf("\nmagicNumber = %d\n", magicNumber)
	if magicNumber != 0x5F0F3CF5 {
		return ERROR_INCORRECT_MAGIC_NUMBER
	}

	err = t.Skip(fd, 2)
	if err != nil {
		return err
	}

	t.unitsPerEm, err = t.ReadUShort(fd)
	if err != nil {
		return err
	}

	err = t.Skip(fd, 2*8) // created, modified
	if err != nil {
		return err
	}

	t.xMin, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	t.yMin, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	t.xMax, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	t.yMax, err = t.ReadShort(fd)
	if err != nil {
		return err
	}

	err = t.Skip(fd, 2*3) //skip macStyle,lowestRecPPEM,fontDirectionHint
	if err != nil {
		return err
	}

	t.indexToLocFormat, err = t.ReadShort(fd)
	if err != nil {
		retu
Download .txt
gitextract_c0w8xc36/

├── .github/
│   └── workflows/
│       ├── codeql-analysis.yml
│       ├── go.yml
│       └── golangci-lint.yml
├── .gitignore
├── LICENSE
├── README.md
├── go.mod
├── go.sum
├── main.go
└── vendor/
    ├── github.com/
    │   ├── phpdave11/
    │   │   └── gofpdi/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── const.go
    │   │       ├── go.mod
    │   │       ├── go.sum
    │   │       ├── gofpdi.go
    │   │       ├── helper.go
    │   │       ├── importer.go
    │   │       ├── reader.go
    │   │       └── writer.go
    │   ├── pkg/
    │   │   └── errors/
    │   │       ├── .gitignore
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── appveyor.yml
    │   │       ├── errors.go
    │   │       └── stack.go
    │   └── signintech/
    │       └── gopdf/
    │           ├── .gitignore
    │           ├── Changelog.md
    │           ├── LICENSE
    │           ├── README.md
    │           ├── box.go
    │           ├── buff.go
    │           ├── buff_write.go
    │           ├── buffer_pool.go
    │           ├── cache_contact_color.go
    │           ├── cache_content_gray.go
    │           ├── cache_content_image.go
    │           ├── cache_content_imported_object.go
    │           ├── cache_content_line.go
    │           ├── cache_content_line_type.go
    │           ├── cache_content_line_width.go
    │           ├── cache_content_oval.go
    │           ├── cache_content_polygon.go
    │           ├── cache_content_rectangle.go
    │           ├── cache_content_rotate.go
    │           ├── cache_content_text.go
    │           ├── cache_contnent_curve.go
    │           ├── catalog_obj.go
    │           ├── cell_option.go
    │           ├── cid_font_obj.go
    │           ├── config.go
    │           ├── content_obj.go
    │           ├── current.go
    │           ├── device_rgb_obj.go
    │           ├── embedfont_obj.go
    │           ├── encoding_obj.go
    │           ├── encryption_obj.go
    │           ├── ext_g_state_obj.go
    │           ├── font_obj.go
    │           ├── font_option.go
    │           ├── fontconverthelper.go
    │           ├── fontdescriptor_obj.go
    │           ├── fontmaker/
    │           │   └── core/
    │           │       ├── fontmaker.go
    │           │       ├── fontmap.go
    │           │       ├── kern_table.go
    │           │       ├── math.go
    │           │       ├── table_directory_entry.go
    │           │       ├── ttf_info.go
    │           │       ├── ttfparser.go
    │           │       ├── ttfparser_cmap_other_format.go
    │           │       └── ttfparser_kern.go
    │           ├── func_kern_override.go
    │           ├── go.mod
    │           ├── go.sum
    │           ├── gopdf.go
    │           ├── i_cache_contneter.go
    │           ├── ifont.go
    │           ├── image_holder.go
    │           ├── image_obj.go
    │           ├── image_obj_parse.go
    │           ├── img_info.go
    │           ├── imported_obj.go
    │           ├── iobj.go
    │           ├── link_option.go
    │           ├── list_cache_content.go
    │           ├── map_of_character_To_glyph_index.go
    │           ├── margin.go
    │           ├── outlines_obj.go
    │           ├── page_obj.go
    │           ├── page_option.go
    │           ├── page_sizes.go
    │           ├── pages_obj.go
    │           ├── pdf_dictionary_obj.go
    │           ├── pdf_info_obj.go
    │           ├── pdf_protection.go
    │           ├── point.go
    │           ├── procset_obj.go
    │           ├── rect.go
    │           ├── smask_obj.go
    │           ├── strhelper.go
    │           ├── style.go
    │           ├── subfont_descriptor_obj.go
    │           ├── subset_font_obj.go
    │           ├── transparency.go
    │           ├── transparency_xobject_group.go
    │           ├── ttf_option.go
    │           └── unicode_map.go
    └── modules.txt
Download .txt
SYMBOL INDEX (794 symbols across 82 files)

FILE: main.go
  constant Version (line 20) | Version       = "1.0"
  constant NameOfProgram (line 21) | NameOfProgram = "resumeio2pdf"
  constant Copy (line 22) | Copy          = "Copyright (c) 2021, Leonid Sopov <leonid@sopov.org>"
  constant CopyURL (line 23) | CopyURL       = "https://github.com/sopov/resumeio2pdf/"
  constant resumePage (line 25) | resumePage = "https://resume.io/r/%s"
  constant resumeMeta (line 26) | resumeMeta = "https://ssr.resume.tools/meta/ssid-%s?cache=%s"
  constant resumeExt (line 27) | resumeExt  = "png"
  constant resumeIMG (line 28) | resumeIMG  = "https://ssr.resume.tools/to-image/ssid-%s-%d.%s?cache=%s&s...
  constant resumeSize (line 29) | resumeSize = 1800
  constant Timeout (line 30) | Timeout    = 60 * time.Second
  constant exitCodeMisuseArgs (line 32) | exitCodeMisuseArgs = 2
  type metaLink (line 50) | type metaLink struct
  type metaViewPort (line 58) | type metaViewPort struct
  type metaPageInfo (line 63) | type metaPageInfo struct
  type metaInfo (line 68) | type metaInfo struct
  function main (line 72) | func main() {
  function cleanup (line 101) | func cleanup(images []string) {
  function generatePDF (line 115) | func generatePDF(info *metaInfo, images []string) error {
  function getResumeImages (line 159) | func getResumeImages(p int) (pages []string, err error) {
  function downloadPage (line 183) | func downloadPage(imgURL, imgFile string) error {
  function getJSON (line 209) | func getJSON(url string, target interface{}) error {
  function getMeta (line 233) | func getMeta() (meta *metaInfo, err error) {
  function readFlags (line 241) | func readFlags() bool {
  function extractArg (line 303) | func extractArg() bool {
  function usages (line 333) | func usages() {
  function usageID (line 355) | func usageID() {
  function logger (line 360) | func logger(v ...interface{}) {
  function loggerf (line 368) | func loggerf(format string, a ...interface{}) {

FILE: vendor/github.com/phpdave11/gofpdi/const.go
  constant PDF_TYPE_NULL (line 4) | PDF_TYPE_NULL = iota
  constant PDF_TYPE_NUMERIC (line 5) | PDF_TYPE_NUMERIC
  constant PDF_TYPE_TOKEN (line 6) | PDF_TYPE_TOKEN
  constant PDF_TYPE_HEX (line 7) | PDF_TYPE_HEX
  constant PDF_TYPE_STRING (line 8) | PDF_TYPE_STRING
  constant PDF_TYPE_DICTIONARY (line 9) | PDF_TYPE_DICTIONARY
  constant PDF_TYPE_ARRAY (line 10) | PDF_TYPE_ARRAY
  constant PDF_TYPE_OBJDEC (line 11) | PDF_TYPE_OBJDEC
  constant PDF_TYPE_OBJREF (line 12) | PDF_TYPE_OBJREF
  constant PDF_TYPE_OBJECT (line 13) | PDF_TYPE_OBJECT
  constant PDF_TYPE_STREAM (line 14) | PDF_TYPE_STREAM
  constant PDF_TYPE_BOOLEAN (line 15) | PDF_TYPE_BOOLEAN
  constant PDF_TYPE_REAL (line 16) | PDF_TYPE_REAL

FILE: vendor/github.com/phpdave11/gofpdi/helper.go
  function is_numeric (line 9) | func is_numeric(val interface{}) bool {
  function in_array (line 60) | func in_array(needle interface{}, hystack interface{}) bool {
  constant intSize (line 89) | intSize = 32 << (^uint(0) >> 63)
  function abs (line 91) | func abs(x int) int {
  function filterPaeth (line 105) | func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {

FILE: vendor/github.com/phpdave11/gofpdi/importer.go
  type Importer (line 9) | type Importer struct
    method GetReader (line 24) | func (this *Importer) GetReader() *PdfReader {
    method GetWriter (line 28) | func (this *Importer) GetWriter() *PdfWriter {
    method GetReaderForFile (line 32) | func (this *Importer) GetReaderForFile(file string) *PdfReader {
    method GetWriterForFile (line 40) | func (this *Importer) GetWriterForFile(file string) *PdfWriter {
    method init (line 55) | func (this *Importer) init() {
    method SetSourceFile (line 62) | func (this *Importer) SetSourceFile(f string) {
    method SetSourceStream (line 87) | func (this *Importer) SetSourceStream(rs *io.ReadSeeker) {
    method GetPageSizes (line 111) | func (this *Importer) GetPageSizes() map[int]map[string]map[string]flo...
    method ImportPage (line 121) | func (this *Importer) ImportPage(pageno int, box string) int {
    method SetNextObjectID (line 139) | func (this *Importer) SetNextObjectID(objId int) {
    method PutFormXobjects (line 144) | func (this *Importer) PutFormXobjects() map[string]int {
    method PutFormXobjectsUnordered (line 157) | func (this *Importer) PutFormXobjectsUnordered() map[string]string {
    method GetImportedObjects (line 171) | func (this *Importer) GetImportedObjects() map[int]string {
    method GetImportedObjectsUnordered (line 183) | func (this *Importer) GetImportedObjectsUnordered() map[string][]byte {
    method GetImportedObjHashPos (line 194) | func (this *Importer) GetImportedObjHashPos() map[string]map[int]string {
    method UseTemplate (line 205) | func (this *Importer) UseTemplate(tplid int, _x float64, _y float64, _...
  type TplInfo (line 18) | type TplInfo struct
  function NewImporter (line 48) | func NewImporter() *Importer {

FILE: vendor/github.com/phpdave11/gofpdi/reader.go
  type PdfReader (line 17) | type PdfReader struct
    method init (line 68) | func (this *PdfReader) init() error {
    method skipComments (line 97) | func (this *PdfReader) skipComments(r *bufio.Reader) error {
    method skipWhitespace (line 126) | func (this *PdfReader) skipWhitespace(r *bufio.Reader) error {
    method readToken (line 151) | func (this *PdfReader) readToken(r *bufio.Reader) (string, error) {
    method readValue (line 226) | func (this *PdfReader) readValue(r *bufio.Reader, t string) (*PdfValue...
    method resolveCompressedObject (line 451) | func (this *PdfReader) resolveCompressedObject(objSpec *PdfValue) (*Pd...
    method resolveObject (line 589) | func (this *PdfReader) resolveObject(objSpec *PdfValue) (*PdfValue, er...
    method findXref (line 740) | func (this *PdfReader) findXref() error {
    method readXref (line 805) | func (this *PdfReader) readXref() error {
    method readRoot (line 1170) | func (this *PdfReader) readRoot() error {
    method readPages (line 1185) | func (this *PdfReader) readPages() error {
    method getPageResources (line 1218) | func (this *PdfReader) getPageResources(pageno int) (*PdfValue, error) {
    method getPageContent (line 1272) | func (this *PdfReader) getPageContent(objSpec *PdfValue) ([]*PdfValue,...
    method getContent (line 1303) | func (this *PdfReader) getContent(pageno int) (string, error) {
    method rebuildContentStream (line 1345) | func (this *PdfReader) rebuildContentStream(content *PdfValue) ([]byte...
    method getAllPageBoxes (line 1398) | func (this *PdfReader) getAllPageBoxes(k float64) (map[int]map[string]...
    method getPageBoxes (line 1415) | func (this *PdfReader) getPageBoxes(pageno int, k float64) (map[string...
    method getPageBox (line 1446) | func (this *PdfReader) getPageBox(page *PdfValue, box_index string, k ...
    method getPageRotation (line 1494) | func (this *PdfReader) getPageRotation(pageno int) (*PdfValue, error) {
    method _getPageRotation (line 1504) | func (this *PdfReader) _getPageRotation(page *PdfValue) (*PdfValue, er...
    method read (line 1549) | func (this *PdfReader) read() error {
  function NewPdfReaderFromStream (line 31) | func NewPdfReaderFromStream(rs io.ReadSeeker) (*PdfReader, error) {
  function NewPdfReader (line 46) | func NewPdfReader(filename string) (*PdfReader, error) {
  type PdfValue (line 79) | type PdfValue struct

FILE: vendor/github.com/phpdave11/gofpdi/writer.go
  type PdfWriter (line 15) | type PdfWriter struct
    method SetTplIdOffset (line 47) | func (this *PdfWriter) SetTplIdOffset(n int) {
    method Init (line 51) | func (this *PdfWriter) Init() {
    method SetUseHash (line 61) | func (this *PdfWriter) SetUseHash(b bool) {
    method SetNextObjectID (line 65) | func (this *PdfWriter) SetNextObjectID(id int) {
    method GetImportedObjects (line 101) | func (this *PdfWriter) GetImportedObjects() map[*PdfObjectId][]byte {
    method GetImportedObjHashPos (line 107) | func (this *PdfWriter) GetImportedObjHashPos() map[*PdfObjectId]map[in...
    method ClearImportedObjects (line 111) | func (this *PdfWriter) ClearImportedObjects() {
    method ImportPage (line 116) | func (this *PdfWriter) ImportPage(reader *PdfReader, pageno int, boxNa...
    method newObj (line 200) | func (this *PdfWriter) newObj(objId int, onlyNewObj bool) {
    method endObj (line 221) | func (this *PdfWriter) endObj() {
    method shaOfInt (line 228) | func (this *PdfWriter) shaOfInt(i int) string {
    method outObjRef (line 235) | func (this *PdfWriter) outObjRef(objId int) {
    method out (line 250) | func (this *PdfWriter) out(s string) {
    method straightOut (line 256) | func (this *PdfWriter) straightOut(s string) {
    method writeValue (line 261) | func (this *PdfWriter) writeValue(value *PdfValue) {
    method PutFormXobjects (line 341) | func (this *PdfWriter) PutFormXobjects(reader *PdfReader) (map[string]...
    method putImportedObjects (line 464) | func (this *PdfWriter) putImportedObjects(reader *PdfReader) error {
    method getTemplateSize (line 514) | func (this *PdfWriter) getTemplateSize(tplid int, _w float64, _h float...
    method UseTemplate (line 541) | func (this *PdfWriter) UseTemplate(tplid int, _x float64, _y float64, ...
  type PdfObjectId (line 37) | type PdfObjectId struct
  type PdfObject (line 42) | type PdfObject struct
  function NewPdfWriter (line 69) | func NewPdfWriter(filename string) (*PdfWriter, error) {
  type PdfTemplate (line 86) | type PdfTemplate struct

FILE: vendor/github.com/pkg/errors/errors.go
  function New (line 102) | func New(message string) error {
  function Errorf (line 112) | func Errorf(format string, args ...interface{}) error {
  type fundamental (line 120) | type fundamental struct
    method Error (line 125) | func (f *fundamental) Error() string { return f.msg }
    method Format (line 127) | func (f *fundamental) Format(s fmt.State, verb rune) {
  function WithStack (line 145) | func WithStack(err error) error {
  type withStack (line 155) | type withStack struct
    method Cause (line 160) | func (w *withStack) Cause() error { return w.error }
    method Format (line 162) | func (w *withStack) Format(s fmt.State, verb rune) {
  function Wrap (line 181) | func Wrap(err error, message string) error {
  function Wrapf (line 198) | func Wrapf(err error, format string, args ...interface{}) error {
  function WithMessage (line 214) | func WithMessage(err error, message string) error {
  function WithMessagef (line 226) | func WithMessagef(err error, format string, args ...interface{}) error {
  type withMessage (line 236) | type withMessage struct
    method Error (line 241) | func (w *withMessage) Error() string { return w.msg + ": " + w.cause.E...
    method Cause (line 242) | func (w *withMessage) Cause() error  { return w.cause }
    method Format (line 244) | func (w *withMessage) Format(s fmt.State, verb rune) {
  function Cause (line 269) | func Cause(err error) error {

FILE: vendor/github.com/pkg/errors/stack.go
  type Frame (line 12) | type Frame
    method pc (line 16) | func (f Frame) pc() uintptr { return uintptr(f) - 1 }
    method file (line 20) | func (f Frame) file() string {
    method line (line 31) | func (f Frame) line() int {
    method Format (line 52) | func (f Frame) Format(s fmt.State, verb rune) {
  type StackTrace (line 81) | type StackTrace
    method Format (line 91) | func (st StackTrace) Format(s fmt.State, verb rune) {
  type stack (line 110) | type stack
    method Format (line 112) | func (s *stack) Format(st fmt.State, verb rune) {
    method StackTrace (line 125) | func (s *stack) StackTrace() StackTrace {
  function callers (line 133) | func callers() *stack {
  function funcname (line 142) | func funcname(name string) string {

FILE: vendor/github.com/signintech/gopdf/box.go
  type Box (line 3) | type Box struct
    method UnitsToPoints (line 9) | func (box *Box) UnitsToPoints(t int) (b *Box) {

FILE: vendor/github.com/signintech/gopdf/buff.go
  type Buff (line 4) | type Buff struct
    method Write (line 10) | func (b *Buff) Write(p []byte) (int, error) {
    method Len (line 25) | func (b *Buff) Len() int {
    method Bytes (line 30) | func (b *Buff) Bytes() []byte {
    method Position (line 35) | func (b *Buff) Position() int {
    method SetPosition (line 40) | func (b *Buff) SetPosition(pos int) {

FILE: vendor/github.com/signintech/gopdf/buff_write.go
  function WriteUInt32 (line 6) | func WriteUInt32(w io.Writer, v uint) error {
  function WriteUInt16 (line 19) | func WriteUInt16(w io.Writer, v uint) error {
  function WriteTag (line 31) | func WriteTag(w io.Writer, tag string) error {
  function WriteBytes (line 41) | func WriteBytes(w io.Writer, data []byte, offset int, count int) error {

FILE: vendor/github.com/signintech/gopdf/buffer_pool.go
  function GetBuffer (line 17) | func GetBuffer() *bytes.Buffer {
  function PutBuffer (line 22) | func PutBuffer(buf *bytes.Buffer) {

FILE: vendor/github.com/signintech/gopdf/cache_contact_color.go
  constant colorTypeStroke (line 8) | colorTypeStroke = "RG"
  constant colorTypeFill (line 10) | colorTypeFill = "rg"
  type cacheContentColor (line 12) | type cacheContentColor struct
    method write (line 17) | func (c *cacheContentColor) write(w io.Writer, protection *PDFProtecti...

FILE: vendor/github.com/signintech/gopdf/cache_content_gray.go
  constant grayTypeFill (line 8) | grayTypeFill = "g"
  constant grayTypeStroke (line 9) | grayTypeStroke = "G"
  type cacheContentGray (line 11) | type cacheContentGray struct
    method write (line 16) | func (c *cacheContentGray) write(w io.Writer, protection *PDFProtectio...

FILE: vendor/github.com/signintech/gopdf/cache_content_image.go
  type cacheContentImage (line 8) | type cacheContentImage struct
    method write (line 20) | func (c *cacheContentImage) write(w io.Writer, protection *PDFProtecti...

FILE: vendor/github.com/signintech/gopdf/cache_content_imported_object.go
  type cacheContentImportedTemplate (line 8) | type cacheContentImportedTemplate struct
    method write (line 17) | func (c *cacheContentImportedTemplate) write(w io.Writer, protection *...

FILE: vendor/github.com/signintech/gopdf/cache_content_line.go
  type cacheContentLine (line 8) | type cacheContentLine struct
    method write (line 16) | func (c *cacheContentLine) write(w io.Writer, protection *PDFProtectio...

FILE: vendor/github.com/signintech/gopdf/cache_content_line_type.go
  type cacheContentLineType (line 8) | type cacheContentLineType struct
    method write (line 12) | func (c *cacheContentLineType) write(w io.Writer, protection *PDFProte...

FILE: vendor/github.com/signintech/gopdf/cache_content_line_width.go
  type cacheContentLineWidth (line 8) | type cacheContentLineWidth struct
    method write (line 12) | func (c *cacheContentLineWidth) write(w io.Writer, protection *PDFProt...

FILE: vendor/github.com/signintech/gopdf/cache_content_oval.go
  type cacheContentOval (line 8) | type cacheContentOval struct
    method write (line 16) | func (c *cacheContentOval) write(w io.Writer, protection *PDFProtectio...

FILE: vendor/github.com/signintech/gopdf/cache_content_polygon.go
  type cacheContentPolygon (line 8) | type cacheContentPolygon struct
    method write (line 14) | func (c *cacheContentPolygon) write(w io.Writer, protection *PDFProtec...

FILE: vendor/github.com/signintech/gopdf/cache_content_rectangle.go
  type cacheContentRectangle (line 8) | type cacheContentRectangle struct
    method write (line 34) | func (c cacheContentRectangle) write(w io.Writer, protection *PDFProte...
  function NewCacheContentRectangle (line 18) | func NewCacheContentRectangle(pageHeight float64, rectOpts DrawableRectO...

FILE: vendor/github.com/signintech/gopdf/cache_content_rotate.go
  type cacheContentRotate (line 9) | type cacheContentRotate struct
    method write (line 15) | func (cc *cacheContentRotate) write(w io.Writer, protection *PDFProtec...

FILE: vendor/github.com/signintech/gopdf/cache_content_text.go
  constant ContentTypeCell (line 10) | ContentTypeCell = 0
  constant ContentTypeText (line 13) | ContentTypeText = 1
  type cacheContentText (line 15) | type cacheContentText struct
    method isSame (line 37) | func (c *cacheContentText) isSame(cache cacheContentText) bool {
    method setPageHeight (line 55) | func (c *cacheContentText) setPageHeight(pageheight float64) {
    method pageHeight (line 59) | func (c *cacheContentText) pageHeight() float64 {
    method calTypoAscender (line 68) | func (c *cacheContentText) calTypoAscender() float64 {
    method calTypoDescender (line 72) | func (c *cacheContentText) calTypoDescender() float64 {
    method calY (line 76) | func (c *cacheContentText) calY() (float64, error) {
    method calX (line 96) | func (c *cacheContentText) calX() (float64, error) {
    method write (line 113) | func (c *cacheContentText) write(w io.Writer, protection *PDFProtectio...
    method drawBorder (line 183) | func (c *cacheContentText) drawBorder(w io.Writer) error {
    method underline (line 236) | func (c *cacheContentText) underline(w io.Writer, startX float64, star...
    method createContent (line 254) | func (c *cacheContentText) createContent() (float64, float64, error) {
  function convertTypoUnit (line 63) | func convertTypoUnit(val float64, unitsPerEm uint, fontSize float64) flo...
  function createContent (line 266) | func createContent(f *SubsetFontObj, text string, fontSize int, rectangl...
  function kern (line 311) | func kern(f *SubsetFontObj, leftRune rune, rightRune rune, leftIndex uin...
  type CacheContent (line 333) | type CacheContent struct
    method Setup (line 338) | func (c *CacheContent) Setup(rectangle *Rect,
    method WriteTextToContent (line 371) | func (c *CacheContent) WriteTextToContent(text string) {

FILE: vendor/github.com/signintech/gopdf/cache_contnent_curve.go
  type cacheContentCurve (line 8) | type cacheContentCurve struct
    method write (line 21) | func (c *cacheContentCurve) write(w io.Writer, protection *PDFProtecti...

FILE: vendor/github.com/signintech/gopdf/catalog_obj.go
  type CatalogObj (line 9) | type CatalogObj struct
    method init (line 13) | func (c *CatalogObj) init(funcGetRoot func() *GoPdf) {
    method getType (line 18) | func (c *CatalogObj) getType() string {
    method write (line 22) | func (c *CatalogObj) write(w io.Writer, objID int) error {
    method SetIndexObjOutlines (line 34) | func (c *CatalogObj) SetIndexObjOutlines(index int) {

FILE: vendor/github.com/signintech/gopdf/cell_option.go
  constant Left (line 4) | Left = 8
  constant Top (line 6) | Top = 4
  constant Right (line 8) | Right = 2
  constant Bottom (line 10) | Bottom = 1
  constant Center (line 12) | Center = 16
  constant Middle (line 14) | Middle = 32
  constant AllBorders (line 16) | AllBorders = 15
  type CellOption (line 19) | type CellOption struct

FILE: vendor/github.com/signintech/gopdf/cid_font_obj.go
  type CIDFontObj (line 10) | type CIDFontObj struct
    method init (line 15) | func (ci *CIDFontObj) init(funcGetRoot func() *GoPdf) {
    method SetIndexObjSubfontDescriptor (line 19) | func (ci *CIDFontObj) SetIndexObjSubfontDescriptor(index int) {
    method getType (line 23) | func (ci *CIDFontObj) getType() string {
    method write (line 27) | func (ci *CIDFontObj) write(w io.Writer, objID int) error {
    method SetPtrToSubsetFontObj (line 51) | func (ci *CIDFontObj) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {

FILE: vendor/github.com/signintech/gopdf/config.go
  constant UnitUnset (line 5) | UnitUnset = iota
  constant UnitPT (line 6) | UnitPT
  constant UnitMM (line 7) | UnitMM
  constant UnitCM (line 8) | UnitCM
  constant UnitIN (line 9) | UnitIN
  constant conversionUnitPT (line 12) | conversionUnitPT = 1.0
  constant conversionUnitMM (line 13) | conversionUnitMM = 72.0 / 25.4
  constant conversionUnitCM (line 14) | conversionUnitCM = 72.0 / 2.54
  constant conversionUnitIN (line 15) | conversionUnitIN = 72.0
  constant Unit_Unset (line 21) | Unit_Unset = UnitUnset
  constant Unit_PT (line 22) | Unit_PT    = UnitPT
  constant Unit_MM (line 23) | Unit_MM    = UnitMM
  constant Unit_CM (line 24) | Unit_CM    = UnitCM
  constant Unit_IN (line 25) | Unit_IN    = UnitIN
  type Config (line 29) | type Config struct
  type PDFProtectionConfig (line 38) | type PDFProtectionConfig struct
  function UnitsToPoints (line 46) | func UnitsToPoints(t int, u float64) float64 {
  function PointsToUnits (line 62) | func PointsToUnits(t int, u float64) float64 {
  function UnitsToPointsVar (line 78) | func UnitsToPointsVar(t int, u ...*float64) {
  function PointsToUnitsVar (line 85) | func PointsToUnitsVar(t int, u ...*float64) {

FILE: vendor/github.com/signintech/gopdf/content_obj.go
  type ContentObj (line 11) | type ContentObj struct
    method protection (line 17) | func (c *ContentObj) protection() *PDFProtection {
    method init (line 21) | func (c *ContentObj) init(funcGetRoot func() *GoPdf) {
    method write (line 25) | func (c *ContentObj) write(w io.Writer, objID int) error {
    method getType (line 97) | func (c *ContentObj) getType() string {
    method AppendStreamText (line 102) | func (c *ContentObj) AppendStreamText(text string) error {
    method AppendStreamSubsetFont (line 145) | func (c *ContentObj) AppendStreamSubsetFont(rectangle *Rect, text stri...
    method AppendStreamLine (line 183) | func (c *ContentObj) AppendStreamLine(x1 float64, y1 float64, x2 float...
    method AppendStreamImportedTemplate (line 196) | func (c *ContentObj) AppendStreamImportedTemplate(tplName string, scal...
    method AppendStreamRectangle (line 207) | func (c *ContentObj) AppendStreamRectangle(opts DrawableRectOptions) {
    method AppendStreamOval (line 213) | func (c *ContentObj) AppendStreamOval(x1 float64, y1 float64, x2 float...
    method AppendStreamCurve (line 232) | func (c *ContentObj) AppendStreamCurve(x0 float64, y0 float64, x1 floa...
    method AppendStreamSetLineWidth (line 248) | func (c *ContentObj) AppendStreamSetLineWidth(w float64) {
    method AppendStreamSetLineType (line 255) | func (c *ContentObj) AppendStreamSetLineType(t string) {
    method AppendStreamSetGrayFill (line 263) | func (c *ContentObj) AppendStreamSetGrayFill(w float64) {
    method AppendStreamSetGrayStroke (line 272) | func (c *ContentObj) AppendStreamSetGrayStroke(w float64) {
    method AppendStreamSetColorStroke (line 281) | func (c *ContentObj) AppendStreamSetColorStroke(r uint8, g uint8, b ui...
    method AppendStreamSetColorFill (line 291) | func (c *ContentObj) AppendStreamSetColorFill(r uint8, g uint8, b uint...
    method GetCacheContentImage (line 300) | func (c *ContentObj) GetCacheContentImage(index int, opts ImageOptions...
    method AppendStreamImage (line 317) | func (c *ContentObj) AppendStreamImage(index int, opts ImageOptions) {
    method AppendStreamPolygon (line 323) | func (c *ContentObj) AppendStreamPolygon(points []Point, style string) {
    method appendRotate (line 331) | func (c *ContentObj) appendRotate(angle, x, y float64) {
    method appendRotateReset (line 341) | func (c *ContentObj) appendRotateReset() {
  function ContentObjCalTextHeight (line 348) | func ContentObjCalTextHeight(fontsize int) float64 {
  function fixRange10 (line 355) | func fixRange10(val float64) float64 {
  function convertTTFUnit2PDFUnit (line 365) | func convertTTFUnit2PDFUnit(n int, upem int) int {

FILE: vendor/github.com/signintech/gopdf/current.go
  type Current (line 4) | type Current struct
    method setTextColor (line 54) | func (c *Current) setTextColor(rgb Rgb) {
    method textColor (line 58) | func (c *Current) textColor() Rgb {
  type ImageCache (line 63) | type ImageCache struct
  type Rgb (line 70) | type Rgb struct
    method SetR (line 77) | func (rgb *Rgb) SetR(r uint8) {
    method SetG (line 82) | func (rgb *Rgb) SetG(g uint8) {
    method SetB (line 87) | func (rgb *Rgb) SetB(b uint8) {
    method equal (line 91) | func (rgb Rgb) equal(obj Rgb) bool {

FILE: vendor/github.com/signintech/gopdf/device_rgb_obj.go
  type DeviceRGBObj (line 9) | type DeviceRGBObj struct
    method init (line 14) | func (d *DeviceRGBObj) init(funcGetRoot func() *GoPdf) {
    method protection (line 18) | func (d *DeviceRGBObj) protection() *PDFProtection {
    method getType (line 22) | func (d *DeviceRGBObj) getType() string {
    method write (line 27) | func (d *DeviceRGBObj) write(w io.Writer, objID int) error {

FILE: vendor/github.com/signintech/gopdf/embedfont_obj.go
  type EmbedFontObj (line 10) | type EmbedFontObj struct
    method init (line 17) | func (e *EmbedFontObj) init(funcGetRoot func() *GoPdf) {
    method protection (line 21) | func (e *EmbedFontObj) protection() *PDFProtection {
    method write (line 25) | func (e *EmbedFontObj) write(w io.Writer, objID int) error {
    method getType (line 49) | func (e *EmbedFontObj) getType() string {
    method SetFont (line 54) | func (e *EmbedFontObj) SetFont(font IFont, zfontpath string) {

FILE: vendor/github.com/signintech/gopdf/encoding_obj.go
  type EncodingObj (line 8) | type EncodingObj struct
    method init (line 12) | func (e *EncodingObj) init(funcGetRoot func() *GoPdf) {
    method getType (line 15) | func (e *EncodingObj) getType() string {
    method write (line 18) | func (e *EncodingObj) write(w io.Writer, objID int) error {
    method SetFont (line 26) | func (e *EncodingObj) SetFont(font IFont) {
    method GetFont (line 31) | func (e *EncodingObj) GetFont() IFont {

FILE: vendor/github.com/signintech/gopdf/encryption_obj.go
  type EncryptionObj (line 10) | type EncryptionObj struct
    method init (line 16) | func (e *EncryptionObj) init(func() *GoPdf) {
    method getType (line 20) | func (e *EncryptionObj) getType() string {
    method write (line 24) | func (e *EncryptionObj) write(w io.Writer, objID int) error {
    method escape (line 36) | func (e *EncryptionObj) escape(b []byte) string {

FILE: vendor/github.com/signintech/gopdf/ext_g_state_obj.go
  type ExtGState (line 12) | type ExtGState struct
    method init (line 73) | func (egs ExtGState) init(func() *GoPdf) {}
    method getType (line 75) | func (egs ExtGState) getType() string {
    method write (line 79) | func (egs ExtGState) write(w io.Writer, objID int) error {
  type ExtGStateOptions (line 20) | type ExtGStateOptions struct
    method GetId (line 27) | func (extOpt ExtGStateOptions) GetId() string {
  function GetCachedExtGState (line 45) | func GetCachedExtGState(opts ExtGStateOptions, gp *GoPdf) (ExtGState, er...
  type ExtGStatesMap (line 106) | type ExtGStatesMap struct
    method Find (line 118) | func (extm *ExtGStatesMap) Find(extGState ExtGStateOptions) (ExtGState...
    method Save (line 133) | func (tm *ExtGStatesMap) Save(id string, extGState ExtGState) ExtGState {
  function NewExtGStatesMap (line 111) | func NewExtGStatesMap() ExtGStatesMap {

FILE: vendor/github.com/signintech/gopdf/font_obj.go
  type FontObj (line 9) | type FontObj struct
    method init (line 23) | func (f *FontObj) init(funcGetRoot func() *GoPdf) {
    method write (line 28) | func (f *FontObj) write(w io.Writer, objID int) error {
    method getType (line 48) | func (f *FontObj) getType() string {
    method SetIndexObjWidth (line 53) | func (f *FontObj) SetIndexObjWidth(index int) {
    method SetIndexObjFontDescriptor (line 58) | func (f *FontObj) SetIndexObjFontDescriptor(index int) {
    method SetIndexObjEncoding (line 63) | func (f *FontObj) SetIndexObjEncoding(index int) {

FILE: vendor/github.com/signintech/gopdf/font_option.go
  constant Regular (line 8) | Regular = 0
  constant Italic (line 10) | Italic = 1
  constant Bold (line 12) | Bold = 2
  constant Underline (line 14) | Underline = 4
  function getConvertedStyle (line 16) | func getConvertedStyle(fontStyle string) (style int) {

FILE: vendor/github.com/signintech/gopdf/fontconverthelper.go
  function FontConvertHelperCw2Str (line 10) | func FontConvertHelperCw2Str(cw FontCw) string {
  function FontConvertHelper_Cw2Str (line 23) | func FontConvertHelper_Cw2Str(cw FontCw) string {

FILE: vendor/github.com/signintech/gopdf/fontdescriptor_obj.go
  type FontDescriptorObj (line 9) | type FontDescriptorObj struct
    method init (line 14) | func (f *FontDescriptorObj) init(funcGetRoot func() *GoPdf) {
    method write (line 18) | func (f *FontDescriptorObj) write(w io.Writer, objID int) error {
    method getType (line 41) | func (f *FontDescriptorObj) getType() string {
    method SetFont (line 46) | func (f *FontDescriptorObj) SetFont(font IFont) {
    method GetFont (line 51) | func (f *FontDescriptorObj) GetFont() IFont {
    method SetFontFileObjRelate (line 56) | func (f *FontDescriptorObj) SetFontFileObjRelate(relate string) {

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/fontmaker.go
  type FontMaker (line 20) | type FontMaker struct
    method GetResults (line 25) | func (f *FontMaker) GetResults() []string {
    method MakeFont (line 34) | func (f *FontMaker) MakeFont(fontpath string, mappath string, encode s...
    method GoStructName (line 94) | func (f *FontMaker) GoStructName(name string) string {
    method MakeDefinitionFile (line 99) | func (f *FontMaker) MakeDefinitionFile(gofontname string, mappath stri...
    method MakeFontDescriptor (line 213) | func (f *FontMaker) MakeFontDescriptor(info TtfInfo) (string, error) {
    method MakeFontEncoding (line 304) | func (f *FontMaker) MakeFontEncoding(mappath string, fontmaps []FontMa...
    method MakeWidthArray (line 325) | func (f *FontMaker) MakeWidthArray(widths map[int]int) (string, error) {
    method FileSize (line 345) | func (f *FontMaker) FileSize(path string) (int64, error) {
    method GetInfoFromTrueType (line 361) | func (f *FontMaker) GetInfoFromTrueType(fontpath string, fontmaps []Fo...
    method MultiplyAndRoundWithUInt64 (line 433) | func (f *FontMaker) MultiplyAndRoundWithUInt64(k float64, v uint) int {
    method MultiplyAndRound (line 438) | func (f *FontMaker) MultiplyAndRound(k float64, v int) int {
    method Round (line 443) | func (f *FontMaker) Round(value float64) int {
    method LoadMap (line 447) | func (f *FontMaker) LoadMap(encodingpath string) ([]FontMap, error) {
  function NewFontMaker (line 30) | func NewFontMaker() *FontMaker {

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/fontmap.go
  type FontMap (line 3) | type FontMap struct

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/kern_table.go
  type KernTable (line 4) | type KernTable struct
  type KernMap (line 11) | type KernMap
  type KernValue (line 14) | type KernValue
    method ValueByRight (line 17) | func (k KernValue) ValueByRight(right uint) (bool, int16) {

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/math.go
  function Round (line 3) | func Round(value float64) int {

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/table_directory_entry.go
  type TableDirectoryEntry (line 3) | type TableDirectoryEntry struct
    method PaddedLength (line 9) | func (t TableDirectoryEntry) PaddedLength() int {

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/ttf_info.go
  type TtfInfo (line 10) | type TtfInfo
    method PushString (line 12) | func (t TtfInfo) PushString(key string, val string) {
    method PushBytes (line 16) | func (t TtfInfo) PushBytes(key string, val []byte) {
    method PushInt64 (line 20) | func (t TtfInfo) PushInt64(key string, val int64) {
    method PushInt (line 24) | func (t TtfInfo) PushInt(key string, val int) {
    method PushUInt64 (line 28) | func (t TtfInfo) PushUInt64(key string, val uint) {
    method PushBool (line 32) | func (t TtfInfo) PushBool(key string, val bool) {
    method PushInt64s (line 36) | func (t TtfInfo) PushInt64s(key string, val []int) {
    method PushMapIntInt64 (line 40) | func (t TtfInfo) PushMapIntInt64(key string, val map[int]int) {
    method GetBool (line 44) | func (t TtfInfo) GetBool(key string) (bool, error) {
    method GetString (line 58) | func (t TtfInfo) GetString(key string) (string, error) {
    method GetInt64 (line 72) | func (t TtfInfo) GetInt64(key string) (int, error) {
    method GetInt64s (line 86) | func (t TtfInfo) GetInt64s(key string) ([]int, error) {
    method GetMapIntInt64 (line 100) | func (t TtfInfo) GetMapIntInt64(key string) (map[int]int, error) {
  function NewTtfInfo (line 114) | func NewTtfInfo() TtfInfo {

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser.go
  type TTFParser (line 24) | type TTFParser struct
    method Kern (line 88) | func (t *TTFParser) Kern() *KernTable {
    method UnderlinePosition (line 93) | func (t *TTFParser) UnderlinePosition() int {
    method GroupingTables (line 98) | func (t *TTFParser) GroupingTables() []CmapFormat12GroupingTable {
    method UnderlineThickness (line 103) | func (t *TTFParser) UnderlineThickness() int {
    method XHeight (line 107) | func (t *TTFParser) XHeight() int {
    method XMin (line 115) | func (t *TTFParser) XMin() int {
    method YMin (line 119) | func (t *TTFParser) YMin() int {
    method XMax (line 123) | func (t *TTFParser) XMax() int {
    method YMax (line 127) | func (t *TTFParser) YMax() int {
    method ItalicAngle (line 131) | func (t *TTFParser) ItalicAngle() int {
    method Flag (line 135) | func (t *TTFParser) Flag() int {
    method Ascender (line 145) | func (t *TTFParser) Ascender() int {
    method Descender (line 152) | func (t *TTFParser) Descender() int {
    method TypoAscender (line 163) | func (t *TTFParser) TypoAscender() int {
    method TypoDescender (line 167) | func (t *TTFParser) TypoDescender() int {
    method CapHeight (line 172) | func (t *TTFParser) CapHeight() int {
    method NumGlyphs (line 177) | func (t *TTFParser) NumGlyphs() uint {
    method UnitsPerEm (line 181) | func (t *TTFParser) UnitsPerEm() uint {
    method NumberOfHMetrics (line 185) | func (t *TTFParser) NumberOfHMetrics() uint {
    method Widths (line 189) | func (t *TTFParser) Widths() []uint {
    method Chars (line 193) | func (t *TTFParser) Chars() map[int]uint {
    method GetTables (line 197) | func (t *TTFParser) GetTables() map[string]TableDirectoryEntry {
    method SetUseKerning (line 202) | func (t *TTFParser) SetUseKerning(use bool) {
    method Parse (line 207) | func (t *TTFParser) Parse(filepath string) error {
    method ParseByReader (line 216) | func (t *TTFParser) ParseByReader(rd io.Reader) error {
    method ParseFontData (line 226) | func (t *TTFParser) ParseFontData(fontData []byte) error {
    method FontData (line 326) | func (t *TTFParser) FontData() []byte {
    method ParseLoca (line 331) | func (t *TTFParser) ParseLoca(fd *bytes.Reader) error {
    method ParsePost (line 374) | func (t *TTFParser) ParsePost(fd *bytes.Reader) error {
    method ParseOS2 (line 419) | func (t *TTFParser) ParseOS2(fd *bytes.Reader) error {
    method ParseName (line 503) | func (t *TTFParser) ParseName(fd *bytes.Reader) error {
    method PregReplace (line 586) | func (t *TTFParser) PregReplace(pattern string, replacement string, su...
    method ParseCmap (line 597) | func (t *TTFParser) ParseCmap(fd *bytes.Reader) error {
    method FTell (line 779) | func (t *TTFParser) FTell(fd *bytes.Reader) (uint, error) {
    method ParseHmtx (line 785) | func (t *TTFParser) ParseHmtx(fd *bytes.Reader) error {
    method ArrayPadUint (line 813) | func (t *TTFParser) ArrayPadUint(arr []uint, size uint, val uint) ([]u...
    method ParseHead (line 829) | func (t *TTFParser) ParseHead(fd *bytes.Reader) error {
    method ParseHhea (line 900) | func (t *TTFParser) ParseHhea(fd *bytes.Reader) error {
    method ParseMaxp (line 936) | func (t *TTFParser) ParseMaxp(fd *bytes.Reader) error {
    method Seek (line 956) | func (t *TTFParser) Seek(fd *bytes.Reader, tag string) error {
    method BytesToString (line 970) | func (t *TTFParser) BytesToString(b []byte) string {
    method ReadUShort (line 975) | func (t *TTFParser) ReadUShort(fd *bytes.Reader) (uint, error) {
    method ReadShort (line 985) | func (t *TTFParser) ReadShort(fd *bytes.Reader) (int, error) {
    method ReadShortInt16 (line 1002) | func (t *TTFParser) ReadShortInt16(fd *bytes.Reader) (int16, error) {
    method ReadULong (line 1011) | func (t *TTFParser) ReadULong(fd *bytes.Reader) (uint, error) {
    method Skip (line 1022) | func (t *TTFParser) Skip(fd *bytes.Reader, length int) error {
    method Read (line 1031) | func (t *TTFParser) Read(fd *bytes.Reader, length int) ([]byte, error) {

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser_cmap_other_format.go
  method ParseCmapFormat12 (line 9) | func (t *TTFParser) ParseCmapFormat12(fd *bytes.Reader) (bool, error) {
  type cmapFormat12EncodingSubtable (line 119) | type cmapFormat12EncodingSubtable struct
  type CmapFormat12GroupingTable (line 125) | type CmapFormat12GroupingTable struct

FILE: vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser_kern.go
  method Parsekern (line 9) | func (t *TTFParser) Parsekern(fd *bytes.Reader) error {
  method parsekernSubTable (line 45) | func (t *TTFParser) parsekernSubTable(fd *bytes.Reader) error {
  method parsekernSubTableFormat0 (line 67) | func (t *TTFParser) parsekernSubTableFormat0(fd *bytes.Reader) error {

FILE: vendor/github.com/signintech/gopdf/func_kern_override.go
  type FuncKernOverride (line 4) | type FuncKernOverride

FILE: vendor/github.com/signintech/gopdf/gopdf.go
  constant subsetFont (line 21) | subsetFont = "SubsetFont"
  constant defaultMargin (line 24) | defaultMargin = 10.0
  type GoPdf (line 27) | type GoPdf struct
    method SetLineWidth (line 119) | func (gp *GoPdf) SetLineWidth(width float64) {
    method SetCompressLevel (line 130) | func (gp *GoPdf) SetCompressLevel(level int) {
    method SetNoCompression (line 145) | func (gp *GoPdf) SetNoCompression() {
    method SetLineType (line 155) | func (gp *GoPdf) SetLineType(linetype string) {
    method Line (line 160) | func (gp *GoPdf) Line(x1 float64, y1 float64, x2 float64, y2 float64) {
    method RectFromLowerLeft (line 166) | func (gp *GoPdf) RectFromLowerLeft(x float64, y float64, wdth float64,...
    method RectFromUpperLeft (line 180) | func (gp *GoPdf) RectFromUpperLeft(x float64, y float64, wdth float64,...
    method RectFromLowerLeftWithStyle (line 198) | func (gp *GoPdf) RectFromLowerLeftWithStyle(x float64, y float64, wdth...
    method RectFromLowerLeftWithOpts (line 211) | func (gp *GoPdf) RectFromLowerLeftWithOpts(opts DrawableRectOptions) e...
    method RectFromUpperLeftWithStyle (line 233) | func (gp *GoPdf) RectFromUpperLeftWithStyle(x float64, y float64, wdth...
    method RectFromUpperLeftWithOpts (line 246) | func (gp *GoPdf) RectFromUpperLeftWithOpts(opts DrawableRectOptions) e...
    method Oval (line 266) | func (gp *GoPdf) Oval(x1 float64, y1 float64, x2 float64, y2 float64) {
    method Br (line 272) | func (gp *GoPdf) Br(h float64) {
    method SetGrayFill (line 279) | func (gp *GoPdf) SetGrayFill(grayScale float64) {
    method SetGrayStroke (line 286) | func (gp *GoPdf) SetGrayStroke(grayScale float64) {
    method SetX (line 292) | func (gp *GoPdf) SetX(x float64) {
    method GetX (line 299) | func (gp *GoPdf) GetX() float64 {
    method SetY (line 304) | func (gp *GoPdf) SetY(y float64) {
    method GetY (line 310) | func (gp *GoPdf) GetY() float64 {
    method ImageByHolder (line 315) | func (gp *GoPdf) ImageByHolder(img ImageHolder, x float64, y float64, ...
    method ImageByHolderWithOptions (line 329) | func (gp *GoPdf) ImageByHolderWithOptions(img ImageHolder, opts ImageO...
    method maskHolder (line 367) | func (gp *GoPdf) maskHolder(img ImageHolder, opts ImageOptions) (int, ...
    method createTransparencyXObjectGroup (line 434) | func (gp *GoPdf) createTransparencyXObjectGroup(image *cacheContentIma...
    method imageByHolder (line 470) | func (gp *GoPdf) imageByHolder(img ImageHolder, opts ImageOptions) err...
    method Image (line 553) | func (gp *GoPdf) Image(picPath string, x float64, y float64, rect *Rec...
    method ImageFrom (line 570) | func (gp *GoPdf) ImageFrom(img image.Image, x float64, y float64, rect...
    method AddPage (line 600) | func (gp *GoPdf) AddPage() {
    method AddPageWithOption (line 606) | func (gp *GoPdf) AddPageWithOption(opt PageOption) {
    method AddOutline (line 641) | func (gp *GoPdf) AddOutline(title string) {
    method Start (line 646) | func (gp *GoPdf) Start(config Config) {
    method SetFontWithStyle (line 683) | func (gp *GoPdf) SetFontWithStyle(family string, style int, size int) ...
    method SetFont (line 715) | func (gp *GoPdf) SetFont(family string, style string, size int) error {
    method WritePdf (line 720) | func (gp *GoPdf) WritePdf(pdfPath string) error {
    method Write (line 724) | func (gp *GoPdf) Write(w io.Writer) error {
    method Read (line 728) | func (gp *GoPdf) Read(p []byte) (int, error) {
    method Close (line 738) | func (gp *GoPdf) Close() error {
    method compilePdf (line 743) | func (gp *GoPdf) compilePdf(w io.Writer) error {
    method GetBytesPdfReturnErr (line 787) | func (gp *GoPdf) GetBytesPdfReturnErr() ([]byte, error) {
    method GetBytesPdf (line 797) | func (gp *GoPdf) GetBytesPdf() []byte {
    method Text (line 806) | func (gp *GoPdf) Text(text string) error {
    method CellWithOption (line 822) | func (gp *GoPdf) CellWithOption(rectangle *Rect, text string, opt Cell...
    method Cell (line 845) | func (gp *GoPdf) Cell(rectangle *Rect, text string) error {
    method MultiCell (line 866) | func (gp *GoPdf) MultiCell(rectangle *Rect, text string) error {
    method SplitText (line 908) | func (gp *GoPdf) SplitText(text string, width float64) ([]string, erro...
    method ImportPage (line 948) | func (gp *GoPdf) ImportPage(sourceFile string, pageno int, box string)...
    method ImportPageStream (line 982) | func (gp *GoPdf) ImportPageStream(sourceStream *io.ReadSeeker, pageno ...
    method UseImportedTemplate (line 1014) | func (gp *GoPdf) UseImportedTemplate(tplid int, x float64, y float64, ...
    method GetNextObjectID (line 1022) | func (gp *GoPdf) GetNextObjectID() int {
    method GetNumberOfPages (line 1027) | func (gp *GoPdf) GetNumberOfPages() int {
    method ImportObjects (line 1032) | func (gp *GoPdf) ImportObjects(objs map[int]string, startObjID int) {
    method ImportTemplates (line 1041) | func (gp *GoPdf) ImportTemplates(tpls map[string]int) {
    method AddExternalLink (line 1049) | func (gp *GoPdf) AddExternalLink(url string, x, y, w, h float64) {
    method AddInternalLink (line 1056) | func (gp *GoPdf) AddInternalLink(anchor string, x, y, w, h float64) {
    method SetAnchor (line 1063) | func (gp *GoPdf) SetAnchor(name string) {
    method AddTTFFontData (line 1069) | func (gp *GoPdf) AddTTFFontData(family string, fontData []byte) error {
    method AddTTFFontDataWithOption (line 1074) | func (gp *GoPdf) AddTTFFontDataWithOption(family string, fontData []by...
    method AddTTFFontByReader (line 1090) | func (gp *GoPdf) AddTTFFontByReader(family string, rd io.Reader) error {
    method AddTTFFontByReaderWithOption (line 1095) | func (gp *GoPdf) AddTTFFontByReaderWithOption(family string, rd io.Rea...
    method setSubsetFontObject (line 1112) | func (gp *GoPdf) setSubsetFontObject(subsetFont *SubsetFontObj, family...
    method AddTTFFontWithOption (line 1161) | func (gp *GoPdf) AddTTFFontWithOption(family string, ttfpath string, o...
    method AddTTFFont (line 1175) | func (gp *GoPdf) AddTTFFont(family string, ttfpath string) error {
    method KernOverride (line 1180) | func (gp *GoPdf) KernOverride(family string, fn FuncKernOverride) error {
    method SetTextColor (line 1200) | func (gp *GoPdf) SetTextColor(r uint8, g uint8, b uint8) {
    method SetStrokeColor (line 1211) | func (gp *GoPdf) SetStrokeColor(r uint8, g uint8, b uint8) {
    method SetFillColor (line 1216) | func (gp *GoPdf) SetFillColor(r uint8, g uint8, b uint8) {
    method MeasureTextWidth (line 1221) | func (gp *GoPdf) MeasureTextWidth(text string) (float64, error) {
    method Curve (line 1242) | func (gp *GoPdf) Curve(x0 float64, y0 float64, x1 float64, y1 float64,...
    method SetInfo (line 1255) | func (gp *GoPdf) SetInfo(info PdfInfo) {
    method Rotate (line 1263) | func (gp *GoPdf) Rotate(angle, x, y float64) {
    method RotateReset (line 1269) | func (gp *GoPdf) RotateReset() {
    method Polygon (line 1283) | func (gp *GoPdf) Polygon(points []Point, style string) {
    method init (line 1297) | func (gp *GoPdf) init() {
    method resetCurrXY (line 1340) | func (gp *GoPdf) resetCurrXY() {
    method UnitsToPoints (line 1346) | func (gp *GoPdf) UnitsToPoints(u float64) float64 {
    method UnitsToPointsVar (line 1351) | func (gp *GoPdf) UnitsToPointsVar(u ...*float64) {
    method PointsToUnits (line 1356) | func (gp *GoPdf) PointsToUnits(u float64) float64 {
    method PointsToUnitsVar (line 1361) | func (gp *GoPdf) PointsToUnitsVar(u ...*float64) {
    method isUseProtection (line 1365) | func (gp *GoPdf) isUseProtection() bool {
    method createProtection (line 1369) | func (gp *GoPdf) createProtection() *PDFProtection {
    method protection (line 1379) | func (gp *GoPdf) protection() *PDFProtection {
    method prepare (line 1383) | func (gp *GoPdf) prepare() {
    method xref (line 1436) | func (gp *GoPdf) xref(w io.Writer, xrefbyteoffset int, linelens []int,...
    method writeInfo (line 1467) | func (gp *GoPdf) writeInfo(w io.Writer) {
    method formatXrefline (line 1499) | func (gp *GoPdf) formatXrefline(n int) string {
    method addObj (line 1507) | func (gp *GoPdf) addObj(iobj IObj) int {
    method getContent (line 1513) | func (gp *GoPdf) getContent() *ContentObj {
    method SetTransparency (line 1549) | func (gp *GoPdf) SetTransparency(transparency Transparency) error {
    method getCachedTransparency (line 1560) | func (gp *GoPdf) getCachedTransparency(transparency *Transparency) (*T...
    method saveTransparency (line 1575) | func (gp *GoPdf) saveTransparency(transparency *Transparency) (*Transp...
    method IsCurrFontContainGlyph (line 1604) | func (gp *GoPdf) IsCurrFontContainGlyph(r rune) (bool, error) {
  type DrawableRectOptions (line 83) | type DrawableRectOptions struct
  type CropOptions (line 93) | type CropOptions struct
  type ImageOptions (line 100) | type ImageOptions struct
  type MaskOptions (line 113) | type MaskOptions struct
  type countingWriter (line 770) | type countingWriter struct
    method Write (line 780) | func (cw *countingWriter) Write(b []byte) (int, error) {
  function newCountingWriter (line 776) | func newCountingWriter(w io.Writer) *countingWriter {
  function encodeUtf8 (line 1527) | func encodeUtf8(str string) string {
  function infodate (line 1539) | func infodate(t time.Time) string {

FILE: vendor/github.com/signintech/gopdf/i_cache_contneter.go
  type ICacheContent (line 7) | type ICacheContent interface

FILE: vendor/github.com/signintech/gopdf/ifont.go
  type IFont (line 4) | type IFont interface
  type FontCw (line 21) | type FontCw
  type FontDescItem (line 24) | type FontDescItem struct
  function ToByte (line 35) | func ToByte(chr string) byte {

FILE: vendor/github.com/signintech/gopdf/image_holder.go
  type ImageHolder (line 12) | type ImageHolder interface
  function ImageHolderByBytes (line 18) | func ImageHolderByBytes(b []byte) (ImageHolder, error) {
  function ImageHolderByPath (line 23) | func ImageHolderByPath(path string) (ImageHolder, error) {
  function ImageHolderByReader (line 28) | func ImageHolderByReader(r io.Reader) (ImageHolder, error) {
  type imageBuff (line 33) | type imageBuff struct
    method ID (line 79) | func (i *imageBuff) ID() string {
  function newImageBuff (line 38) | func newImageBuff(b []byte) (*imageBuff, error) {
  function newImageBuffByPath (line 50) | func newImageBuffByPath(path string) (*imageBuff, error) {
  function newImageBuffByReader (line 61) | func newImageBuffByReader(r io.Reader) (*imageBuff, error) {

FILE: vendor/github.com/signintech/gopdf/image_obj.go
  type ImageObj (line 19) | type ImageObj struct
    method init (line 29) | func (i *ImageObj) init(funcGetRoot func() *GoPdf) {
    method setProtection (line 33) | func (i *ImageObj) setProtection(p *PDFProtection) {
    method protection (line 37) | func (i *ImageObj) protection() *PDFProtection {
    method write (line 41) | func (i *ImageObj) write(w io.Writer, objID int) error {
    method isColspaceIndexed (line 88) | func (i *ImageObj) isColspaceIndexed() bool {
    method haveSMask (line 92) | func (i *ImageObj) haveSMask() bool {
    method createSMask (line 96) | func (i *ImageObj) createSMask() (*SMask, error) {
    method createDeviceRGB (line 109) | func (i *ImageObj) createDeviceRGB() (*DeviceRGBObj, error) {
    method getType (line 115) | func (i *ImageObj) getType() string {
    method SetImagePath (line 120) | func (i *ImageObj) SetImagePath(path string) error {
    method SetImage (line 136) | func (i *ImageObj) SetImage(r io.Reader) error {
    method GetRect (line 148) | func (i *ImageObj) GetRect() *Rect {
    method getRect (line 158) | func (i *ImageObj) getRect() (*Rect, error) {
    method parse (line 190) | func (i *ImageObj) parse() error {
    method Parse (line 203) | func (i *ImageObj) Parse() error {

FILE: vendor/github.com/signintech/gopdf/image_obj_parse.go
  type ColorSpaces (line 16) | type ColorSpaces
  constant DeviceGray (line 19) | DeviceGray = "DeviceGray"
  function writeMaskImgProps (line 22) | func writeMaskImgProps(w io.Writer, imginfo imgInfo) error {
  function writeImgProps (line 41) | func writeImgProps(w io.Writer, imginfo imgInfo, splittedMask bool) error {
  function writeBaseImgProps (line 83) | func writeBaseImgProps(w io.Writer, imginfo imgInfo, colorSpace string) ...
  function isColspaceIndexed (line 113) | func isColspaceIndexed(imginfo imgInfo) bool {
  function haveSMask (line 120) | func haveSMask(imginfo imgInfo) bool {
  function parseImgByPath (line 127) | func parseImgByPath(path string) (imgInfo, error) {
  function parseImg (line 135) | func parseImg(raw *bytes.Reader) (imgInfo, error) {
  function parseImgJpg (line 169) | func parseImgJpg(info *imgInfo, imgConfig image.Config) error {
  function parsePng (line 192) | func parsePng(f *bytes.Reader, info *imgInfo, imgConfig image.Config) er...
  function compress (line 448) | func compress(data []byte) ([]byte, error) {
  function readUInt (line 464) | func readUInt(f *bytes.Reader) (uint, error) {
  function readInt (line 474) | func readInt(f *bytes.Reader) (int, error) {
  function readBytes (line 489) | func readBytes(f *bytes.Reader, len int) ([]byte, error) {
  function isDeviceRGB (line 498) | func isDeviceRGB(formatname string, img *image.Image) bool {
  function ImgReactagleToWH (line 508) | func ImgReactagleToWH(imageRect image.Rectangle) (float64, float64) {

FILE: vendor/github.com/signintech/gopdf/img_info.go
  type imgInfo (line 3) | type imgInfo struct

FILE: vendor/github.com/signintech/gopdf/imported_obj.go
  type ImportedObj (line 8) | type ImportedObj struct
    method init (line 12) | func (c *ImportedObj) init(funcGetRoot func() *GoPdf) {
    method getType (line 16) | func (c *ImportedObj) getType() string {
    method write (line 20) | func (c *ImportedObj) write(w io.Writer, objID int) error {

FILE: vendor/github.com/signintech/gopdf/iobj.go
  type IObj (line 8) | type IObj interface

FILE: vendor/github.com/signintech/gopdf/link_option.go
  type anchorOption (line 3) | type anchorOption struct
  type linkOption (line 8) | type linkOption struct

FILE: vendor/github.com/signintech/gopdf/list_cache_content.go
  type listCacheContent (line 5) | type listCacheContent struct
    method last (line 9) | func (l *listCacheContent) last() ICacheContent {
    method append (line 17) | func (l *listCacheContent) append(cache ICacheContent) {
    method appendContentText (line 21) | func (l *listCacheContent) appendContentText(cache cacheContentText, t...
    method write (line 62) | func (l *listCacheContent) write(w io.Writer, protection *PDFProtectio...

FILE: vendor/github.com/signintech/gopdf/map_of_character_To_glyph_index.go
  type MapOfCharacterToGlyphIndex (line 4) | type MapOfCharacterToGlyphIndex struct
    method KeyExists (line 18) | func (m *MapOfCharacterToGlyphIndex) KeyExists(k rune) bool {
    method Set (line 31) | func (m *MapOfCharacterToGlyphIndex) Set(k rune, v uint) {
    method Index (line 38) | func (m *MapOfCharacterToGlyphIndex) Index(k rune) (int, bool) {
    method Val (line 51) | func (m *MapOfCharacterToGlyphIndex) Val(k rune) (uint, bool) {
    method AllKeys (line 60) | func (m *MapOfCharacterToGlyphIndex) AllKeys() []rune {
    method AllVals (line 65) | func (m *MapOfCharacterToGlyphIndex) AllVals() []uint {
  function NewMapOfCharacterToGlyphIndex (line 11) | func NewMapOfCharacterToGlyphIndex() *MapOfCharacterToGlyphIndex {

FILE: vendor/github.com/signintech/gopdf/margin.go
  type Margins (line 4) | type Margins struct
  method SetLeftMargin (line 9) | func (gp *GoPdf) SetLeftMargin(margin float64) {
  method SetTopMargin (line 15) | func (gp *GoPdf) SetTopMargin(margin float64) {
  method SetMargins (line 21) | func (gp *GoPdf) SetMargins(left, top, right, bottom float64) {
  method SetMarginLeft (line 27) | func (gp *GoPdf) SetMarginLeft(margin float64) {
  method SetMarginTop (line 32) | func (gp *GoPdf) SetMarginTop(margin float64) {
  method SetMarginRight (line 37) | func (gp *GoPdf) SetMarginRight(margin float64) {
  method SetMarginBottom (line 42) | func (gp *GoPdf) SetMarginBottom(margin float64) {
  method Margins (line 47) | func (gp *GoPdf) Margins() (float64, float64, float64, float64) {
  method MarginLeft (line 55) | func (gp *GoPdf) MarginLeft() float64 {
  method MarginTop (line 60) | func (gp *GoPdf) MarginTop() float64 {
  method MarginRight (line 65) | func (gp *GoPdf) MarginRight() float64 {
  method MarginBottom (line 70) | func (gp *GoPdf) MarginBottom() float64 {

FILE: vendor/github.com/signintech/gopdf/outlines_obj.go
  type OutlinesObj (line 9) | type OutlinesObj struct
    method init (line 19) | func (o *OutlinesObj) init(funcGetRoot func() *GoPdf) {
    method getType (line 25) | func (o *OutlinesObj) getType() string {
    method write (line 29) | func (o *OutlinesObj) write(w io.Writer, objID int) error {
    method SetIndexObjOutlines (line 51) | func (o *OutlinesObj) SetIndexObjOutlines(index int) {
    method AddOutline (line 55) | func (o *OutlinesObj) AddOutline(dest int, title string) {
    method Count (line 68) | func (o *OutlinesObj) Count() int {
  type OutlineObj (line 72) | type OutlineObj struct
    method init (line 81) | func (o *OutlineObj) init(funcGetRoot func() *GoPdf) {
    method getType (line 84) | func (o *OutlineObj) getType() string {
    method write (line 88) | func (o *OutlineObj) write(w io.Writer, objID int) error {

FILE: vendor/github.com/signintech/gopdf/page_obj.go
  type PageObj (line 10) | type PageObj struct
    method init (line 18) | func (p *PageObj) init(funcGetRoot func() *GoPdf) {
    method setOption (line 23) | func (p *PageObj) setOption(opt PageOption) {
    method write (line 27) | func (p *PageObj) write(w io.Writer, objID int) error {
    method writeExternalLink (line 72) | func (p *PageObj) writeExternalLink(w io.Writer, l linkOption, objID i...
    method writeInternalLink (line 92) | func (p *PageObj) writeInternalLink(w io.Writer, l linkOption, anchors...
    method getType (line 102) | func (p *PageObj) getType() string {

FILE: vendor/github.com/signintech/gopdf/page_option.go
  type PageOption (line 4) | type PageOption struct
    method isEmpty (line 9) | func (p PageOption) isEmpty() bool {
    method isTrimBoxSet (line 16) | func (p PageOption) isTrimBoxSet() bool {

FILE: vendor/github.com/signintech/gopdf/pages_obj.go
  type PagesObj (line 9) | type PagesObj struct
    method init (line 15) | func (p *PagesObj) init(funcGetRoot func() *GoPdf) {
    method write (line 20) | func (p *PagesObj) write(w io.Writer, objID int) error {
    method getType (line 33) | func (p *PagesObj) getType() string {
    method test (line 37) | func (p *PagesObj) test() {

FILE: vendor/github.com/signintech/gopdf/pdf_dictionary_obj.go
  type PdfDictionaryObj (line 26) | type PdfDictionaryObj struct
    method init (line 32) | func (p *PdfDictionaryObj) init(funcGetRoot func() *GoPdf) {
    method setProtection (line 36) | func (p *PdfDictionaryObj) setProtection(pr *PDFProtection) {
    method protection (line 40) | func (p *PdfDictionaryObj) protection() *PDFProtection {
    method write (line 44) | func (p *PdfDictionaryObj) write(w io.Writer, objID int) error {
    method getType (line 82) | func (p *PdfDictionaryObj) getType() string {
    method SetPtrToSubsetFontObj (line 87) | func (p *PdfDictionaryObj) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {
    method makeGlyfAndLocaTable (line 91) | func (p *PdfDictionaryObj) makeGlyfAndLocaTable() ([]byte, []int, erro...
    method getGlyphSize (line 145) | func (p *PdfDictionaryObj) getGlyphSize(glyph int) int {
    method getGlyphData (line 154) | func (p *PdfDictionaryObj) getGlyphData(glyph int) []byte {
    method makeFont (line 169) | func (p *PdfDictionaryObj) makeFont() ([]byte, error) {
    method completeGlyphClosure (line 266) | func (p *PdfDictionaryObj) completeGlyphClosure(mapOfglyphs *MapOfChar...
    method AddCompositeGlyphs (line 292) | func (p *PdfDictionaryObj) AddCompositeGlyphs(glyphArray *[]int, glyph...
    method GetOffset (line 351) | func (p *PdfDictionaryObj) GetOffset(glyph int) int {
  constant hasScale (line 344) | hasScale = 8
  constant moreComponents (line 345) | moreComponents = 32
  constant arg1and2areWords (line 346) | arg1and2areWords = 1
  constant xAndYScale (line 347) | xAndYScale = 64
  constant twoByTwo (line 348) | twoByTwo = 128
  function CheckSum (line 359) | func CheckSum(data []byte) uint {

FILE: vendor/github.com/signintech/gopdf/pdf_info_obj.go
  type PdfInfo (line 6) | type PdfInfo struct

FILE: vendor/github.com/signintech/gopdf/pdf_protection.go
  constant PermissionsPrint (line 13) | PermissionsPrint = 4
  constant PermissionsModify (line 15) | PermissionsModify = 8
  constant PermissionsCopy (line 17) | PermissionsCopy = 16
  constant PermissionsAnnotForms (line 19) | PermissionsAnnotForms = 32
  type PDFProtection (line 28) | type PDFProtection struct
    method SetProtection (line 38) | func (p *PDFProtection) SetProtection(permissions int, userPass []byte...
    method setProtection (line 42) | func (p *PDFProtection) setProtection(permissions int, userPass []byte...
    method generateEncryptionKey (line 50) | func (p *PDFProtection) generateEncryptionKey(userPass []byte, ownerPa...
    method EncryptionObj (line 75) | func (p *PDFProtection) EncryptionObj() *EncryptionObj {
    method encryptionObj (line 79) | func (p *PDFProtection) encryptionObj() *EncryptionObj {
    method createOValue (line 87) | func (p *PDFProtection) createOValue(userPassWithPadding []byte, owner...
    method createUValue (line 99) | func (p *PDFProtection) createUValue(userPassWithPadding []byte, oValu...
    method randomPass (line 116) | func (p *PDFProtection) randomPass(strlen int) []byte {
    method Objectkey (line 127) | func (p *PDFProtection) Objectkey(objID int) []byte {
    method objectkey (line 131) | func (p *PDFProtection) objectkey(n int) []byte {
  function rc4Cip (line 139) | func rc4Cip(key []byte, src []byte) ([]byte, error) {

FILE: vendor/github.com/signintech/gopdf/point.go
  type Point (line 4) | type Point struct

FILE: vendor/github.com/signintech/gopdf/procset_obj.go
  type ProcSetObj (line 9) | type ProcSetObj struct
    method init (line 18) | func (pr *ProcSetObj) init(funcGetRoot func() *GoPdf) {
    method write (line 24) | func (pr *ProcSetObj) write(w io.Writer, objID int) error {
    method getType (line 65) | func (pr *ProcSetObj) getType() string {
  type RelateFonts (line 70) | type RelateFonts
    method IsContainsFamily (line 73) | func (re *RelateFonts) IsContainsFamily(family string) bool {
    method IsContainsFamilyAndStyle (line 83) | func (re *RelateFonts) IsContainsFamilyAndStyle(family string, style i...
  type RelateFont (line 93) | type RelateFont struct
  type RelateXobjects (line 103) | type RelateXobjects
  type RelateXobject (line 106) | type RelateXobject struct
  type ExtGS (line 111) | type ExtGS struct

FILE: vendor/github.com/signintech/gopdf/rect.go
  type Rect (line 4) | type Rect struct
    method PointsToUnits (line 11) | func (rect *Rect) PointsToUnits(t int) (r *Rect) {
    method UnitsToPoints (line 26) | func (rect *Rect) UnitsToPoints(t int) (r *Rect) {

FILE: vendor/github.com/signintech/gopdf/smask_obj.go
  type SMaskSubtypes (line 9) | type SMaskSubtypes
  constant SMaskAlphaSubtype (line 12) | SMaskAlphaSubtype      = "/Alpha"
  constant SMaskLuminositySubtype (line 13) | SMaskLuminositySubtype = "/Luminosity"
  type SMask (line 17) | type SMask struct
    method init (line 53) | func (s SMask) init(func() *GoPdf) {}
    method setProtection (line 55) | func (s *SMask) setProtection(p *PDFProtection) {
    method protection (line 59) | func (s SMask) protection() *PDFProtection {
    method getType (line 63) | func (s SMask) getType() string {
    method write (line 67) | func (s SMask) write(w io.Writer, objID int) error {
  type SMaskOptions (line 27) | type SMaskOptions struct
    method GetId (line 32) | func (smask SMaskOptions) GetId() string {
  function GetCachedMask (line 38) | func GetCachedMask(opts SMaskOptions, gp *GoPdf) SMask {
  type SMaskMap (line 102) | type SMaskMap struct
    method Find (line 114) | func (smask *SMaskMap) Find(sMask SMaskOptions) (SMask, bool) {
    method Save (line 129) | func (smask *SMaskMap) Save(id string, sMask SMask) SMask {
  function NewSMaskMap (line 107) | func NewSMaskMap() SMaskMap {

FILE: vendor/github.com/signintech/gopdf/strhelper.go
  function StrHelperGetStringWidth (line 9) | func StrHelperGetStringWidth(str string, fontSize int, ifont IFont) floa...
  function CreateEmbeddedFontSubsetName (line 22) | func CreateEmbeddedFontSubsetName(name string) string {
  function ReadShortFromByte (line 29) | func ReadShortFromByte(data []byte, offset int) (int64, int) {
  function ReadUShortFromByte (line 44) | func ReadUShortFromByte(data []byte, offset int) (uint64, int) {

FILE: vendor/github.com/signintech/gopdf/style.go
  type PaintStyle (line 3) | type PaintStyle
  constant DrawPaintStyle (line 6) | DrawPaintStyle     PaintStyle = "S"
  constant FillPaintStyle (line 7) | FillPaintStyle     PaintStyle = "f"
  constant DrawFillPaintStyle (line 8) | DrawFillPaintStyle PaintStyle = "B"
  function parseStyle (line 11) | func parseStyle(style string) PaintStyle {

FILE: vendor/github.com/signintech/gopdf/subfont_descriptor_obj.go
  type SubfontDescriptorObj (line 11) | type SubfontDescriptorObj struct
    method init (line 16) | func (s *SubfontDescriptorObj) init(func() *GoPdf) {}
    method getType (line 18) | func (s *SubfontDescriptorObj) getType() string {
    method write (line 22) | func (s *SubfontDescriptorObj) write(w io.Writer, objID int) error {
    method SetIndexObjPdfDictionary (line 47) | func (s *SubfontDescriptorObj) SetIndexObjPdfDictionary(index int) {
    method SetPtrToSubsetFontObj (line 52) | func (s *SubfontDescriptorObj) SetPtrToSubsetFontObj(ptr *SubsetFontOb...
  function DesignUnitsToPdf (line 57) | func DesignUnitsToPdf(val int, unitsPerEm uint) int {

FILE: vendor/github.com/signintech/gopdf/subset_font_obj.go
  type SubsetFontObj (line 18) | type SubsetFontObj struct
    method init (line 29) | func (s *SubsetFontObj) init(funcGetRoot func() *GoPdf) {
    method write (line 34) | func (s *SubsetFontObj) write(w io.Writer, objID int) error {
    method SetIndexObjCIDFont (line 48) | func (s *SubsetFontObj) SetIndexObjCIDFont(index int) {
    method SetIndexObjUnicodeMap (line 53) | func (s *SubsetFontObj) SetIndexObjUnicodeMap(index int) {
    method SetFamily (line 58) | func (s *SubsetFontObj) SetFamily(familyname string) {
    method GetFamily (line 63) | func (s *SubsetFontObj) GetFamily() string {
    method SetTtfFontOption (line 68) | func (s *SubsetFontObj) SetTtfFontOption(option TtfOption) {
    method GetTtfFontOption (line 73) | func (s *SubsetFontObj) GetTtfFontOption() TtfOption {
    method KernValueByLeft (line 78) | func (s *SubsetFontObj) KernValueByLeft(left uint) (bool, *core.KernVa...
    method SetTTFByPath (line 97) | func (s *SubsetFontObj) SetTTFByPath(ttfpath string) error {
    method SetTTFByReader (line 108) | func (s *SubsetFontObj) SetTTFByReader(rd io.Reader) error {
    method SetTTFData (line 119) | func (s *SubsetFontObj) SetTTFData(data []byte) error {
    method AddChars (line 130) | func (s *SubsetFontObj) AddChars(txt string) error {
    method CharIndex (line 150) | func (s *SubsetFontObj) CharIndex(r rune) (uint, error) {
    method CharWidth (line 159) | func (s *SubsetFontObj) CharWidth(r rune) (uint, error) {
    method getType (line 167) | func (s *SubsetFontObj) getType() string {
    method charCodeToGlyphIndexFormat12 (line 171) | func (s *SubsetFontObj) charCodeToGlyphIndexFormat12(r rune) (uint, er...
    method charCodeToGlyphIndexFormat4 (line 185) | func (s *SubsetFontObj) charCodeToGlyphIndexFormat4(r rune) (uint, err...
    method CharCodeToGlyphIndex (line 215) | func (s *SubsetFontObj) CharCodeToGlyphIndex(r rune) (uint, error) {
    method GlyphIndexToPdfWidth (line 232) | func (s *SubsetFontObj) GlyphIndexToPdfWidth(glyphIndex uint) uint {
    method GetTTFParser (line 248) | func (s *SubsetFontObj) GetTTFParser() *core.TTFParser {
    method GetUt (line 253) | func (s *SubsetFontObj) GetUt() int {
    method GetUp (line 258) | func (s *SubsetFontObj) GetUp() int {

FILE: vendor/github.com/signintech/gopdf/transparency.go
  type BlendModeType (line 10) | type BlendModeType
  constant Hue (line 13) | Hue             BlendModeType = "/Hue"
  constant Color (line 14) | Color           BlendModeType = "/Color"
  constant NormalBlendMode (line 15) | NormalBlendMode BlendModeType = "/Normal"
  constant Darken (line 16) | Darken          BlendModeType = "/Darken"
  constant Screen (line 17) | Screen          BlendModeType = "/Screen"
  constant Overlay (line 18) | Overlay         BlendModeType = "/Overlay"
  constant Lighten (line 19) | Lighten         BlendModeType = "/Lighten"
  constant Multiply (line 20) | Multiply        BlendModeType = "/Multiply"
  constant Exclusion (line 21) | Exclusion       BlendModeType = "/Exclusion"
  constant ColorBurn (line 22) | ColorBurn       BlendModeType = "/ColorBurn"
  constant HardLight (line 23) | HardLight       BlendModeType = "/HardLight"
  constant SoftLight (line 24) | SoftLight       BlendModeType = "/SoftLight"
  constant Difference (line 25) | Difference      BlendModeType = "/Difference"
  constant Saturation (line 26) | Saturation      BlendModeType = "/Saturation"
  constant Luminosity (line 27) | Luminosity      BlendModeType = "/Luminosity"
  constant ColorDodge (line 28) | ColorDodge      BlendModeType = "/ColorDodge"
  constant DefaultAplhaValue (line 31) | DefaultAplhaValue = 1
  type Transparency (line 34) | type Transparency struct
    method GetId (line 56) | func (t Transparency) GetId() string {
  function NewTransparency (line 40) | func NewTransparency(alpha float64, blendModeType string) (Transparency,...
  type TransparencyMap (line 62) | type TransparencyMap struct
    method Find (line 74) | func (tm *TransparencyMap) Find(transparency Transparency) (Transparen...
    method Save (line 89) | func (tm *TransparencyMap) Save(transparency Transparency) Transparency {
  function NewTransparencyMap (line 67) | func NewTransparencyMap() TransparencyMap {
  function defineBlendModeType (line 99) | func defineBlendModeType(bmType string) (BlendModeType, error) {

FILE: vendor/github.com/signintech/gopdf/transparency_xobject_group.go
  type TransparencyXObjectGroup (line 8) | type TransparencyXObjectGroup struct
    method init (line 41) | func (s TransparencyXObjectGroup) init(funcGetRoot func() *GoPdf) {
    method setProtection (line 45) | func (s *TransparencyXObjectGroup) setProtection(p *PDFProtection) {
    method protection (line 49) | func (s TransparencyXObjectGroup) protection() *PDFProtection {
    method getType (line 53) | func (s TransparencyXObjectGroup) getType() string {
    method write (line 57) | func (s TransparencyXObjectGroup) write(w io.Writer, objId int) error {
  type TransparencyXObjectGroupOptions (line 19) | type TransparencyXObjectGroupOptions struct
  function GetCachedTransparencyXObjectGroup (line 26) | func GetCachedTransparencyXObjectGroup(opts TransparencyXObjectGroupOpti...

FILE: vendor/github.com/signintech/gopdf/ttf_option.go
  type TtfOption (line 4) | type TtfOption struct
  function defaultTtfFontOption (line 10) | func defaultTtfFontOption() TtfOption {

FILE: vendor/github.com/signintech/gopdf/unicode_map.go
  type UnicodeMap (line 9) | type UnicodeMap struct
    method init (line 15) | func (u *UnicodeMap) init(funcGetRoot func() *GoPdf) {
    method setProtection (line 19) | func (u *UnicodeMap) setProtection(p *PDFProtection) {
    method protection (line 23) | func (u *UnicodeMap) protection() *PDFProtection {
    method SetPtrToSubsetFontObj (line 28) | func (u *UnicodeMap) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {
    method getType (line 32) | func (u *UnicodeMap) getType() string {
    method write (line 36) | func (u *UnicodeMap) write(w io.Writer, objID int) error {
  type mapGlyphIndexToCharacter (line 101) | type mapGlyphIndexToCharacter struct
    method set (line 111) | func (m *mapGlyphIndexToCharacter) set(index int, r rune) {
    method size (line 116) | func (m *mapGlyphIndexToCharacter) size() int {
    method allIndexs (line 120) | func (m *mapGlyphIndexToCharacter) allIndexs() []int {
    method runeByIndex (line 124) | func (m *mapGlyphIndexToCharacter) runeByIndex(index int) (rune, bool) {
  function newMapGlyphIndexToCharacter (line 106) | func newMapGlyphIndexToCharacter() *mapGlyphIndexToCharacter {
Condensed preview — 108 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (346K chars).
[
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 2429,
    "preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
  },
  {
    "path": ".github/workflows/go.yml",
    "chars": 357,
    "preview": "name: Go\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n\n  build:\n    runs-on: ubuntu"
  },
  {
    "path": ".github/workflows/golangci-lint.yml",
    "chars": 314,
    "preview": "name: golangci-lint\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\njobs:\n  golangci:\n    name"
  },
  {
    "path": ".gitignore",
    "chars": 72,
    "preview": "# PDF files\n*.pdf\n\n# Test binary, built with `go test -c`\n*.test\n\n.idea/"
  },
  {
    "path": "LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2021 Leonid Sopov\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "README.md",
    "chars": 3487,
    "preview": "# resumeio2pdf\n\n> ⚠️ This project is no longer maintained.  \n> Resume.io made changes on their side, so the tool no long"
  },
  {
    "path": "go.mod",
    "chars": 91,
    "preview": "module github.com/sopov/resumeio2pdf\n\ngo 1.16\n\nrequire github.com/signintech/gopdf v0.9.20\n"
  },
  {
    "path": "go.sum",
    "chars": 511,
    "preview": "github.com/phpdave11/gofpdi v1.0.11 h1:wsBNx+3S0wy1dEp6fzv281S74ogZGgIdYWV2PugWgho=\ngithub.com/phpdave11/gofpdi v1.0.11/"
  },
  {
    "path": "main.go",
    "chars": 7297,
    "preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regex"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/LICENSE",
    "chars": 1151,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2019-2020 David Barnes\nCopyright (c) 2017 Setasign - Jan Slabon, https://www.setasi"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/README.md",
    "chars": 6942,
    "preview": "# gofpdi\n[![MIT\nlicensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/phpdave1"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/const.go",
    "chars": 251,
    "preview": "package gofpdi\n\nconst (\n\tPDF_TYPE_NULL = iota\n\tPDF_TYPE_NUMERIC\n\tPDF_TYPE_TOKEN\n\tPDF_TYPE_HEX\n\tPDF_TYPE_STRING\n\tPDF_TYPE"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/go.mod",
    "chars": 82,
    "preview": "module github.com/phpdave11/gofpdi\n\ngo 1.12\n\nrequire github.com/pkg/errors v0.8.1\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/go.sum",
    "chars": 161,
    "preview": "github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwaw"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/gofpdi.go",
    "chars": 15,
    "preview": "package gofpdi\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/helper.go",
    "chars": 2717,
    "preview": "package gofpdi\n\nimport (\n\t\"strings\"\n)\n\n// Determine if a value is numeric\n// Courtesy of https://github.com/syyongx/php2"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/importer.go",
    "chars": 5629,
    "preview": "package gofpdi\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// The Importer class to be used by a pdf generation library\ntype Importer stru"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/reader.go",
    "chars": 40612,
    "preview": "package gofpdi\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"compress/zlib\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"github.com/pkg/errors\"\n\t\"io\"\n\t\"i"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/writer.go",
    "chars": 12785,
    "preview": "package gofpdi\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"compress/zlib\"\n\t\"crypto/sha1\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"github.com/pkg/error"
  },
  {
    "path": "vendor/github.com/pkg/errors/.gitignore",
    "chars": 266,
    "preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
  },
  {
    "path": "vendor/github.com/pkg/errors/.travis.yml",
    "chars": 175,
    "preview": "language: go\ngo_import_path: github.com/pkg/errors\ngo:\n  - 1.4.x\n  - 1.5.x\n  - 1.6.x\n  - 1.7.x\n  - 1.8.x\n  - 1.9.x\n  - 1"
  },
  {
    "path": "vendor/github.com/pkg/errors/LICENSE",
    "chars": 1312,
    "preview": "Copyright (c) 2015, Dave Cheney <dave@cheney.net>\nAll rights reserved.\n\nRedistribution and use in source and binary form"
  },
  {
    "path": "vendor/github.com/pkg/errors/README.md",
    "chars": 2371,
    "preview": "# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci."
  },
  {
    "path": "vendor/github.com/pkg/errors/appveyor.yml",
    "chars": 639,
    "preview": "version: build-{build}.{branch}\n\nclone_folder: C:\\gopath\\src\\github.com\\pkg\\errors\nshallow_clone: true # for startup spe"
  },
  {
    "path": "vendor/github.com/pkg/errors/errors.go",
    "chars": 7204,
    "preview": "// Package errors provides simple error handling primitives.\n//\n// The traditional error handling idiom in Go is roughly"
  },
  {
    "path": "vendor/github.com/pkg/errors/stack.go",
    "chars": 3380,
    "preview": "package errors\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"path\"\n\t\"runtime\"\n\t\"strings\"\n)\n\n// Frame represents a program counter inside a st"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/.gitignore",
    "chars": 717,
    "preview": "##android\n# built application files\n*.apk\n*.ap_\n\n# files for the dex VM\n*.dex\n\n# Java class files\n*.class\n\n# generated f"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/Changelog.md",
    "chars": 131,
    "preview": "### May 2016\n\nRemove old function\n- ```GoPdf.AddFont(family string, ifont IFont, zfontpath string)```.\n- Remove all font"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/LICENSE",
    "chars": 1078,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 signintech\n\nPermission is hereby granted, free of charge, to any person obtain"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/README.md",
    "chars": 7181,
    "preview": "gopdf\n====\n\ngopdf is a simple library for generating PDF document written in Go lang.\n\n\n#### Features\n\n- Unicode subfont"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/box.go",
    "chars": 532,
    "preview": "package gopdf\n\ntype Box struct {\n\tLeft, Top, Right, Bottom float64\n\tunitOverride             int\n}\n\n// UnitsToPoints con"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/buff.go",
    "chars": 682,
    "preview": "package gopdf\n\n//Buff for pdf content\ntype Buff struct {\n\tposition int\n\tdatas    []byte\n}\n\n//Write : write []byte to buf"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/buff_write.go",
    "chars": 930,
    "preview": "package gopdf\n\nimport \"io\"\n\n//WriteUInt32  writes a 32-bit unsigned integer value to w io.Writer\nfunc WriteUInt32(w io.W"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/buffer_pool.go",
    "chars": 435,
    "preview": "package gopdf\n\nimport (\n\t\"bytes\"\n\t\"sync\"\n)\n\n// buffer pool to reduce GC\nvar buffers = sync.Pool{\n\t// New is called when "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_contact_color.go",
    "chars": 370,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nconst colorTypeStroke = \"RG\"\n\nconst colorTypeFill = \"rg\"\n\ntype cacheContentColor"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_gray.go",
    "chars": 307,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nconst grayTypeFill = \"g\"\nconst grayTypeStroke = \"G\"\n\ntype cacheContentGray struc"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_image.go",
    "chars": 1825,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentImage struct {\n\tverticalFlip     bool\n\thorizontalFlip   bool\n\ti"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_imported_object.go",
    "chars": 459,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentImportedTemplate struct {\n\tpageHeight float64\n\ttplName    strin"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_line.go",
    "chars": 370,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentLine struct {\n\tpageHeight float64\n\tx1         float64\n\ty1      "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_line_type.go",
    "chars": 349,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentLineType struct {\n\tlineType string\n}\n\nfunc (c *cacheContentLine"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_line_width.go",
    "chars": 231,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentLineWidth struct {\n\twidth float64\n}\n\nfunc (c *cacheContentLineW"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_oval.go",
    "chars": 1243,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentOval struct {\n\tpageHeight float64\n\tx1         float64\n\ty1      "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_polygon.go",
    "chars": 572,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentPolygon struct {\n\tpageHeight float64\n\tstyle      string\n\tpoints"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_rectangle.go",
    "chars": 1145,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentRectangle struct {\n\tpageHeight       float64\n\tx                "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_rotate.go",
    "chars": 536,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n)\n\ntype cacheContentRotate struct {\n\tisReset     bool\n\tpageHeight  float64\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_text.go",
    "chars": 9846,
    "preview": "package gopdf\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n)\n\n//ContentTypeCell cell\nconst ContentTypeCell = 0\n\n//ContentTypeText te"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_contnent_curve.go",
    "chars": 789,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentCurve struct {\n\tpageHeight float64\n\tx0         float64\n\ty0     "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/catalog_obj.go",
    "chars": 711,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//CatalogObj : catalog dictionary\ntype CatalogObj struct { //impl IObj\n\toutlines"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cell_option.go",
    "chars": 756,
    "preview": "package gopdf\n\n//Left left\nconst Left = 8 //001000\n//Top top\nconst Top = 4 //000100\n//Right right\nconst Right = 2 //0000"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cid_font_obj.go",
    "chars": 1572,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// CIDFontObj is a CID-keyed font.\n// cf. https://www.adobe.com/content/dam/acom"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/config.go",
    "chars": 2461,
    "preview": "package gopdf\n\n// The units that can be used in the document\nconst (\n\tUnitUnset = iota // No units were set, when conver"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/content_obj.go",
    "chars": 9780,
    "preview": "package gopdf\n\nimport (\n\t\"compress/zlib\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n)\n\n//ContentObj content object\ntype ContentObj struct {"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/current.go",
    "chars": 1563,
    "preview": "package gopdf\n\n//Current current state\ntype Current struct {\n\tsetXCount int //many times we go func SetX()\n\tX         fl"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/device_rgb_obj.go",
    "chars": 834,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//DeviceRGBObj  DeviceRGB\ntype DeviceRGBObj struct {\n\tdata    []byte\n\tgetRoot fu"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/embedfont_obj.go",
    "chars": 1179,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n)\n\n// EmbedFontObj is an embedded font object.\ntype EmbedFontObj struc"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/encoding_obj.go",
    "chars": 671,
    "preview": "package gopdf\n\nimport (\n\t\"io\"\n)\n\n// EncodingObj is a font object.\ntype EncodingObj struct {\n\tfont IFont\n}\n\nfunc (e *Enco"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/encryption_obj.go",
    "chars": 968,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n)\n\n//EncryptionObj  encryption object res\ntype EncryptionObj struct {\n\tu"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/ext_g_state_obj.go",
    "chars": 2846,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"sync\"\n\n\t\"github.com/pkg/errors\"\n)\n\n// TODO: add all fields https://www.adobe.com/"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/font_obj.go",
    "chars": 1431,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//FontObj font obj\ntype FontObj struct {\n\tFamily string\n\t//Style string\n\t//Size "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/font_option.go",
    "chars": 572,
    "preview": "package gopdf\n\nimport (\n\t\"strings\"\n)\n\n//Regular - font style regular\nconst Regular = 0 //000000\n//Italic - font style it"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontconverthelper.go",
    "chars": 612,
    "preview": "package gopdf\n\nimport (\n\t\"strconv\"\n\t//\"fmt\"\n\t\"bytes\"\n)\n\n// FontConvertHelperCw2Str converts main ASCII characters of a F"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontdescriptor_obj.go",
    "chars": 1126,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// FontDescriptorObj is a font descriptor object.\ntype FontDescriptorObj struct "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/fontmaker.go",
    "chars": 11791,
    "preview": "package core\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"compress/zlib\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/fontmap.go",
    "chars": 61,
    "preview": "package core\n\ntype FontMap struct {\n\tUv   int\n\tName string\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/kern_table.go",
    "chars": 498,
    "preview": "package core\n\n//KernTable https://www.microsoft.com/typography/otspec/kern.htm\ntype KernTable struct {\n\tVersion uint //f"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/math.go",
    "chars": 128,
    "preview": "package core\n\nfunc Round(value float64) int {\n\tif value < 0.0 {\n\t\tvalue -= 0.5\n\t} else {\n\t\tvalue += 0.5\n\t}\n\treturn int(v"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/table_directory_entry.go",
    "chars": 189,
    "preview": "package core\n\ntype TableDirectoryEntry struct {\n\tCheckSum uint\n\tOffset   uint\n\tLength   uint\n}\n\nfunc (t TableDirectoryEn"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttf_info.go",
    "chars": 2106,
    "preview": "package core\n\nimport (\n\t\"errors\"\n)\n\nvar ERROR_NO_KEY_FOUND = errors.New(\"no key found\")\nvar ERROR_NO_GET_WRONG_TYPE = er"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser.go",
    "chars": 19402,
    "preview": "package core\n\nimport (\n\t//\"encoding/binary\"\n\t//\"encoding/hex\"\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/io"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser_cmap_other_format.go",
    "chars": 2356,
    "preview": "package core\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n)\n\n//ParseCmapFormat12 parse cmap table format 12 https://www.microsoft.com/ty"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser_kern.go",
    "chars": 1879,
    "preview": "package core\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n//Parsekern parse kerning table  https://www.microsoft.com/typography/otspec/k"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/func_kern_override.go",
    "chars": 184,
    "preview": "package gopdf\n\n//FuncKernOverride  return your custome pair value\ntype FuncKernOverride func(\n\tleftRune rune,\n\trightRune"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/go.mod",
    "chars": 124,
    "preview": "module github.com/signintech/gopdf\n\ngo 1.11\n\nrequire (\n\tgithub.com/phpdave11/gofpdi v1.0.11\n\tgithub.com/pkg/errors v0.8."
  },
  {
    "path": "vendor/github.com/signintech/gopdf/go.sum",
    "chars": 336,
    "preview": "github.com/phpdave11/gofpdi v1.0.11 h1:wsBNx+3S0wy1dEp6fzv281S74ogZGgIdYWV2PugWgho=\ngithub.com/phpdave11/gofpdi v1.0.11/"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/gopdf.go",
    "chars": 41399,
    "preview": "package gopdf\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"compress/zlib\" // for constants\n\t\"fmt\"\n\t\"image\"\n\t\"image/jpeg\"\n\t\"io\"\n\t\"io/iou"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/i_cache_contneter.go",
    "chars": 119,
    "preview": "package gopdf\n\nimport (\n\t\"io\"\n)\n\ntype ICacheContent interface {\n\twrite(w io.Writer, protection *PDFProtection) error\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/ifont.go",
    "chars": 650,
    "preview": "package gopdf\n\n// IFont represents a font interface.\ntype IFont interface {\n\tInit()\n\tGetType() string\n\tGetName() string\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/image_holder.go",
    "chars": 1433,
    "preview": "package gopdf\n\nimport (\n\t\"bytes\"\n\t\"crypto/md5\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n)\n\n//ImageHolder hold image data\ntype ImageHold"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/image_obj.go",
    "chars": 3756,
    "preview": "package gopdf\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"image\"\n\t// Packages image/jpeg and image/png are not used explicitly in the co"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/image_obj_parse.go",
    "chars": 10273,
    "preview": "package gopdf\n\nimport (\n\t\"bytes\"\n\t\"compress/zlib\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"image\"\n\t\"image/color\"\n\t\"io\"\n\t\"io"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/img_info.go",
    "chars": 345,
    "preview": "package gopdf\n\ntype imgInfo struct {\n\tw, h int\n\t//src              string\n\tformatName       string\n\tcolspace         str"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/imported_obj.go",
    "chars": 362,
    "preview": "package gopdf\n\nimport (\n\t\"io\"\n)\n\n//ImportedObj : imported object\ntype ImportedObj struct { //impl IObj\n\tData string\n}\n\nf"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/iobj.go",
    "chars": 168,
    "preview": "package gopdf\n\nimport (\n\t\"io\"\n)\n\n//IObj inteface for all pdf object\ntype IObj interface {\n\tinit(func() *GoPdf)\n\tgetType("
  },
  {
    "path": "vendor/github.com/signintech/gopdf/link_option.go",
    "chars": 154,
    "preview": "package gopdf\n\ntype anchorOption struct {\n\tpage int\n\ty    float64\n}\n\ntype linkOption struct {\n\tx, y, w, h float64\n\turl  "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/list_cache_content.go",
    "chars": 1415,
    "preview": "package gopdf\n\nimport \"io\"\n\ntype listCacheContent struct {\n\tcaches []ICacheContent\n}\n\nfunc (l *listCacheContent) last() "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/map_of_character_To_glyph_index.go",
    "chars": 1424,
    "preview": "package gopdf\n\n//MapOfCharacterToGlyphIndex map of CharacterToGlyphIndex\ntype MapOfCharacterToGlyphIndex struct {\n\tkeyIn"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/margin.go",
    "chars": 2102,
    "preview": "package gopdf\n\n// Margins type.\ntype Margins struct {\n\tLeft, Top, Right, Bottom float64\n}\n\n// SetLeftMargin sets left ma"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/outlines_obj.go",
    "chars": 1926,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//OutlinesObj : outlines dictionary\ntype OutlinesObj struct { //impl IObj\n\tgetRo"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/page_obj.go",
    "chars": 2777,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n)\n\n//PageObj pdf page object\ntype PageObj struct { //impl IObj\n\tContents"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/page_option.go",
    "chars": 411,
    "preview": "package gopdf\n\n//PageOption option of page\ntype PageOption struct {\n\tTrimBox  *Box\n\tPageSize *Rect\n}\n\nfunc (p PageOption"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/page_sizes.go",
    "chars": 1886,
    "preview": "package gopdf\n\n// PageSizeLetter page format\nvar PageSizeLetter = &Rect{W: 612, H: 792, unitOverride: UnitPT}\n\n// PageSi"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pages_obj.go",
    "chars": 801,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//PagesObj pdf pages object\ntype PagesObj struct { //impl IObj\n\tPageCount int\n\tK"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pdf_dictionary_obj.go",
    "chars": 9213,
    "preview": "package gopdf\n\nimport (\n\t\"compress/zlib\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"sort\"\n\n\t\"github.com/signintech/gopdf/fontmaker/core\"\n)"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pdf_info_obj.go",
    "chars": 697,
    "preview": "package gopdf\n\nimport \"time\"\n\n//PdfInfo Document Information Dictionary\ntype PdfInfo struct {\n\tTitle        string    //"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pdf_protection.go",
    "chars": 3968,
    "preview": "package gopdf\n\nimport (\n\t\"crypto/md5\"\n\t\"crypto/rc4\"\n\t\"encoding/binary\"\n\t\"math/rand\"\n\t\"time\"\n)\n\nconst (\n\t//PermissionsPri"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/point.go",
    "chars": 96,
    "preview": "package gopdf\n\n//Point a point in a two-dimensional\ntype Point struct {\n\tX float64\n\tY float64\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/procset_obj.go",
    "chars": 2509,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// ProcSetObj is a PDF procSet object.\ntype ProcSetObj struct {\n\t//Font\n\tRelates"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/rect.go",
    "chars": 863,
    "preview": "package gopdf\n\n// Rect defines a rectangle.\ntype Rect struct {\n\tW            float64\n\tH            float64\n\tunitOverride"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/smask_obj.go",
    "chars": 2626,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"sync\"\n)\n\ntype SMaskSubtypes string\n\nconst (\n\tSMaskAlphaSubtype      = \"/Alpha\"\n\tS"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/strhelper.go",
    "chars": 1075,
    "preview": "package gopdf\n\nimport (\n\t\"math/big\"\n\t\"strings\"\n)\n\n//StrHelperGetStringWidth get string width\nfunc StrHelperGetStringWidt"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/style.go",
    "chars": 354,
    "preview": "package gopdf\n\ntype PaintStyle string\n\nconst (\n\tDrawPaintStyle     PaintStyle = \"S\"\n\tFillPaintStyle     PaintStyle = \"f\""
  },
  {
    "path": "vendor/github.com/signintech/gopdf/subfont_descriptor_obj.go",
    "chars": 2033,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/signintech/gopdf/fontmaker/core\"\n)\n\n//SubfontDescriptorObj pdf subfon"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/subset_font_obj.go",
    "chars": 6382,
    "preview": "package gopdf\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/signintech/gopdf/fontmaker/core\"\n)\n\n//ErrCharNotFound char "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/transparency.go",
    "chars": 3096,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\n\t\"github.com/pkg/errors\"\n)\n\ntype BlendModeType string\n\nconst (\n\tHue             "
  },
  {
    "path": "vendor/github.com/signintech/gopdf/transparency_xobject_group.go",
    "chars": 2159,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype TransparencyXObjectGroup struct {\n\tIndex            int\n\tBBox             ["
  },
  {
    "path": "vendor/github.com/signintech/gopdf/ttf_option.go",
    "chars": 285,
    "preview": "package gopdf\n\n//TtfOption  font option\ntype TtfOption struct {\n\tUseKerning      bool\n\tStyle           int // Regular|Bo"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/unicode_map.go",
    "chars": 3151,
    "preview": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//UnicodeMap unicode map\ntype UnicodeMap struct {\n\tPtrToSubsetFontObj *SubsetFon"
  },
  {
    "path": "vendor/modules.txt",
    "chars": 240,
    "preview": "# github.com/phpdave11/gofpdi v1.0.11\ngithub.com/phpdave11/gofpdi\n# github.com/pkg/errors v0.8.1\ngithub.com/pkg/errors\n#"
  }
]

About this extraction

This page contains the full source code of the sopov/resumeio2pdf GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 108 files (300.1 KB), approximately 96.1k tokens, and a symbol index with 794 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!