[
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ main ]\n  schedule:\n    - cron: '43 20 * * 5'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'go' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]\n        # Learn more:\n        # 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\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v2\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v1\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n        # queries: ./path/to/local/query, your-org/your-repo/queries@main\n\n    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    - name: Autobuild\n      uses: github/codeql-action/autobuild@v1\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 https://git.io/JvXDl\n\n    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines\n    #    and modify them (or add more) to build your code if your project\n    #    uses a compiled language\n\n    #- run: |\n    #   make bootstrap\n    #   make release\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v1\n"
  },
  {
    "path": ".github/workflows/go.yml",
    "content": "name: Go\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v2\n\n    - name: Set up Go\n      uses: actions/setup-go@v2\n      with:\n        go-version: 1.17\n\n    - name: Build\n      run: go build -v ./...\n\n    - name: Test\n      run: go test -v ./...\n"
  },
  {
    "path": ".github/workflows/golangci-lint.yml",
    "content": "name: golangci-lint\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\njobs:\n  golangci:\n    name: lint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: golangci-lint\n        uses: golangci/golangci-lint-action@v2\n        with:\n          version: latest\n"
  },
  {
    "path": ".gitignore",
    "content": "# PDF files\n*.pdf\n\n# Test binary, built with `go test -c`\n*.test\n\n.idea/"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Leonid Sopov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# resumeio2pdf\n\n> ⚠️ This project is no longer maintained.  \n> Resume.io made changes on their side, so the tool no longer works.\n\nA progam that allows users to download their resumes from [resume.io](https://resume.io/) as PDFs, including links.\n\n## Usage\n\n```bash\n./resumeio2pdf [options] [ID or URL]\n./resumeio2pdf https://resume.io/r/SecureID\n```\n\nOptions:\n*  `-pdf` (string)  name of pdf file (default: `SecureID` + `.pdf`)\n*  `-sid` (string) SecureID of resume\n*  `-url` (string) link to resume of the format: https://resume.io/r/SecureID\n*  `-verbose` show detail information\n*  `-version` show version\n*  `-y`\toverwrite PDF file\n\n## Quick Instructions\n1. Run `go build` to generate the executable.\n2. Run `./resumeio2pdf https://resume.io/r/[SecureID]` where the provided URL is that generated by the **Share Link** on resume.io.\n\n## Step-by-Step Instructions\n1. Download the application by clicking the **<> Code** button and choosing **Download ZIP**.\n \n2. Once the download has been completed, extract the files. You will end up with a **resumeio2pdf-main/** folder.\n\n3. Open your terminal and navigate to the **resumeio2pdf-main/** folder that you have just extracted.\n- You may have the option to skip this by simply choosing the **New Terminal at Folder** after right clicking on the folder.\n\n4. With your terminal still open, type the command `go version` to see if you already have Go installed.\n- If you get a message with version information that looks something like `go version go1.17.6 …` then you can skip to Step 6.\n- Otherwise, continue on to the next step.\n\n5. 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.\n- 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. \n\n6. With Go installed, you can now run the `go build` command to build the executable file that will download your PDF.\n- 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. \n- 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.\n\n7. 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.\n\n## Alternative Methods\nRepository with binary files: https://github.com/sopov/resumeio2pdf.bin\n\n## Other Questions and Concerns\n* I don't understand how to install and/or use Go.\n* Can you download my resume for me? \n* Can you make a video tutorial?\n\nPlease 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.\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/sopov/resumeio2pdf\n\ngo 1.16\n\nrequire github.com/signintech/gopdf v0.9.20\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/phpdave11/gofpdi v1.0.11 h1:wsBNx+3S0wy1dEp6fzv281S74ogZGgIdYWV2PugWgho=\ngithub.com/phpdave11/gofpdi v1.0.11/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/signintech/gopdf v0.9.20 h1:UJInJStc5NpkSCSZCmkSrUy7JR/BqRWpoH50c7hJJ5w=\ngithub.com/signintech/gopdf v0.9.20/go.mod h1:PXwitUSeFWEWs+wHVjSS3cUmD4PTXB686ozqfDIQQoQ=\n"
  },
  {
    "path": "main.go",
    "content": "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\"regexp\"\n\t\"time\"\n\n\t\"github.com/signintech/gopdf\"\n)\n\nconst (\n\tVersion       = \"1.0\"\n\tNameOfProgram = \"resumeio2pdf\"\n\tCopy          = \"Copyright (c) 2021, Leonid Sopov <leonid@sopov.org>\"\n\tCopyURL       = \"https://github.com/sopov/resumeio2pdf/\"\n\n\tresumePage = \"https://resume.io/r/%s\"\n\tresumeMeta = \"https://ssr.resume.tools/meta/ssid-%s?cache=%s\"\n\tresumeExt  = \"png\" // png, jpeg\n\tresumeIMG  = \"https://ssr.resume.tools/to-image/ssid-%s-%d.%s?cache=%s&size=%d\"\n\tresumeSize = 1800\n\tTimeout    = 60 * time.Second\n\n\texitCodeMisuseArgs = 2\n)\n\nvar (\n\turl         = flag.String(\"url\", \"\", \"link to resume of the format: https://resume.io/r/SecureID\")\n\tsid         = flag.String(\"sid\", \"\", \"SecureID of resume\")\n\tshowVersion = flag.Bool(\"version\", false, \"show version\")\n\tverbose     = flag.Bool(\"verbose\", false, \"show detail information\")\n\toverWrite   = flag.Bool(\"y\", false, \"overwrite PDF file\")\n\tpdfFileName = flag.String(\"pdf\", \"\", \"name of pdf file (default: SecureID + .pdf)\")\n\n\thttpClient = &http.Client{Timeout: Timeout}\n\treSID      = regexp.MustCompile(`^[[:alnum:]]+$`)\n\treID       = regexp.MustCompile(`^\\d+$`)\n\treURL      = regexp.MustCompile(`^https://resume[.]io/r/([[:alnum:]]+)`)\n\treIDURL    = regexp.MustCompile(`^https://resume[.]io/(?:app|api)/.*?/(\\d+)`)\n)\n\ntype metaLink struct {\n\tURL    string  `json:\"url\"`\n\tLeft   float64 `json:\"left\"`\n\tTop    float64 `json:\"top\"`\n\tHeight float64 `json:\"height\"`\n\tWidth  float64 `json:\"width\"`\n}\n\ntype metaViewPort struct {\n\tHeight float64 `json:\"height\"`\n\tWidth  float64 `json:\"width\"`\n}\n\ntype metaPageInfo struct {\n\tLinks    []metaLink   `json:\"links\"`\n\tViewPort metaViewPort `json:\"viewport\"`\n}\n\ntype metaInfo struct {\n\tPages []metaPageInfo `json:\"pages\"`\n}\n\nfunc main() {\n\tif !readFlags() || *sid == \"\" {\n\t\tos.Exit(exitCodeMisuseArgs)\n\t}\n\n\tloggerf(\"SecureID: %s\", *sid)\n\tloggerf(\"URL: %s\", *url)\n\tloggerf(\"PDF: %s\", *pdfFileName)\n\n\tmeta, err := getMeta()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\timages, err := getResumeImages(len(meta.Pages))\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\terr = generatePDF(meta, images)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tcleanup(images)\n\n\tfmt.Printf(\"Resume stored to %s\\n\", *pdfFileName)\n}\n\nfunc cleanup(images []string) {\n\tfor _, file := range images {\n\t\tif _, err := os.Stat(file); os.IsNotExist(err) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := os.Remove(file); err != nil {\n\t\t\tfmt.Printf(\"Error on remove `%s': %s\", file, err.Error())\n\t\t} else {\n\t\t\tloggerf(\"Image `%s' successfully deleted.\", file)\n\t\t}\n\t}\n}\n\nfunc generatePDF(info *metaInfo, images []string) error {\n\tpdf := gopdf.GoPdf{}\n\n\tlogger(\"Start Generate PDF\")\n\n\tpageSize := gopdf.Rect{\n\t\tW: info.Pages[0].ViewPort.Width,\n\t\tH: info.Pages[0].ViewPort.Height,\n\t}\n\n\tpdf.Start(gopdf.Config{PageSize: pageSize})\n\n\tfor i, image := range images {\n\t\tloggerf(\"Add page #%d\", i+1)\n\n\t\tpageSize := gopdf.Rect{\n\t\t\tW: info.Pages[i].ViewPort.Width,\n\t\t\tH: info.Pages[i].ViewPort.Height,\n\t\t}\n\n\t\topt := gopdf.PageOption{\n\t\t\tPageSize: &pageSize,\n\t\t}\n\t\tpdf.AddPageWithOption(opt)\n\n\t\terr := pdf.Image(image, 0, 0, &pageSize)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tfor _, link := range info.Pages[i].Links {\n\t\t\tloggerf(\"Add link to %s\", link.URL)\n\n\t\t\tx := link.Left\n\t\t\ty := pageSize.H - link.Top - link.Height\n\t\t\tpdf.AddExternalLink(link.URL, x, y, link.Width, link.Height)\n\t\t}\n\t}\n\n\tloggerf(\"Store PDF to `%s'\", *pdfFileName)\n\n\treturn pdf.WritePdf(*pdfFileName)\n}\n\nfunc getResumeImages(p int) (pages []string, err error) {\n\tif p < 1 {\n\t\treturn nil, errors.New(\"required one or more pages\")\n\t}\n\n\tfor pID := 1; pID <= p; pID++ {\n\t\tpageFile := fmt.Sprintf(\"%s-%d.%s\", *sid, pID, resumeExt)\n\t\tif _, err := os.Stat(pageFile); os.IsNotExist(err) {\n\t\t\tloggerf(\"Download image #%d/%d\", pID, p)\n\t\t\timgURL := fmt.Sprintf(resumeIMG, *sid, pID, resumeExt, time.Now().UTC().Format(time.RFC3339), resumeSize)\n\n\t\t\tif err := downloadPage(imgURL, pageFile); err != nil {\n\t\t\t\treturn pages, err\n\t\t\t}\n\t\t}\n\n\t\tpages = append(pages, pageFile)\n\t}\n\n\tloggerf(\"Total %d pages\", len(pages))\n\n\treturn pages, nil\n}\n\nfunc downloadPage(imgURL, imgFile string) error {\n\tr, err := httpClient.Get(imgURL)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer r.Body.Close()\n\n\tif r.StatusCode != http.StatusOK {\n\t\treturn errors.New(r.Status)\n\t}\n\n\tfile, err := os.Create(imgFile)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer file.Close()\n\n\t_, err = io.Copy(file, r.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc getJSON(url string, target interface{}) error {\n\tlogger(\"Download meta information\")\n\n\tr, err := httpClient.Get(url)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer r.Body.Close()\n\n\tif r.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"Can't download information from the site resume.io. Please, check URL.\\n\\nError: %s\", r.Status)\n\t}\n\n\tdecoder := json.NewDecoder(r.Body)\n\n\terr = decoder.Decode(&target)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc getMeta() (meta *metaInfo, err error) {\n\tmetaURL := fmt.Sprintf(resumeMeta, *sid, time.Now().UTC().Format(time.RFC3339))\n\tmeta = &metaInfo{}\n\terr = getJSON(metaURL, meta)\n\n\treturn meta, err\n}\n\nfunc readFlags() bool {\n\tflag.Parse()\n\n\tif *showVersion {\n\t\tfmt.Printf(\"Version: %s\\n\", Version)\n\n\t\treturn false\n\t}\n\n\tif !extractArg() {\n\t\treturn false\n\t}\n\n\tif *sid == \"\" && *url == \"\" {\n\t\tusages()\n\t\treturn false\n\t}\n\n\tif *sid != \"\" {\n\t\tif !reSID.MatchString(*sid) {\n\t\t\tfmt.Println(\"The ID must be as alphanumeric\")\n\t\t\treturn false\n\t\t}\n\n\t\t*url = fmt.Sprintf(resumePage, *sid)\n\t}\n\n\tif reIDURL.MatchString(*url) {\n\t\tusageID()\n\t\treturn false\n\t}\n\n\tif !reURL.MatchString(*url) {\n\t\tmsg := fmt.Sprintf(\"The URL must be in the format %s\\n\", resumePage)\n\t\tfmt.Printf(msg, \"SecureID\")\n\n\t\treturn false\n\t}\n\n\tif *sid == \"\" {\n\t\tm := reURL.FindSubmatch([]byte(*url))\n\t\t*sid = string(m[1])\n\t}\n\n\tif *pdfFileName == \"\" {\n\t\t*pdfFileName = fmt.Sprintf(\"%s.pdf\", *sid)\n\t}\n\n\trePDF := regexp.MustCompile(`(?i)[.]pdf$`)\n\tif !rePDF.MatchString(*pdfFileName) {\n\t\t*pdfFileName = fmt.Sprintf(\"%s.pdf\", *pdfFileName)\n\t}\n\n\tif _, err := os.Stat(*pdfFileName); !*overWrite && !os.IsNotExist(err) {\n\t\tfmt.Printf(\"File `%s' already exists.\\n\\nFor overwrite run with `-y' flag\\n\", *pdfFileName)\n\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc extractArg() bool {\n\targ := flag.Arg(0)\n\n\tif arg == \"\" {\n\t\treturn true\n\t}\n\n\tif reID.MatchString(arg) {\n\t\tusageID()\n\t\treturn false\n\t}\n\n\tif reIDURL.MatchString(arg) {\n\t\tusageID()\n\t\treturn false\n\t}\n\n\tif reSID.MatchString(arg) {\n\t\t*sid = arg\n\t\treturn true\n\t}\n\n\tif reURL.MatchString(arg) {\n\t\t*url = arg\n\t\treturn true\n\t}\n\n\treturn true\n}\n\nfunc usages() {\n\tfileExec, err := os.Executable()\n\tif err == nil {\n\t\tfileExec = filepath.Base(fileExec)\n\t}\n\n\tif fileExec == \"\" {\n\t\tfileExec = NameOfProgram\n\t}\n\n\tfmt.Println(\"Syntax:\")\n\tfmt.Println(\"  \", fileExec, \"[options] [ID or URL]\")\n\n\tfmt.Println()\n\tfmt.Println(\"Options:\")\n\tflag.PrintDefaults()\n\n\tfmt.Println()\n\tfmt.Println(Copy)\n\tfmt.Println(CopyURL)\n}\n\nfunc usageID() {\n\tfmt.Println(\"Open in browser: https://resume.io/app/resumes\")\n\tfmt.Println(\"Click on `...More' / `Share a link', and lunch with private URL.\")\n}\n\nfunc logger(v ...interface{}) {\n\tif !*verbose {\n\t\treturn\n\t}\n\n\tlog.Println(v...)\n}\n\nfunc loggerf(format string, a ...interface{}) {\n\tif !*verbose {\n\t\treturn\n\t}\n\n\tlog.Printf(format, a...)\n}\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019-2020 David Barnes\nCopyright (c) 2017 Setasign - Jan Slabon, https://www.setasign.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/README.md",
    "content": "# gofpdi\n[![MIT\nlicensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/phpdave11/gofpdi/master/LICENSE)\n[![Report](https://goreportcard.com/badge/github.com/phpdave11/gofpdi)](https://goreportcard.com/report/github.com/phpdave11/gofpdi)\n[![GoDoc](https://img.shields.io/badge/godoc-gofpdi-blue.svg)](https://godoc.org/github.com/phpdave11/gofpdi)\n\n## Go Free PDF Document Importer\n\ngofpdi allows you to import an existing PDF into a new PDF.  The following PDF generation libraries are supported:\n\n- [gopdf](https://github.com/signintech/gopdf)\n\n- [gofpdf](https://github.com/phpdave11/gofpdf)\n\n## Acknowledgments\nThis 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).\n[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.\n\n## Examples\n\n### gopdf example\n\n```go\npackage main\n\nimport (\n        \"github.com/signintech/gopdf\"\n        \"io\"\n        \"net/http\"\n        \"os\"\n)\n\nfunc main() {\n        var err error\n\n        // Download a Font\n        fontUrl := \"https://github.com/google/fonts/raw/master/ofl/daysone/DaysOne-Regular.ttf\"\n        if err = DownloadFile(\"example-font.ttf\", fontUrl); err != nil {\n                panic(err)\n        }\n\n        // Download a PDF\n        fileUrl := \"https://tcpdf.org/files/examples/example_012.pdf\"\n        if err = DownloadFile(\"example-pdf.pdf\", fileUrl); err != nil {\n                panic(err)\n        }\n\n        pdf := gopdf.GoPdf{}\n        pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4\n\n        pdf.AddPage()\n\n        err = pdf.AddTTFFont(\"daysone\", \"example-font.ttf\")\n        if err != nil {\n                panic(err)\n        }\n\n        err = pdf.SetFont(\"daysone\", \"\", 20)\n        if err != nil {\n                panic(err)\n        }\n\n        // Color the page\n        pdf.SetLineWidth(0.1)\n        pdf.SetFillColor(124, 252, 0) //setup fill color\n        pdf.RectFromUpperLeftWithStyle(50, 100, 400, 600, \"FD\")\n        pdf.SetFillColor(0, 0, 0)\n\n        pdf.SetX(50)\n        pdf.SetY(50)\n        pdf.Cell(nil, \"Import existing PDF into GoPDF Document\")\n\n        // Import page 1\n        tpl1 := pdf.ImportPage(\"example-pdf.pdf\", 1, \"/MediaBox\")\n\n        // Draw pdf onto page\n        pdf.UseImportedTemplate(tpl1, 50, 100, 400, 0)\n\n        pdf.WritePdf(\"example.pdf\")\n\n}\n\n// DownloadFile will download a url to a local file. It's efficient because it will\n// write as it downloads and not load the whole file into memory.\nfunc DownloadFile(filepath string, url string) error {\n        // Get the data\n        resp, err := http.Get(url)\n        if err != nil {\n                return err\n        }\n        defer resp.Body.Close()\n\n        // Create the file\n        out, err := os.Create(filepath)\n        if err != nil {\n                return err\n        }\n        defer out.Close()\n\n        // Write the body to file\n        _, err = io.Copy(out, resp.Body)\n        return err\n}\n```\n\nGenerated PDF: [example.pdf](https://github.com/signintech/gopdf/files/3144466/example.pdf)\n\nScreenshot of PDF:\n\n![example](https://user-images.githubusercontent.com/9421180/57180557-4c1dbd80-6e4f-11e9-8f47-9d40217805be.jpg)\n\n### gofpdf example #1 - import PDF from file\n\n```go\npackage main\n\nimport (\n\t\"github.com/phpdave11/gofpdf\"\n\t\"github.com/phpdave11/gofpdf/contrib/gofpdi\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\tvar err error\n\n\tpdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\n\n\t// Download a PDF\n\tfileUrl := \"https://tcpdf.org/files/examples/example_026.pdf\"\n\tif err = DownloadFile(\"example-pdf.pdf\", fileUrl); err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Import example-pdf.pdf with gofpdi free pdf document importer\n\ttpl1 := gofpdi.ImportPage(pdf, \"example-pdf.pdf\", 1, \"/MediaBox\")\n\n\tpdf.AddPage()\n\n\tpdf.SetFillColor(200, 700, 220)\n\tpdf.Rect(20, 50, 150, 215, \"F\")\n\n\t// Draw imported template onto page\n\tgofpdi.UseImportedTemplate(pdf, tpl1, 20, 50, 150, 0)\n\n\tpdf.SetFont(\"Helvetica\", \"\", 20)\n\tpdf.Cell(0, 0, \"Import existing PDF into gofpdf document with gofpdi\")\n\n\terr = pdf.OutputFileAndClose(\"example.pdf\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// DownloadFile will download a url to a local file. It's efficient because it will\n// write as it downloads and not load the whole file into memory.\nfunc DownloadFile(filepath string, url string) error {\n\t// Get the data\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\t// Create the file\n\tout, err := os.Create(filepath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer out.Close()\n\n\t// Write the body to file\n\t_, err = io.Copy(out, resp.Body)\n\treturn err\n}\n```\n\nGenerated PDF:  [example.pdf](https://github.com/phpdave11/gofpdf/files/3178770/example.pdf)\n\nScreenshot of PDF:\n![example](https://user-images.githubusercontent.com/9421180/57713804-ca8d1300-7638-11e9-9f8e-e3f803374803.jpg)\n\n\n\n### gofpdf example #2 - import PDF from stream\n\n```go\npackage main\n\nimport (\n    \"bytes\"\n    \"github.com/phpdave11/gofpdf\"\n    \"github.com/phpdave11/gofpdf/contrib/gofpdi\"\n    \"io\"\n    \"io/ioutil\"\n    \"net/http\"\n)\n\nfunc main() {\n    var err error\n\n    pdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\n\n    // Download a PDF into memory                                                                                                                     \n    res, err := http.Get(\"https://tcpdf.org/files/examples/example_038.pdf\")\n    if err != nil {\n        panic(err)\n    }\n    pdfBytes, err := ioutil.ReadAll(res.Body)\n    res.Body.Close()\n    if err != nil {\n        panic(err)\n    }\n\n    // convert []byte to io.ReadSeeker                                                                                                                \n    rs := io.ReadSeeker(bytes.NewReader(pdfBytes))\n\n    // Import in-memory PDF stream with gofpdi free pdf document importer                                                                             \n    tpl1 := gofpdi.ImportPageFromStream(pdf, &rs, 1, \"/TrimBox\")\n\n    pdf.AddPage()\n\n    pdf.SetFillColor(200, 700, 220)\n    pdf.Rect(20, 50, 150, 215, \"F\")\n\n    // Draw imported template onto page                                                                                                               \n    gofpdi.UseImportedTemplate(pdf, tpl1, 20, 50, 150, 0)\n\n    pdf.SetFont(\"Helvetica\", \"\", 20)\n    pdf.Cell(0, 0, \"Import PDF stream into gofpdf document with gofpdi\")\n\n    err = pdf.OutputFileAndClose(\"example.pdf\")\n    if err != nil {\n        panic(err)\n    }\n}\n```\n\nGenerated PDF:\n\n[example.pdf](https://github.com/phpdave11/gofpdi/files/3483219/example.pdf)\n\nScreenshot of PDF:\n\n![example.jpg](https://user-images.githubusercontent.com/9421180/62728726-18b87500-b9e2-11e9-885c-7c68b7ac6222.jpg)\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/const.go",
    "content": "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_DICTIONARY\n\tPDF_TYPE_ARRAY\n\tPDF_TYPE_OBJDEC\n\tPDF_TYPE_OBJREF\n\tPDF_TYPE_OBJECT\n\tPDF_TYPE_STREAM\n\tPDF_TYPE_BOOLEAN\n\tPDF_TYPE_REAL\n)\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/go.mod",
    "content": "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",
    "content": "github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/gofpdi.go",
    "content": "package gofpdi\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/helper.go",
    "content": "package gofpdi\n\nimport (\n\t\"strings\"\n)\n\n// Determine if a value is numeric\n// Courtesy of https://github.com/syyongx/php2go/blob/master/php.go\nfunc is_numeric(val interface{}) bool {\n\tswitch val.(type) {\n\tcase int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:\n\tcase float32, float64, complex64, complex128:\n\t\treturn true\n\tcase string:\n\t\tstr := val.(string)\n\t\tif str == \"\" {\n\t\t\treturn false\n\t\t}\n\t\t// Trim any whitespace\n\t\tstr = strings.TrimSpace(str)\n\t\t//fmt.Println(str)\n\t\tif str[0] == '-' || str[0] == '+' {\n\t\t\tif len(str) == 1 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tstr = str[1:]\n\t\t}\n\t\t// hex\n\t\tif len(str) > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') {\n\t\t\tfor _, h := range str[2:] {\n\t\t\t\tif !((h >= '0' && h <= '9') || (h >= 'a' && h <= 'f') || (h >= 'A' && h <= 'F')) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\t// 0-9,Point,Scientific\n\t\tp, s, l := 0, 0, len(str)\n\t\tfor i, v := range str {\n\t\t\tif v == '.' { // Point\n\t\t\t\tif p > 0 || s > 0 || i+1 == l {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tp = i\n\t\t\t} else if v == 'e' || v == 'E' { // Scientific\n\t\t\t\tif i == 0 || s > 0 || i+1 == l {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\ts = i\n\t\t\t} else if v < '0' || v > '9' {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\treturn false\n}\n\nfunc in_array(needle interface{}, hystack interface{}) bool {\n\tswitch key := needle.(type) {\n\tcase string:\n\t\tfor _, item := range hystack.([]string) {\n\t\t\tif key == item {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\tcase int:\n\t\tfor _, item := range hystack.([]int) {\n\t\t\tif key == item {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\tcase int64:\n\t\tfor _, item := range hystack.([]int64) {\n\t\t\tif key == item {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\tdefault:\n\t\treturn false\n\t}\n\treturn false\n}\n\n// Taken from png library\n\n// intSize is either 32 or 64.\nconst intSize = 32 << (^uint(0) >> 63)\n\nfunc abs(x int) int {\n\t// m := -1 if x < 0. m := 0 otherwise.\n\tm := x >> (intSize - 1)\n\n\t// In two's complement representation, the negative number\n\t// of any number (except the smallest one) can be computed\n\t// by flipping all the bits and add 1. This is faster than\n\t// code with a branch.\n\t// See Hacker's Delight, section 2-4.\n\treturn (x ^ m) - m\n}\n\n// filterPaeth applies the Paeth filter to the cdat slice.\n// cdat is the current row's data, pdat is the previous row's data.\nfunc filterPaeth(cdat, pdat []byte, bytesPerPixel int) {\n\tvar a, b, c, pa, pb, pc int\n\tfor i := 0; i < bytesPerPixel; i++ {\n\t\ta, c = 0, 0\n\t\tfor j := i; j < len(cdat); j += bytesPerPixel {\n\t\t\tb = int(pdat[j])\n\t\t\tpa = b - c\n\t\t\tpb = a - c\n\t\t\tpc = abs(pa + pb)\n\t\t\tpa = abs(pa)\n\t\t\tpb = abs(pb)\n\t\t\tif pa <= pb && pa <= pc {\n\t\t\t\t// No-op.\n\t\t\t} else if pb <= pc {\n\t\t\t\ta = b\n\t\t\t} else {\n\t\t\t\ta = c\n\t\t\t}\n\t\t\ta += int(cdat[j])\n\t\t\ta &= 0xff\n\t\t\tcdat[j] = uint8(a)\n\t\t\tc = b\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/importer.go",
    "content": "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 struct {\n\tsourceFile string\n\treaders    map[string]*PdfReader\n\twriters    map[string]*PdfWriter\n\ttplMap     map[int]*TplInfo\n\ttplN       int\n\twriter     *PdfWriter\n}\n\ntype TplInfo struct {\n\tSourceFile string\n\tWriter     *PdfWriter\n\tTemplateId int\n}\n\nfunc (this *Importer) GetReader() *PdfReader {\n\treturn this.GetReaderForFile(this.sourceFile)\n}\n\nfunc (this *Importer) GetWriter() *PdfWriter {\n\treturn this.GetWriterForFile(this.sourceFile)\n}\n\nfunc (this *Importer) GetReaderForFile(file string) *PdfReader {\n\tif _, ok := this.readers[file]; ok {\n\t\treturn this.readers[file]\n\t}\n\n\treturn nil\n}\n\nfunc (this *Importer) GetWriterForFile(file string) *PdfWriter {\n\tif _, ok := this.writers[file]; ok {\n\t\treturn this.writers[file]\n\t}\n\n\treturn nil\n}\n\nfunc NewImporter() *Importer {\n\timporter := &Importer{}\n\timporter.init()\n\n\treturn importer\n}\n\nfunc (this *Importer) init() {\n\tthis.readers = make(map[string]*PdfReader, 0)\n\tthis.writers = make(map[string]*PdfWriter, 0)\n\tthis.tplMap = make(map[int]*TplInfo, 0)\n\tthis.writer, _ = NewPdfWriter(\"\")\n}\n\nfunc (this *Importer) SetSourceFile(f string) {\n\tthis.sourceFile = f\n\n\t// If reader hasn't been instantiated, do that now\n\tif _, ok := this.readers[this.sourceFile]; !ok {\n\t\treader, err := NewPdfReader(this.sourceFile)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tthis.readers[this.sourceFile] = reader\n\t}\n\n\t// If writer hasn't been instantiated, do that now\n\tif _, ok := this.writers[this.sourceFile]; !ok {\n\t\twriter, err := NewPdfWriter(\"\")\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\t// Make the next writer start template numbers at this.tplN\n\t\twriter.SetTplIdOffset(this.tplN)\n\t\tthis.writers[this.sourceFile] = writer\n\t}\n}\n\nfunc (this *Importer) SetSourceStream(rs *io.ReadSeeker) {\n\tthis.sourceFile = fmt.Sprintf(\"%v\", rs)\n\n\tif _, ok := this.readers[this.sourceFile]; !ok {\n\t\treader, err := NewPdfReaderFromStream(*rs)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tthis.readers[this.sourceFile] = reader\n\t}\n\n\t// If writer hasn't been instantiated, do that now\n\tif _, ok := this.writers[this.sourceFile]; !ok {\n\t\twriter, err := NewPdfWriter(\"\")\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\t// Make the next writer start template numbers at this.tplN\n\t\twriter.SetTplIdOffset(this.tplN)\n\t\tthis.writers[this.sourceFile] = writer\n\t}\n}\n\nfunc (this *Importer) GetPageSizes() map[int]map[string]map[string]float64 {\n\tresult, err := this.GetReader().getAllPageBoxes(1.0)\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treturn result\n}\n\nfunc (this *Importer) ImportPage(pageno int, box string) int {\n\tres, err := this.GetWriter().ImportPage(this.GetReader(), pageno, box)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Get current template id\n\ttplN := this.tplN\n\n\t// Set tpl info\n\tthis.tplMap[tplN] = &TplInfo{SourceFile: this.sourceFile, TemplateId: res, Writer: this.GetWriter()}\n\n\t// Increment template id\n\tthis.tplN++\n\n\treturn tplN\n}\n\nfunc (this *Importer) SetNextObjectID(objId int) {\n\tthis.GetWriter().SetNextObjectID(objId)\n}\n\n// Put form xobjects and get back a map of template names (e.g. /GOFPDITPL1) and their object ids (int)\nfunc (this *Importer) PutFormXobjects() map[string]int {\n\tres := make(map[string]int, 0)\n\ttplNamesIds, err := this.GetWriter().PutFormXobjects(this.GetReader())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfor tplName, pdfObjId := range tplNamesIds {\n\t\tres[tplName] = pdfObjId.id\n\t}\n\treturn res\n}\n\n// Put form xobjects and get back a map of template names (e.g. /GOFPDITPL1) and their object ids (sha1 hash)\nfunc (this *Importer) PutFormXobjectsUnordered() map[string]string {\n\tthis.GetWriter().SetUseHash(true)\n\tres := make(map[string]string, 0)\n\ttplNamesIds, err := this.GetWriter().PutFormXobjects(this.GetReader())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfor tplName, pdfObjId := range tplNamesIds {\n\t\tres[tplName] = pdfObjId.hash\n\t}\n\treturn res\n}\n\n// Get object ids (int) and their contents (string)\nfunc (this *Importer) GetImportedObjects() map[int]string {\n\tres := make(map[int]string, 0)\n\tpdfObjIdBytes := this.GetWriter().GetImportedObjects()\n\tfor pdfObjId, bytes := range pdfObjIdBytes {\n\t\tres[pdfObjId.id] = string(bytes)\n\t}\n\treturn res\n}\n\n// Get object ids (sha1 hash) and their contents ([]byte)\n// The contents may have references to other object hashes which will need to be replaced by the pdf generator library\n// The positions of the hashes (sha1 - 40 characters) can be obtained by calling GetImportedObjHashPos()\nfunc (this *Importer) GetImportedObjectsUnordered() map[string][]byte {\n\tres := make(map[string][]byte, 0)\n\tpdfObjIdBytes := this.GetWriter().GetImportedObjects()\n\tfor pdfObjId, bytes := range pdfObjIdBytes {\n\t\tres[pdfObjId.hash] = bytes\n\t}\n\treturn res\n}\n\n// Get the positions of the hashes (sha1 - 40 characters) within each object, to be replaced with\n// actual objects ids by the pdf generator library\nfunc (this *Importer) GetImportedObjHashPos() map[string]map[int]string {\n\tres := make(map[string]map[int]string, 0)\n\tpdfObjIdPosHash := this.GetWriter().GetImportedObjHashPos()\n\tfor pdfObjId, posHashMap := range pdfObjIdPosHash {\n\t\tres[pdfObjId.hash] = posHashMap\n\t}\n\treturn res\n}\n\n// For a given template id (returned from ImportPage), get the template name (e.g. /GOFPDITPL1) and\n// the 4 float64 values necessary to draw the template a x,y for a given width and height.\nfunc (this *Importer) UseTemplate(tplid int, _x float64, _y float64, _w float64, _h float64) (string, float64, float64, float64, float64) {\n\t// Look up template id in importer tpl map\n\ttplInfo := this.tplMap[tplid]\n\treturn tplInfo.Writer.UseTemplate(tplInfo.TemplateId, _x, _y, _w, _h)\n}\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/reader.go",
    "content": "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\"io/ioutil\"\n\t\"math\"\n\t\"os\"\n\t\"strconv\"\n)\n\ntype PdfReader struct {\n\tavailableBoxes []string\n\tstack          []string\n\ttrailer        *PdfValue\n\tcatalog        *PdfValue\n\tpages          []*PdfValue\n\txrefPos        int\n\txref           map[int]map[int]int\n\txrefStream     map[int][2]int\n\tf              io.ReadSeeker\n\tnBytes         int64\n\tsourceFile     string\n}\n\nfunc NewPdfReaderFromStream(rs io.ReadSeeker) (*PdfReader, error) {\n\tlength, err := rs.Seek(0, 2)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"Failed to determine stream length\")\n\t}\n\tparser := &PdfReader{f: rs, nBytes: length}\n\tif err := parser.init(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to initialize parser\")\n\t}\n\tif err := parser.read(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to read pdf from stream\")\n\t}\n\treturn parser, nil\n}\n\nfunc NewPdfReader(filename string) (*PdfReader, error) {\n\tvar err error\n\tf, err := os.Open(filename)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to open file\")\n\t}\n\tinfo, err := f.Stat()\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to obtain file information\")\n\t}\n\n\tparser := &PdfReader{f: f, sourceFile: filename, nBytes: info.Size()}\n\tif err = parser.init(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to initialize parser\")\n\t}\n\tif err = parser.read(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to read pdf\")\n\t}\n\n\treturn parser, nil\n}\n\nfunc (this *PdfReader) init() error {\n\tthis.availableBoxes = []string{\"/MediaBox\", \"/CropBox\", \"/BleedBox\", \"/TrimBox\", \"/ArtBox\"}\n\tthis.xref = make(map[int]map[int]int, 0)\n\tthis.xrefStream = make(map[int][2]int, 0)\n\terr := this.read()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to read pdf\")\n\t}\n\treturn nil\n}\n\ntype PdfValue struct {\n\tType       int\n\tString     string\n\tToken      string\n\tInt        int\n\tReal       float64\n\tBool       bool\n\tDictionary map[string]*PdfValue\n\tArray      []*PdfValue\n\tId         int\n\tNewId      int\n\tGen        int\n\tValue      *PdfValue\n\tStream     *PdfValue\n\tBytes      []byte\n}\n\n// Jump over comments\nfunc (this *PdfReader) skipComments(r *bufio.Reader) error {\n\tvar err error\n\tvar b byte\n\n\tfor {\n\t\tb, err = r.ReadByte()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to ReadByte while skipping comments\")\n\t\t}\n\n\t\tif b == '\\n' || b == '\\r' {\n\t\t\tif b == '\\r' {\n\t\t\t\t// Peek and see if next char is \\n\n\t\t\t\tb2, err := r.ReadByte()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.Wrap(err, \"Failed to read byte\")\n\t\t\t\t}\n\t\t\t\tif b2 != '\\n' {\n\t\t\t\t\tr.UnreadByte()\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Advance reader so that whitespace is ignored\nfunc (this *PdfReader) skipWhitespace(r *bufio.Reader) error {\n\tvar err error\n\tvar b byte\n\n\tfor {\n\t\tb, err = r.ReadByte()\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn errors.Wrap(err, \"Failed to read byte\")\n\t\t}\n\n\t\tif b == ' ' || b == '\\n' || b == '\\r' || b == '\\t' {\n\t\t\tcontinue\n\t\t} else {\n\t\t\tr.UnreadByte()\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Read a token\nfunc (this *PdfReader) readToken(r *bufio.Reader) (string, error) {\n\tvar err error\n\n\t// If there is a token available on the stack, pop it out and return it.\n\tif len(this.stack) > 0 {\n\t\tvar popped string\n\t\tpopped, this.stack = this.stack[len(this.stack)-1], this.stack[:len(this.stack)-1]\n\t\treturn popped, nil\n\t}\n\n\terr = this.skipWhitespace(r)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"Failed to skip whitespace\")\n\t}\n\n\tb, err := r.ReadByte()\n\tif err != nil {\n\t\tif err == io.EOF {\n\t\t\treturn \"\", nil\n\t\t}\n\t\treturn \"\", errors.Wrap(err, \"Failed to read byte\")\n\t}\n\n\tswitch b {\n\tcase '[', ']', '(', ')':\n\t\t// This is either an array or literal string delimeter, return it.\n\t\treturn string(b), nil\n\n\tcase '<', '>':\n\t\t// This could either be a hex string or a dictionary delimiter.\n\t\t// Determine the appropriate case and return the token.\n\t\tnb, err := r.ReadByte()\n\t\tif err != nil {\n\t\t\treturn \"\", errors.Wrap(err, \"Failed to read byte\")\n\t\t}\n\t\tif nb == b {\n\t\t\treturn string(b) + string(nb), nil\n\t\t} else {\n\t\t\tr.UnreadByte()\n\t\t\treturn string(b), nil\n\t\t}\n\n\tcase '%':\n\t\terr = this.skipComments(r)\n\t\tif err != nil {\n\t\t\treturn \"\", errors.Wrap(err, \"Failed to skip comments\")\n\t\t}\n\t\treturn this.readToken(r)\n\n\tdefault:\n\t\t// FIXME this may not be performant to create new strings for each byte\n\t\t// Is it probably better to create a buffer and then convert to a string at the end.\n\t\tstr := string(b)\n\n\tloop:\n\t\tfor {\n\t\t\tb, err := r.ReadByte()\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", errors.Wrap(err, \"Failed to read byte\")\n\t\t\t}\n\t\t\tswitch b {\n\t\t\tcase ' ', '%', '[', ']', '<', '>', '(', ')', '\\r', '\\n', '\\t', '/':\n\t\t\t\tr.UnreadByte()\n\t\t\t\tbreak loop\n\t\t\tdefault:\n\t\t\t\tstr += string(b)\n\t\t\t}\n\t\t}\n\t\treturn str, nil\n\t}\n\n\treturn \"\", nil\n}\n\n// Read a value based on a token\nfunc (this *PdfReader) readValue(r *bufio.Reader, t string) (*PdfValue, error) {\n\tvar err error\n\tvar b byte\n\n\tresult := &PdfValue{}\n\tresult.Type = -1\n\tresult.Token = t\n\tresult.Dictionary = make(map[string]*PdfValue, 0)\n\tresult.Array = make([]*PdfValue, 0)\n\n\tswitch t {\n\tcase \"<\":\n\t\t// This is a hex string\n\n\t\t// Read bytes until '>' is found\n\t\tvar s string\n\t\tfor {\n\t\t\tb, err = r.ReadByte()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read byte\")\n\t\t\t}\n\t\t\tif b != '>' {\n\t\t\t\ts += string(b)\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tresult.Type = PDF_TYPE_HEX\n\t\tresult.String = s\n\n\tcase \"<<\":\n\t\t// This is a dictionary\n\n\t\t// Recurse into this function until we reach the end of the dictionary.\n\t\tfor {\n\t\t\tkey, err := this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\t\t\tif key == \"\" {\n\t\t\t\treturn nil, errors.New(\"Token is empty\")\n\t\t\t}\n\n\t\t\tif key == \">>\" {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// read next token\n\t\t\tnewKey, err := this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\n\t\t\tvalue, err := this.readValue(r, newKey)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read value for token: \"+newKey)\n\t\t\t}\n\n\t\t\tif value.Type == -1 {\n\t\t\t\treturn result, nil\n\t\t\t}\n\n\t\t\t// Catch missing value\n\t\t\tif value.Type == PDF_TYPE_TOKEN && value.String == \">>\" {\n\t\t\t\tresult.Type = PDF_TYPE_NULL\n\t\t\t\tresult.Dictionary[key] = value\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// Set value in dictionary\n\t\t\tresult.Dictionary[key] = value\n\t\t}\n\n\t\tresult.Type = PDF_TYPE_DICTIONARY\n\t\treturn result, nil\n\n\tcase \"[\":\n\t\t// This is an array\n\n\t\ttmpResult := make([]*PdfValue, 0)\n\n\t\t// Recurse into this function until we reach the end of the array\n\t\tfor {\n\t\t\tkey, err := this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\t\t\tif key == \"\" {\n\t\t\t\treturn nil, errors.New(\"Token is empty\")\n\t\t\t}\n\n\t\t\tif key == \"]\" {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tvalue, err := this.readValue(r, key)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read value for token: \"+key)\n\t\t\t}\n\n\t\t\tif value.Type == -1 {\n\t\t\t\treturn result, nil\n\t\t\t}\n\n\t\t\ttmpResult = append(tmpResult, value)\n\t\t}\n\n\t\tresult.Type = PDF_TYPE_ARRAY\n\t\tresult.Array = tmpResult\n\n\tcase \"(\":\n\t\t// This is a string\n\n\t\topenBrackets := 1\n\n\t\t// Create new buffer\n\t\tvar buf bytes.Buffer\n\n\t\t// Read bytes until brackets are balanced\n\t\tfor openBrackets > 0 {\n\t\t\tb, err := r.ReadByte()\n\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read byte\")\n\t\t\t}\n\n\t\t\tswitch b {\n\t\t\tcase '(':\n\t\t\t\topenBrackets++\n\n\t\t\tcase ')':\n\t\t\t\topenBrackets--\n\n\t\t\tcase '\\\\':\n\t\t\t\tnb, err := r.ReadByte()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read byte\")\n\t\t\t\t}\n\n\t\t\t\tbuf.WriteByte(b)\n\t\t\t\tbuf.WriteByte(nb)\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif openBrackets > 0 {\n\t\t\t\tbuf.WriteByte(b)\n\t\t\t}\n\t\t}\n\n\t\tresult.Type = PDF_TYPE_STRING\n\t\tresult.String = buf.String()\n\n\tcase \"stream\":\n\t\treturn nil, errors.New(\"Stream not implemented\")\n\n\tdefault:\n\t\tresult.Type = PDF_TYPE_TOKEN\n\t\tresult.Token = t\n\n\t\tif is_numeric(t) {\n\t\t\t// A numeric token.  Make sure that it is not part of something else\n\t\t\tt2, err := this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\t\t\tif t2 != \"\" {\n\t\t\t\tif is_numeric(t2) {\n\t\t\t\t\t// Two numeric tokens in a row.\n\t\t\t\t\t// In this case, we're probably in front of either an object reference\n\t\t\t\t\t// or an object specification.\n\t\t\t\t\t// Determine the case and return the data.\n\t\t\t\t\tt3, err := this.readToken(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t\t\t\t}\n\n\t\t\t\t\tif t3 != \"\" {\n\t\t\t\t\t\tswitch t3 {\n\t\t\t\t\t\tcase \"obj\":\n\t\t\t\t\t\t\tresult.Type = PDF_TYPE_OBJDEC\n\t\t\t\t\t\t\tresult.Id, _ = strconv.Atoi(t)\n\t\t\t\t\t\t\tresult.Gen, _ = strconv.Atoi(t2)\n\t\t\t\t\t\t\treturn result, nil\n\n\t\t\t\t\t\tcase \"R\":\n\t\t\t\t\t\t\tresult.Type = PDF_TYPE_OBJREF\n\t\t\t\t\t\t\tresult.Id, _ = strconv.Atoi(t)\n\t\t\t\t\t\t\tresult.Gen, _ = strconv.Atoi(t2)\n\t\t\t\t\t\t\treturn result, nil\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If we get to this point, that numeric value up there was just a numeric value.\n\t\t\t\t\t\t// Push the extra tokens back into the stack and return the value.\n\t\t\t\t\t\tthis.stack = append(this.stack, t3)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.stack = append(this.stack, t2)\n\t\t\t}\n\n\t\t\tif n, err := strconv.Atoi(t); err == nil {\n\t\t\t\tresult.Type = PDF_TYPE_NUMERIC\n\t\t\t\tresult.Int = n\n\t\t\t\tresult.Real = float64(n) // Also assign Real value here to fix page box parsing bugs\n\t\t\t} else {\n\t\t\t\tresult.Type = PDF_TYPE_REAL\n\t\t\t\tresult.Real, _ = strconv.ParseFloat(t, 64)\n\t\t\t}\n\t\t} else if t == \"true\" || t == \"false\" {\n\t\t\tresult.Type = PDF_TYPE_BOOLEAN\n\t\t\tresult.Bool = t == \"true\"\n\t\t} else if t == \"null\" {\n\t\t\tresult.Type = PDF_TYPE_NULL\n\t\t} else {\n\t\t\tresult.Type = PDF_TYPE_TOKEN\n\t\t\tresult.Token = t\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// Resolve a compressed object (PDF 1.5)\nfunc (this *PdfReader) resolveCompressedObject(objSpec *PdfValue) (*PdfValue, error) {\n\tvar err error\n\n\t// Make sure object reference exists in xrefStream\n\tif _, ok := this.xrefStream[objSpec.Id]; !ok {\n\t\treturn nil, errors.New(fmt.Sprintf(\"Could not find object ID %d in xref stream or xref table.\", objSpec.Id))\n\t}\n\n\t// Get object id and index\n\tobjectId := this.xrefStream[objSpec.Id][0]\n\tobjectIndex := this.xrefStream[objSpec.Id][1]\n\n\t// Read compressed object\n\tcompressedObjSpec := &PdfValue{Type: PDF_TYPE_OBJREF, Id: objectId, Gen: 0}\n\n\t// Resolve compressed object\n\tcompressedObj, err := this.resolveObject(compressedObjSpec)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to resolve compressed object\")\n\t}\n\n\t// Verify object type is /ObjStm\n\tif _, ok := compressedObj.Value.Dictionary[\"/Type\"]; ok {\n\t\tif compressedObj.Value.Dictionary[\"/Type\"].Token != \"/ObjStm\" {\n\t\t\treturn nil, errors.New(\"Expected compressed object type to be /ObjStm\")\n\t\t}\n\t} else {\n\t\treturn nil, errors.New(\"Could not determine compressed object type.\")\n\t}\n\n\t// Get number of sub-objects in compressed object\n\tn := compressedObj.Value.Dictionary[\"/N\"].Int\n\tif n <= 0 {\n\t\treturn nil, errors.New(\"No sub objects in compressed object\")\n\t}\n\n\t// Get offset of first object\n\tfirst := compressedObj.Value.Dictionary[\"/First\"].Int\n\n\t// Get length\n\t//length := compressedObj.Value.Dictionary[\"/Length\"].Int\n\n\t// Check for filter\n\tfilter := \"\"\n\tif _, ok := compressedObj.Value.Dictionary[\"/Filter\"]; ok {\n\t\tfilter = compressedObj.Value.Dictionary[\"/Filter\"].Token\n\t\tif filter != \"/FlateDecode\" {\n\t\t\treturn nil, errors.New(\"Unsupported filter - expected /FlateDecode, got: \" + filter)\n\t\t}\n\t}\n\n\tif filter == \"/FlateDecode\" {\n\t\t// Decompress if filter is /FlateDecode\n\t\t// Uncompress zlib compressed data\n\t\tvar out bytes.Buffer\n\t\tzlibReader, _ := zlib.NewReader(bytes.NewBuffer(compressedObj.Stream.Bytes))\n\t\tdefer zlibReader.Close()\n\t\tio.Copy(&out, zlibReader)\n\n\t\t// Set stream to uncompressed data\n\t\tcompressedObj.Stream.Bytes = out.Bytes()\n\t}\n\n\t// Get io.Reader for bytes\n\tr := bufio.NewReader(bytes.NewBuffer(compressedObj.Stream.Bytes))\n\n\tsubObjId := 0\n\tsubObjPos := 0\n\n\t// Read sub-object indeces and their positions within the (un)compressed object\n\tfor i := 0; i < n; i++ {\n\t\tvar token string\n\t\tvar _objidx int\n\t\tvar _objpos int\n\n\t\t// Read first token (object index)\n\t\ttoken, err = this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\t// Convert line (string) into int\n\t\t_objidx, err = strconv.Atoi(token)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to convert token into integer: \"+token)\n\t\t}\n\n\t\t// Read first token (object index)\n\t\ttoken, err = this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\t// Convert line (string) into int\n\t\t_objpos, err = strconv.Atoi(token)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to convert token into integer: \"+token)\n\t\t}\n\n\t\tif i == objectIndex {\n\t\t\tsubObjId = _objidx\n\t\t\tsubObjPos = _objpos\n\t\t}\n\t}\n\n\t// Now create an io.ReadSeeker\n\trs := io.ReadSeeker(bytes.NewReader(compressedObj.Stream.Bytes))\n\n\t// Determine where to seek to (sub-object position + /First)\n\tseekTo := int64(subObjPos + first)\n\n\t// Fast forward to the object\n\trs.Seek(seekTo, 0)\n\n\t// Create a new io.Reader\n\tr = bufio.NewReader(rs)\n\n\t// Read token\n\ttoken, err := this.readToken(r)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t}\n\n\t// Read object\n\tobj, err := this.readValue(r, token)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to read value for token: \"+token)\n\t}\n\n\tresult := &PdfValue{}\n\tresult.Id = subObjId\n\tresult.Gen = 0\n\tresult.Type = PDF_TYPE_OBJECT\n\tresult.Value = obj\n\n\treturn result, nil\n}\n\nfunc (this *PdfReader) resolveObject(objSpec *PdfValue) (*PdfValue, error) {\n\tvar err error\n\tvar old_pos int64\n\n\t// Create new bufio.Reader\n\tr := bufio.NewReader(this.f)\n\n\tif objSpec.Type == PDF_TYPE_OBJREF {\n\t\t// This is a reference, resolve it.\n\t\toffset := this.xref[objSpec.Id][objSpec.Gen]\n\n\t\tif _, ok := this.xref[objSpec.Id]; !ok {\n\t\t\t// This may be a compressed object\n\t\t\treturn this.resolveCompressedObject(objSpec)\n\t\t}\n\n\t\t// Save current file position\n\t\t// This is needed if you want to resolve reference while you're reading another object.\n\t\t// (e.g.: if you need to determine the length of a stream)\n\t\told_pos, err = this.f.Seek(0, os.SEEK_CUR)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to get current position of file\")\n\t\t}\n\n\t\t// Reposition the file pointer and load the object header\n\t\t_, err = this.f.Seek(int64(offset), 0)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to set position of file\")\n\t\t}\n\n\t\ttoken, err := this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\tobj, err := this.readValue(r, token)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to read value for token: \"+token)\n\t\t}\n\n\t\tif obj.Type != PDF_TYPE_OBJDEC {\n\t\t\treturn nil, errors.New(fmt.Sprintf(\"Expected type to be PDF_TYPE_OBJDEC, got: %d\", obj.Type))\n\t\t}\n\n\t\tif obj.Id != objSpec.Id {\n\t\t\treturn nil, errors.New(fmt.Sprintf(\"Object ID (%d) does not match ObjSpec ID (%d)\", obj.Id, objSpec.Id))\n\t\t}\n\n\t\tif obj.Gen != objSpec.Gen {\n\t\t\treturn nil, errors.New(\"Object Gen does not match ObjSpec Gen\")\n\t\t}\n\n\t\t// Read next token\n\t\ttoken, err = this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\t// Read actual object value\n\t\tvalue, err := this.readValue(r, token)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to read value for token: \"+token)\n\t\t}\n\n\t\t// Read next token\n\t\ttoken, err = this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\tresult := &PdfValue{}\n\t\tresult.Id = obj.Id\n\t\tresult.Gen = obj.Gen\n\t\tresult.Type = PDF_TYPE_OBJECT\n\t\tresult.Value = value\n\n\t\tif token == \"stream\" {\n\t\t\tresult.Type = PDF_TYPE_STREAM\n\n\t\t\terr = this.skipWhitespace(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to skip whitespace\")\n\t\t\t}\n\n\t\t\t// Get stream length dictionary\n\t\t\tlengthDict := value.Dictionary[\"/Length\"]\n\n\t\t\t// Get number of bytes of stream\n\t\t\tlength := lengthDict.Int\n\n\t\t\t// If lengthDict is an object reference, resolve the object and set length\n\t\t\tif lengthDict.Type == PDF_TYPE_OBJREF {\n\t\t\t\tlengthDict, err = this.resolveObject(lengthDict)\n\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, errors.Wrap(err, \"Failed to resolve length object of stream\")\n\t\t\t\t}\n\n\t\t\t\t// Set length to resolved object value\n\t\t\t\tlength = lengthDict.Value.Int\n\t\t\t}\n\n\t\t\t// Read length bytes\n\t\t\tbytes := make([]byte, length)\n\n\t\t\t// Cannot use reader.Read() because that may not read all the bytes\n\t\t\t_, err := io.ReadFull(r, bytes)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read bytes from buffer\")\n\t\t\t}\n\n\t\t\ttoken, err = this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\t\t\tif token != \"endstream\" {\n\t\t\t\treturn nil, errors.New(\"Expected next token to be: endstream, got: \" + token)\n\t\t\t}\n\n\t\t\ttoken, err = this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\n\t\t\tstreamObj := &PdfValue{}\n\t\t\tstreamObj.Type = PDF_TYPE_STREAM\n\t\t\tstreamObj.Bytes = bytes\n\n\t\t\tresult.Stream = streamObj\n\t\t}\n\n\t\tif token != \"endobj\" {\n\t\t\treturn nil, errors.New(\"Expected next token to be: endobj, got: \" + token)\n\t\t}\n\n\t\t// Reposition the file pointer to previous position\n\t\t_, err = this.f.Seek(old_pos, 0)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to set position of file\")\n\t\t}\n\n\t\treturn result, nil\n\n\t} else {\n\t\treturn objSpec, nil\n\t}\n\n\treturn &PdfValue{}, nil\n}\n\n// Find the xref offset (should be at the end of the PDF)\nfunc (this *PdfReader) findXref() error {\n\tvar result int\n\tvar err error\n\tvar toRead int64\n\n\ttoRead = 1500\n\n\t// If PDF is smaller than 1500 bytes, be sure to only read the number of bytes that are in the file\n\tfileSize := this.nBytes\n\tif fileSize < toRead {\n\t\ttoRead = fileSize\n\t}\n\n\t// 0 means relative to the origin of the file,\n\t// 1 means relative to the current offset,\n\t// and 2 means relative to the end.\n\twhence := 2\n\n\t// Perform seek operation\n\t_, err = this.f.Seek(-toRead, whence)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to set position of file\")\n\t}\n\n\t// Create new bufio.Reader\n\tr := bufio.NewReader(this.f)\n\tfor {\n\t\t// Read all tokens until \"startxref\" is found\n\t\ttoken, err := this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\tif token == \"startxref\" {\n\t\t\ttoken, err = this.readToken(r)\n\t\t\t// Probably EOF before finding startxref\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to find startxref token\")\n\t\t\t}\n\n\t\t\t// Convert line (string) into int\n\t\t\tresult, err = strconv.Atoi(token)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to convert xref position into integer: \"+token)\n\t\t\t}\n\n\t\t\t// Successfully read the xref position\n\t\t\tthis.xrefPos = result\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Rewind file pointer\n\twhence = 0\n\t_, err = this.f.Seek(0, whence)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to set position of file\")\n\t}\n\n\tthis.xrefPos = result\n\n\treturn nil\n}\n\n// Read and parse the xref table\nfunc (this *PdfReader) readXref() error {\n\tvar err error\n\n\t// Create new bufio.Reader\n\tr := bufio.NewReader(this.f)\n\n\t// Set file pointer to xref start\n\t_, err = this.f.Seek(int64(this.xrefPos), 0)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to set position of file\")\n\t}\n\n\t// Xref should start with 'xref'\n\tt, err := this.readToken(r)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t}\n\tif t != \"xref\" {\n\t\t// Maybe this is an XRef stream ...\n\t\tv, err := this.readValue(r, t)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to read XRef stream\")\n\t\t}\n\n\t\tif v.Type == PDF_TYPE_OBJDEC {\n\t\t\t// Read next token\n\t\t\tt, err = this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\n\t\t\t// Read actual object value\n\t\t\tv, err := this.readValue(r, t)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to read value for token: \"+t)\n\t\t\t}\n\n\t\t\t// If /Type is set, check to see if it is XRef\n\t\t\tif _, ok := v.Dictionary[\"/Type\"]; ok {\n\t\t\t\tif v.Dictionary[\"/Type\"].Token == \"/XRef\" {\n\t\t\t\t\t// Continue reading xref stream data now that it is confirmed that it is an xref stream\n\n\t\t\t\t\t// Check for /DecodeParms\n\t\t\t\t\tpaethDecode := false\n\t\t\t\t\tif _, ok := v.Dictionary[\"/DecodeParms\"]; ok {\n\t\t\t\t\t\tcolumns := 0\n\t\t\t\t\t\tpredictor := 0\n\n\t\t\t\t\t\tif _, ok2 := v.Dictionary[\"/DecodeParms\"].Dictionary[\"/Columns\"]; ok2 {\n\t\t\t\t\t\t\tcolumns = v.Dictionary[\"/DecodeParms\"].Dictionary[\"/Columns\"].Int\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif _, ok2 := v.Dictionary[\"/DecodeParms\"].Dictionary[\"/Predictor\"]; ok2 {\n\t\t\t\t\t\t\tpredictor = v.Dictionary[\"/DecodeParms\"].Dictionary[\"/Predictor\"].Int\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif columns != 4 || predictor != 12 {\n\t\t\t\t\t\t\treturn errors.New(\"Unsupported /DecodeParms - only tested with /Columns 4 /Predictor 12\")\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpaethDecode = true\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check to make sure field size is [1 2 1] - not yet tested with other field sizes\n\t\t\t\t\tif v.Dictionary[\"/W\"].Array[0].Int != 1 || v.Dictionary[\"/W\"].Array[1].Int > 4 || v.Dictionary[\"/W\"].Array[2].Int != 1 {\n\t\t\t\t\t\treturn errors.New(fmt.Sprintf(\"Unsupported field sizes in cross-reference stream dictionary: /W [%d %d %d]\",\n\t\t\t\t\t\t\tv.Dictionary[\"/W\"].Array[0].Int,\n\t\t\t\t\t\t\tv.Dictionary[\"/W\"].Array[1].Int,\n\t\t\t\t\t\t\tv.Dictionary[\"/W\"].Array[2].Int))\n\t\t\t\t\t}\n\n\t\t\t\t\tindex := make([]int, 2)\n\n\t\t\t\t\t// If /Index is not set, this is an error\n\t\t\t\t\tif _, ok := v.Dictionary[\"/Index\"]; ok {\n\t\t\t\t\t\tif len(v.Dictionary[\"/Index\"].Array) < 2 {\n\t\t\t\t\t\t\treturn errors.Wrap(err, \"Index array does not contain 2 elements\")\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tindex[0] = v.Dictionary[\"/Index\"].Array[0].Int\n\t\t\t\t\t\tindex[1] = v.Dictionary[\"/Index\"].Array[1].Int\n\t\t\t\t\t} else {\n\t\t\t\t\t\tindex[0] = 0\n\t\t\t\t\t}\n\n\t\t\t\t\tprevXref := 0\n\n\t\t\t\t\t// Check for previous xref stream\n\t\t\t\t\tif _, ok := v.Dictionary[\"/Prev\"]; ok {\n\t\t\t\t\t\tprevXref = v.Dictionary[\"/Prev\"].Int\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set root object\n\t\t\t\t\tif _, ok := v.Dictionary[\"/Root\"]; ok {\n\t\t\t\t\t\t// Just set the whole dictionary with /Root key to keep compatibiltiy with existing code\n\t\t\t\t\t\tthis.trailer = v\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Don't return an error here.  The trailer could be in another XRef stream.\n\t\t\t\t\t\t//return errors.New(\"Did not set root object\")\n\t\t\t\t\t}\n\n\t\t\t\t\tstartObject := index[0]\n\n\t\t\t\t\terr = this.skipWhitespace(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"Failed to skip whitespace\")\n\t\t\t\t\t}\n\n\t\t\t\t\t// Get stream length dictionary\n\t\t\t\t\tlengthDict := v.Dictionary[\"/Length\"]\n\n\t\t\t\t\t// Get number of bytes of stream\n\t\t\t\t\tlength := lengthDict.Int\n\n\t\t\t\t\t// If lengthDict is an object reference, resolve the object and set length\n\t\t\t\t\tif lengthDict.Type == PDF_TYPE_OBJREF {\n\t\t\t\t\t\tlengthDict, err = this.resolveObject(lengthDict)\n\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn errors.Wrap(err, \"Failed to resolve length object of stream\")\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Set length to resolved object value\n\t\t\t\t\t\tlength = lengthDict.Value.Int\n\t\t\t\t\t}\n\n\t\t\t\t\tt, err = this.readToken(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t\t\t\t}\n\t\t\t\t\tif t != \"stream\" {\n\t\t\t\t\t\treturn errors.New(\"Expected next token to be: stream, got: \" + t)\n\t\t\t\t\t}\n\n\t\t\t\t\terr = this.skipWhitespace(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"Failed to skip whitespace\")\n\t\t\t\t\t}\n\n\t\t\t\t\t// Read length bytes\n\t\t\t\t\tdata := make([]byte, length)\n\n\t\t\t\t\t// Cannot use reader.Read() because that may not read all the bytes\n\t\t\t\t\t_, err := io.ReadFull(r, data)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"Failed to read bytes from buffer\")\n\t\t\t\t\t}\n\n\t\t\t\t\t// Look for endstream token\n\t\t\t\t\tt, err = this.readToken(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t\t\t\t}\n\t\t\t\t\tif t != \"endstream\" {\n\t\t\t\t\t\treturn errors.New(\"Expected next token to be: endstream, got: \" + t)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Look for endobj token\n\t\t\t\t\tt, err = this.readToken(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t\t\t\t}\n\t\t\t\t\tif t != \"endobj\" {\n\t\t\t\t\t\treturn errors.New(\"Expected next token to be: endobj, got: \" + t)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Now decode zlib data\n\t\t\t\t\tb := bytes.NewReader(data)\n\n\t\t\t\t\tz, err := zlib.NewReader(b)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"zlib.NewReader error\")\n\t\t\t\t\t}\n\t\t\t\t\tdefer z.Close()\n\n\t\t\t\t\tp, err := ioutil.ReadAll(z)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"ioutil.ReadAll error\")\n\t\t\t\t\t}\n\n\t\t\t\t\tobjPos := 0\n\t\t\t\t\tobjGen := 0\n\t\t\t\t\ti := startObject\n\n\t\t\t\t\t// Decode result with paeth algorithm\n\t\t\t\t\tvar result []byte\n\t\t\t\t\tb = bytes.NewReader(p)\n\n\t\t\t\t\tfirstFieldSize := v.Dictionary[\"/W\"].Array[0].Int\n\t\t\t\t\tmiddleFieldSize := v.Dictionary[\"/W\"].Array[1].Int\n\t\t\t\t\tlastFieldSize := v.Dictionary[\"/W\"].Array[2].Int\n\n\t\t\t\t\tfieldSize := firstFieldSize + middleFieldSize + lastFieldSize\n\t\t\t\t\tif paethDecode {\n\t\t\t\t\t\tfieldSize++\n\t\t\t\t\t}\n\n\t\t\t\t\tprevRow := make([]byte, fieldSize)\n\t\t\t\t\tfor {\n\t\t\t\t\t\tresult = make([]byte, fieldSize)\n\t\t\t\t\t\t_, err := io.ReadFull(b, result)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tif err == io.EOF {\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn errors.Wrap(err, \"io.ReadFull error\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif paethDecode {\n\t\t\t\t\t\t\tfilterPaeth(result, prevRow, fieldSize)\n\t\t\t\t\t\t\tcopy(prevRow, result)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tobjectData := make([]byte, fieldSize)\n\t\t\t\t\t\tif paethDecode {\n\t\t\t\t\t\t\tcopy(objectData, result[1:fieldSize])\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcopy(objectData, result[0:fieldSize])\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif objectData[0] == 1 {\n\t\t\t\t\t\t\t// Regular objects\n\t\t\t\t\t\t\tb := make([]byte, 4)\n\t\t\t\t\t\t\tcopy(b[4-middleFieldSize:], objectData[1:1+middleFieldSize])\n\n\t\t\t\t\t\t\tobjPos = int(binary.BigEndian.Uint32(b))\n\t\t\t\t\t\t\tobjGen = int(objectData[firstFieldSize+middleFieldSize])\n\n\t\t\t\t\t\t\t// Append map[int]int\n\t\t\t\t\t\t\tthis.xref[i] = make(map[int]int, 1)\n\n\t\t\t\t\t\t\t// Set object id, generation, and position\n\t\t\t\t\t\t\tthis.xref[i][objGen] = objPos\n\t\t\t\t\t\t} else if objectData[0] == 2 {\n\t\t\t\t\t\t\t// Compressed objects\n\t\t\t\t\t\t\tb := make([]byte, 4)\n\t\t\t\t\t\t\tcopy(b[4-middleFieldSize:], objectData[1:1+middleFieldSize])\n\n\t\t\t\t\t\t\tobjId := int(binary.BigEndian.Uint32(b))\n\t\t\t\t\t\t\tobjIdx := int(objectData[firstFieldSize+middleFieldSize])\n\n\t\t\t\t\t\t\t// object id (i) is located in StmObj (objId) at index (objIdx)\n\t\t\t\t\t\t\tthis.xrefStream[i] = [2]int{objId, objIdx}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti++\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for previous xref stream\n\t\t\t\t\tif prevXref > 0 {\n\t\t\t\t\t\t// Set xrefPos to /Prev xref\n\t\t\t\t\t\tthis.xrefPos = prevXref\n\n\t\t\t\t\t\t// Read preivous xref\n\t\t\t\t\t\txrefErr := this.readXref()\n\t\t\t\t\t\tif xrefErr != nil {\n\t\t\t\t\t\t\treturn errors.Wrap(xrefErr, \"Failed to read prev xref\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t}\n\n\t\treturn errors.New(\"Expected xref to start with 'xref'.  Got: \" + t)\n\t}\n\n\tfor {\n\t\t// Next value will be the starting object id (usually 0, but not always) or the trailer\n\t\tt, err = this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\t// Check for trailer\n\t\tif t == \"trailer\" {\n\t\t\tbreak\n\t\t}\n\n\t\t// Convert token to int\n\t\tstartObject, err := strconv.Atoi(t)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to convert start object to integer: \"+t)\n\t\t}\n\n\t\t// Determine how many objects there are\n\t\tt, err = this.readToken(r)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t}\n\n\t\t// Convert token to int\n\t\tnumObject, err := strconv.Atoi(t)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to convert num object to integer: \"+t)\n\t\t}\n\n\t\t// For all objects in xref, read object position, object generation, and status (free or new)\n\t\tfor i := startObject; i < startObject+numObject; i++ {\n\t\t\tt, err = this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\n\t\t\t// Get object position as int\n\t\t\tobjPos, err := strconv.Atoi(t)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to convert object position to integer: \"+t)\n\t\t\t}\n\n\t\t\tt, err = this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\n\t\t\t// Get object generation as int\n\t\t\tobjGen, err := strconv.Atoi(t)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to convert object generation to integer: \"+t)\n\t\t\t}\n\n\t\t\t// Get object status (free or new)\n\t\t\tobjStatus, err := this.readToken(r)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t\t\t}\n\t\t\tif objStatus != \"f\" && objStatus != \"n\" {\n\t\t\t\treturn errors.New(\"Expected objStatus to be 'n' or 'f', got: \" + objStatus)\n\t\t\t}\n\n\t\t\t// Append map[int]int\n\t\t\tthis.xref[i] = make(map[int]int, 1)\n\n\t\t\t// Set object id, generation, and position\n\t\t\tthis.xref[i][objGen] = objPos\n\t\t}\n\t}\n\n\t// Read trailer dictionary\n\tt, err = this.readToken(r)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to read token\")\n\t}\n\n\ttrailer, err := this.readValue(r, t)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to read value for token: \"+t)\n\t}\n\n\t// If /Root is set, then set trailer object so that /Root can be read later\n\tif _, ok := trailer.Dictionary[\"/Root\"]; ok {\n\t\tthis.trailer = trailer\n\t}\n\n\t// If a /Prev xref trailer is specified, parse that\n\tif tr, ok := trailer.Dictionary[\"/Prev\"]; ok {\n\t\t// Resolve parent xref table\n\t\tthis.xrefPos = tr.Int\n\t\treturn this.readXref()\n\t}\n\n\treturn nil\n}\n\n// Read root (catalog object)\nfunc (this *PdfReader) readRoot() error {\n\tvar err error\n\n\trootObjSpec := this.trailer.Dictionary[\"/Root\"]\n\n\t// Read root (catalog)\n\tthis.catalog, err = this.resolveObject(rootObjSpec)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to resolve root object\")\n\t}\n\n\treturn nil\n}\n\n// Read all pages in PDF\nfunc (this *PdfReader) readPages() error {\n\tvar err error\n\n\t// resolve_pages_dict\n\tpagesDict, err := this.resolveObject(this.catalog.Value.Dictionary[\"/Pages\"])\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to resolve pages object\")\n\t}\n\n\t// This will normally return itself\n\tkids, err := this.resolveObject(pagesDict.Value.Dictionary[\"/Kids\"])\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to resolve kids object\")\n\t}\n\n\t// Allocate pages\n\tthis.pages = make([]*PdfValue, len(kids.Array))\n\n\t// Loop through pages and add to result\n\tfor i := 0; i < len(kids.Array); i++ {\n\t\tpage, err := this.resolveObject(kids.Array[i])\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"Failed to resolve kid object\")\n\t\t}\n\n\t\t// Set page\n\t\tthis.pages[i] = page\n\t}\n\n\treturn nil\n}\n\n// Get references to page resources for a given page number\nfunc (this *PdfReader) getPageResources(pageno int) (*PdfValue, error) {\n\tvar err error\n\n\t// Check to make sure page exists in pages slice\n\tif len(this.pages) < pageno {\n\t\treturn nil, errors.New(fmt.Sprintf(\"Page %d does not exist!!\", pageno))\n\t}\n\n\t// Resolve page object\n\tpage, err := this.resolveObject(this.pages[pageno-1])\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Failed to resolve page object\")\n\t}\n\n\t// Check to see if /Resources exists in Dictionary\n\tif _, ok := page.Value.Dictionary[\"/Resources\"]; ok {\n\t\t// Resolve /Resources object\n\t\tres, err := this.resolveObject(page.Value.Dictionary[\"/Resources\"])\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to resolve resources object\")\n\t\t}\n\n\t\t// If type is PDF_TYPE_OBJECT, return its Value\n\t\tif res.Type == PDF_TYPE_OBJECT {\n\t\t\treturn res.Value, nil\n\t\t}\n\n\t\t// Otherwise, returned the resolved object\n\t\treturn res, nil\n\t} else {\n\t\t// If /Resources does not exist, check to see if /Parent exists and return that\n\t\tif _, ok := page.Value.Dictionary[\"/Parent\"]; ok {\n\t\t\t// Resolve parent object\n\t\t\tres, err := this.resolveObject(page.Value.Dictionary[\"/Parent\"])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to resolve parent object\")\n\t\t\t}\n\n\t\t\t// If /Parent object type is PDF_TYPE_OBJECT, return its Value\n\t\t\tif res.Type == PDF_TYPE_OBJECT {\n\t\t\t\treturn res.Value, nil\n\t\t\t}\n\n\t\t\t// Otherwise, return the resolved parent object\n\t\t\treturn res, nil\n\t\t}\n\t}\n\n\t// Return an empty PdfValue if we got here\n\t// TODO:  Improve error handling\n\treturn &PdfValue{}, nil\n}\n\n// Get page content and return a slice of PdfValue objects\nfunc (this *PdfReader) getPageContent(objSpec *PdfValue) ([]*PdfValue, error) {\n\tvar err error\n\tvar content *PdfValue\n\n\t// Allocate slice\n\tcontents := make([]*PdfValue, 0)\n\n\tif objSpec.Type == PDF_TYPE_OBJREF {\n\t\t// If objSpec is an object reference, resolve the object and append it to contents\n\t\tcontent, err = this.resolveObject(objSpec)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to resolve object\")\n\t\t}\n\t\tcontents = append(contents, content)\n\t} else if objSpec.Type == PDF_TYPE_ARRAY {\n\t\t// If objSpec is an array, loop through the array and recursively get page content and append to contents\n\t\tfor i := 0; i < len(objSpec.Array); i++ {\n\t\t\ttmpContents, err := this.getPageContent(objSpec.Array[i])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to get page content\")\n\t\t\t}\n\t\t\tfor j := 0; j < len(tmpContents); j++ {\n\t\t\t\tcontents = append(contents, tmpContents[j])\n\t\t\t}\n\t\t}\n\t}\n\n\treturn contents, nil\n}\n\n// Get content (i.e. PDF drawing instructions)\nfunc (this *PdfReader) getContent(pageno int) (string, error) {\n\tvar err error\n\tvar contents []*PdfValue\n\n\t// Check to make sure page exists in pages slice\n\tif len(this.pages) < pageno {\n\t\treturn \"\", errors.New(fmt.Sprintf(\"Page %d does not exist.\", pageno))\n\t}\n\n\t// Get page\n\tpage := this.pages[pageno-1]\n\n\t// FIXME: This could be slow, converting []byte to string and appending many times\n\tbuffer := \"\"\n\n\t// Check to make sure /Contents exists in page dictionary\n\tif _, ok := page.Value.Dictionary[\"/Contents\"]; ok {\n\t\t// Get an array of page content\n\t\tcontents, err = this.getPageContent(page.Value.Dictionary[\"/Contents\"])\n\t\tif err != nil {\n\t\t\treturn \"\", errors.Wrap(err, \"Failed to get page content\")\n\t\t}\n\n\t\tfor i := 0; i < len(contents); i++ {\n\t\t\t// Decode content if one or more /Filter is specified.\n\t\t\t// Most common filter is FlateDecode which can be uncompressed with zlib\n\t\t\ttmpBuffer, err := this.rebuildContentStream(contents[i])\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", errors.Wrap(err, \"Failed to rebuild content stream\")\n\t\t\t}\n\n\t\t\t// FIXME:  This is probably slow\n\t\t\tbuffer += string(tmpBuffer)\n\t\t}\n\t}\n\n\treturn buffer, nil\n}\n\n// Rebuild content stream\n// This will decode content if one or more /Filter (such as FlateDecode) is specified.\n// If there are multiple filters, they will be decoded in the order in which they were specified.\nfunc (this *PdfReader) rebuildContentStream(content *PdfValue) ([]byte, error) {\n\tvar err error\n\tvar tmpFilter *PdfValue\n\n\t// Allocate slice of PdfValue\n\tfilters := make([]*PdfValue, 0)\n\n\t// If content has a /Filter, append it to filters slice\n\tif _, ok := content.Value.Dictionary[\"/Filter\"]; ok {\n\t\tfilter := content.Value.Dictionary[\"/Filter\"]\n\n\t\t// If filter type is a reference, resolve it\n\t\tif filter.Type == PDF_TYPE_OBJREF {\n\t\t\ttmpFilter, err = this.resolveObject(filter)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to resolve object\")\n\t\t\t}\n\t\t\tfilter = tmpFilter.Value\n\t\t}\n\n\t\tif filter.Type == PDF_TYPE_TOKEN {\n\t\t\t// If filter type is a token (e.g. FlateDecode), appent it to filters slice\n\t\t\tfilters = append(filters, filter)\n\t\t} else if filter.Type == PDF_TYPE_ARRAY {\n\t\t\t// If filter type is an array, then there are multiple filters.  Set filters variable to array value.\n\t\t\tfilters = filter.Array\n\t\t}\n\n\t}\n\n\t// Set stream variable to content bytes\n\tstream := content.Stream.Bytes\n\n\t// Loop through filters and apply each filter to stream\n\tfor i := 0; i < len(filters); i++ {\n\t\tswitch filters[i].Token {\n\t\tcase \"/FlateDecode\":\n\t\t\t// Uncompress zlib compressed data\n\t\t\tvar out bytes.Buffer\n\t\t\tzlibReader, _ := zlib.NewReader(bytes.NewBuffer(stream))\n\t\t\tdefer zlibReader.Close()\n\t\t\tio.Copy(&out, zlibReader)\n\n\t\t\t// Set stream to uncompressed data\n\t\t\tstream = out.Bytes()\n\t\tdefault:\n\t\t\treturn nil, errors.New(\"Unspported filter: \" + filters[i].Token)\n\t\t}\n\t}\n\n\treturn stream, nil\n}\n\nfunc (this *PdfReader) getAllPageBoxes(k float64) (map[int]map[string]map[string]float64, error) {\n\tvar err error\n\n\t// Allocate result with the number of available boxes\n\tresult := make(map[int]map[string]map[string]float64, len(this.pages))\n\n\tfor i := 1; i <= len(this.pages); i++ {\n\t\tresult[i], err = this.getPageBoxes(i, k)\n\t\tif result[i] == nil {\n\t\t\treturn nil, errors.Wrap(err, \"Unable to get page box\")\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// Get all page box data\nfunc (this *PdfReader) getPageBoxes(pageno int, k float64) (map[string]map[string]float64, error) {\n\tvar err error\n\n\t// Allocate result with the number of available boxes\n\tresult := make(map[string]map[string]float64, len(this.availableBoxes))\n\n\t// Check to make sure page exists in pages slice\n\tif len(this.pages) < pageno {\n\t\treturn nil, errors.New(fmt.Sprintf(\"Page %d does not exist?\", pageno))\n\t}\n\n\t// Resolve page object\n\tpage, err := this.resolveObject(this.pages[pageno-1])\n\tif err != nil {\n\t\treturn nil, errors.New(\"Failed to resolve page object\")\n\t}\n\n\t// Loop through available boxes and add to result\n\tfor i := 0; i < len(this.availableBoxes); i++ {\n\t\tbox, err := this.getPageBox(page, this.availableBoxes[i], k)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Failed to get page box\")\n\t\t}\n\n\t\tresult[this.availableBoxes[i]] = box\n\t}\n\n\treturn result, nil\n}\n\n// Get a specific page box value (e.g. MediaBox) and return its values\nfunc (this *PdfReader) getPageBox(page *PdfValue, box_index string, k float64) (map[string]float64, error) {\n\tvar err error\n\tvar tmpBox *PdfValue\n\n\t// Allocate 8 fields in result\n\tresult := make(map[string]float64, 8)\n\n\t// Check to make sure box_index (e.g. MediaBox) exists in page dictionary\n\tif _, ok := page.Value.Dictionary[box_index]; ok {\n\t\tbox := page.Value.Dictionary[box_index]\n\n\t\t// If the box type is a reference, resolve it\n\t\tif box.Type == PDF_TYPE_OBJREF {\n\t\t\ttmpBox, err = this.resolveObject(box)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.New(\"Failed to resolve object\")\n\t\t\t}\n\t\t\tbox = tmpBox.Value\n\t\t}\n\n\t\tif box.Type == PDF_TYPE_ARRAY {\n\t\t\t// If the box type is an array, calculate scaled value based on k\n\t\t\tresult[\"x\"] = box.Array[0].Real / k\n\t\t\tresult[\"y\"] = box.Array[1].Real / k\n\t\t\tresult[\"w\"] = math.Abs(box.Array[0].Real-box.Array[2].Real) / k\n\t\t\tresult[\"h\"] = math.Abs(box.Array[1].Real-box.Array[3].Real) / k\n\t\t\tresult[\"llx\"] = math.Min(box.Array[0].Real, box.Array[2].Real)\n\t\t\tresult[\"lly\"] = math.Min(box.Array[1].Real, box.Array[3].Real)\n\t\t\tresult[\"urx\"] = math.Max(box.Array[0].Real, box.Array[2].Real)\n\t\t\tresult[\"ury\"] = math.Max(box.Array[1].Real, box.Array[3].Real)\n\t\t} else {\n\t\t\t// TODO: Improve error handling\n\t\t\treturn nil, errors.New(\"Could not get page box\")\n\t\t}\n\t} else if _, ok := page.Value.Dictionary[\"/Parent\"]; ok {\n\t\tparentObj, err := this.resolveObject(page.Value.Dictionary[\"/Parent\"])\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Could not resolve parent object\")\n\t\t}\n\n\t\t// If the page box is inherited from /Parent, recursively return page box of parent\n\t\treturn this.getPageBox(parentObj, box_index, k)\n\t}\n\n\treturn result, nil\n}\n\n// Get page rotation for a page number\nfunc (this *PdfReader) getPageRotation(pageno int) (*PdfValue, error) {\n\t// Check to make sure page exists in pages slice\n\tif len(this.pages) < pageno {\n\t\treturn nil, errors.New(fmt.Sprintf(\"Page %d does not exist!!!!\", pageno))\n\t}\n\n\treturn this._getPageRotation(this.pages[pageno-1])\n}\n\n// Get page rotation for a page object spec\nfunc (this *PdfReader) _getPageRotation(page *PdfValue) (*PdfValue, error) {\n\tvar err error\n\n\t// Resolve page object\n\tpage, err = this.resolveObject(page)\n\tif err != nil {\n\t\treturn nil, errors.New(\"Failed to resolve page object\")\n\t}\n\n\t// Check to make sure /Rotate exists in page dictionary\n\tif _, ok := page.Value.Dictionary[\"/Rotate\"]; ok {\n\t\tres, err := this.resolveObject(page.Value.Dictionary[\"/Rotate\"])\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Failed to resolve rotate object\")\n\t\t}\n\n\t\t// If the type is PDF_TYPE_OBJECT, return its value\n\t\tif res.Type == PDF_TYPE_OBJECT {\n\t\t\treturn res.Value, nil\n\t\t}\n\n\t\t// Otherwise, return the object\n\t\treturn res, nil\n\t} else {\n\t\t// Check to see if parent has a rotation\n\t\tif _, ok := page.Value.Dictionary[\"/Parent\"]; ok {\n\t\t\t// Recursively return /Parent page rotation\n\t\t\tres, err := this._getPageRotation(page.Value.Dictionary[\"/Parent\"])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"Failed to get page rotation for parent\")\n\t\t\t}\n\n\t\t\t// If the type is PDF_TYPE_OBJECT, return its value\n\t\t\tif res.Type == PDF_TYPE_OBJECT {\n\t\t\t\treturn res.Value, nil\n\t\t\t}\n\n\t\t\t// Otherwise, return the object\n\t\t\treturn res, nil\n\t\t}\n\t}\n\n\treturn &PdfValue{Int: 0}, nil\n}\n\nfunc (this *PdfReader) read() error {\n\tvar err error\n\n\t// Find xref position\n\terr = this.findXref()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to find xref position\")\n\t}\n\n\t// Parse xref table\n\terr = this.readXref()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to read xref table\")\n\t}\n\n\t// Read catalog\n\terr = this.readRoot()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to read root\")\n\t}\n\n\t// Read pages\n\terr = this.readPages()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to to read pages\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/phpdave11/gofpdi/writer.go",
    "content": "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/errors\"\n\t\"math\"\n\t\"os\"\n)\n\ntype PdfWriter struct {\n\tf       *os.File\n\tw       *bufio.Writer\n\tr       *PdfReader\n\tk       float64\n\ttpls    []*PdfTemplate\n\tm       int\n\tn       int\n\toffsets map[int]int\n\toffset  int\n\tresult  map[int]string\n\t// Keep track of which objects have already been written\n\tobj_stack       map[int]*PdfValue\n\tdon_obj_stack   map[int]*PdfValue\n\twritten_objs    map[*PdfObjectId][]byte\n\twritten_obj_pos map[*PdfObjectId]map[int]string\n\tcurrent_obj     *PdfObject\n\tcurrent_obj_id  int\n\ttpl_id_offset   int\n\tuse_hash        bool\n}\n\ntype PdfObjectId struct {\n\tid   int\n\thash string\n}\n\ntype PdfObject struct {\n\tid     *PdfObjectId\n\tbuffer *bytes.Buffer\n}\n\nfunc (this *PdfWriter) SetTplIdOffset(n int) {\n\tthis.tpl_id_offset = n\n}\n\nfunc (this *PdfWriter) Init() {\n\tthis.k = 1\n\tthis.obj_stack = make(map[int]*PdfValue, 0)\n\tthis.don_obj_stack = make(map[int]*PdfValue, 0)\n\tthis.tpls = make([]*PdfTemplate, 0)\n\tthis.written_objs = make(map[*PdfObjectId][]byte, 0)\n\tthis.written_obj_pos = make(map[*PdfObjectId]map[int]string, 0)\n\tthis.current_obj = new(PdfObject)\n}\n\nfunc (this *PdfWriter) SetUseHash(b bool) {\n\tthis.use_hash = b\n}\n\nfunc (this *PdfWriter) SetNextObjectID(id int) {\n\tthis.n = id - 1\n}\n\nfunc NewPdfWriter(filename string) (*PdfWriter, error) {\n\twriter := &PdfWriter{}\n\twriter.Init()\n\n\tif filename != \"\" {\n\t\tvar err error\n\t\tf, err := os.Create(filename)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Unable to create filename: \"+filename)\n\t\t}\n\t\twriter.f = f\n\t\twriter.w = bufio.NewWriter(f)\n\t}\n\treturn writer, nil\n}\n\n// Done with parsing.  Now, create templates.\ntype PdfTemplate struct {\n\tId        int\n\tReader    *PdfReader\n\tResources *PdfValue\n\tBuffer    string\n\tBox       map[string]float64\n\tBoxes     map[string]map[string]float64\n\tX         float64\n\tY         float64\n\tW         float64\n\tH         float64\n\tRotation  int\n\tN         int\n}\n\nfunc (this *PdfWriter) GetImportedObjects() map[*PdfObjectId][]byte {\n\treturn this.written_objs\n}\n\n// For each object (uniquely identified by a sha1 hash), return the positions\n// of each hash within the object, to be replaced with pdf object ids (integers)\nfunc (this *PdfWriter) GetImportedObjHashPos() map[*PdfObjectId]map[int]string {\n\treturn this.written_obj_pos\n}\n\nfunc (this *PdfWriter) ClearImportedObjects() {\n\tthis.written_objs = make(map[*PdfObjectId][]byte, 0)\n}\n\n// Create a PdfTemplate object from a page number (e.g. 1) and a boxName (e.g. MediaBox)\nfunc (this *PdfWriter) ImportPage(reader *PdfReader, pageno int, boxName string) (int, error) {\n\tvar err error\n\n\t// Set default scale to 1\n\tthis.k = 1\n\n\t// Get all page boxes\n\tpageBoxes, err := reader.getPageBoxes(1, this.k)\n\tif err != nil {\n\t\treturn -1, errors.Wrap(err, \"Failed to get page boxes\")\n\t}\n\n\t// If requested box name does not exist for this page, use an alternate box\n\tif _, ok := pageBoxes[boxName]; !ok {\n\t\tif boxName == \"/BleedBox\" || boxName == \"/TrimBox\" || boxName == \"ArtBox\" {\n\t\t\tboxName = \"/CropBox\"\n\t\t} else if boxName == \"/CropBox\" {\n\t\t\tboxName = \"/MediaBox\"\n\t\t}\n\t}\n\n\t// If the requested box name or an alternate box name cannot be found, trigger an error\n\t// TODO: Improve error handling\n\tif _, ok := pageBoxes[boxName]; !ok {\n\t\treturn -1, errors.New(\"Box not found: \" + boxName)\n\t}\n\n\tpageResources, err := reader.getPageResources(pageno)\n\tif err != nil {\n\t\treturn -1, errors.Wrap(err, \"Failed to get page resources\")\n\t}\n\n\tcontent, err := reader.getContent(pageno)\n\tif err != nil {\n\t\treturn -1, errors.Wrap(err, \"Failed to get content\")\n\t}\n\n\t// Set template values\n\ttpl := &PdfTemplate{}\n\ttpl.Reader = reader\n\ttpl.Resources = pageResources\n\ttpl.Buffer = content\n\ttpl.Box = pageBoxes[boxName]\n\ttpl.Boxes = pageBoxes\n\ttpl.X = 0\n\ttpl.Y = 0\n\ttpl.W = tpl.Box[\"w\"]\n\ttpl.H = tpl.Box[\"h\"]\n\n\t// Set template rotation\n\trotation, err := reader.getPageRotation(pageno)\n\tif err != nil {\n\t\treturn -1, errors.Wrap(err, \"Failed to get page rotation\")\n\t}\n\tangle := rotation.Int % 360\n\n\t// Normalize angle\n\tif angle != 0 {\n\t\tsteps := angle / 90\n\t\tw := tpl.W\n\t\th := tpl.H\n\n\t\tif steps%2 == 0 {\n\t\t\ttpl.W = w\n\t\t\ttpl.H = h\n\t\t} else {\n\t\t\ttpl.W = h\n\t\t\ttpl.H = w\n\t\t}\n\n\t\tif angle < 0 {\n\t\t\tangle += 360\n\t\t}\n\n\t\ttpl.Rotation = angle * -1\n\t}\n\n\tthis.tpls = append(this.tpls, tpl)\n\n\t// Return last template id\n\treturn len(this.tpls) - 1, nil\n}\n\n// Create a new object and keep track of the offset for the xref table\nfunc (this *PdfWriter) newObj(objId int, onlyNewObj bool) {\n\tif objId < 0 {\n\t\tthis.n++\n\t\tobjId = this.n\n\t}\n\n\tif !onlyNewObj {\n\t\t// set current object id integer\n\t\tthis.current_obj_id = objId\n\n\t\t// Create new PdfObject and PdfObjectId\n\t\tthis.current_obj = new(PdfObject)\n\t\tthis.current_obj.buffer = new(bytes.Buffer)\n\t\tthis.current_obj.id = new(PdfObjectId)\n\t\tthis.current_obj.id.id = objId\n\t\tthis.current_obj.id.hash = this.shaOfInt(objId)\n\n\t\tthis.written_obj_pos[this.current_obj.id] = make(map[int]string, 0)\n\t}\n}\n\nfunc (this *PdfWriter) endObj() {\n\tthis.out(\"endobj\")\n\n\tthis.written_objs[this.current_obj.id] = this.current_obj.buffer.Bytes()\n\tthis.current_obj_id = -1\n}\n\nfunc (this *PdfWriter) shaOfInt(i int) string {\n\thasher := sha1.New()\n\thasher.Write([]byte(fmt.Sprintf(\"%s-%s\", i, this.r.sourceFile)))\n\tsha := hex.EncodeToString(hasher.Sum(nil))\n\treturn sha\n}\n\nfunc (this *PdfWriter) outObjRef(objId int) {\n\tsha := this.shaOfInt(objId)\n\n\t// Keep track of object hash and position - to be replaced with actual object id (integer)\n\tthis.written_obj_pos[this.current_obj.id][this.current_obj.buffer.Len()] = sha\n\n\tif this.use_hash {\n\t\tthis.current_obj.buffer.WriteString(sha)\n\t} else {\n\t\tthis.current_obj.buffer.WriteString(fmt.Sprintf(\"%d\", objId))\n\t}\n\tthis.current_obj.buffer.WriteString(\" 0 R \")\n}\n\n// Output PDF data with a newline\nfunc (this *PdfWriter) out(s string) {\n\tthis.current_obj.buffer.WriteString(s)\n\tthis.current_obj.buffer.WriteString(\"\\n\")\n}\n\n// Output PDF data\nfunc (this *PdfWriter) straightOut(s string) {\n\tthis.current_obj.buffer.WriteString(s)\n}\n\n// Output a PdfValue\nfunc (this *PdfWriter) writeValue(value *PdfValue) {\n\tswitch value.Type {\n\tcase PDF_TYPE_TOKEN:\n\t\tthis.straightOut(value.Token + \" \")\n\t\tbreak\n\n\tcase PDF_TYPE_NUMERIC:\n\t\tthis.straightOut(fmt.Sprintf(\"%d\", value.Int) + \" \")\n\t\tbreak\n\n\tcase PDF_TYPE_REAL:\n\t\tthis.straightOut(fmt.Sprintf(\"%F\", value.Real) + \" \")\n\t\tbreak\n\n\tcase PDF_TYPE_ARRAY:\n\t\tthis.straightOut(\"[\")\n\t\tfor i := 0; i < len(value.Array); i++ {\n\t\t\tthis.writeValue(value.Array[i])\n\t\t}\n\t\tthis.out(\"]\")\n\t\tbreak\n\n\tcase PDF_TYPE_DICTIONARY:\n\t\tthis.straightOut(\"<<\")\n\t\tfor k, v := range value.Dictionary {\n\t\t\tthis.straightOut(k + \" \")\n\t\t\tthis.writeValue(v)\n\t\t}\n\t\tthis.straightOut(\">>\")\n\t\tbreak\n\n\tcase PDF_TYPE_OBJREF:\n\t\t// An indirect object reference.  Fill the object stack if needed.\n\t\t// Check to see if object already exists on the don_obj_stack.\n\t\tif _, ok := this.don_obj_stack[value.Id]; !ok {\n\t\t\tthis.newObj(-1, true)\n\t\t\tthis.obj_stack[value.Id] = &PdfValue{Type: PDF_TYPE_OBJREF, Gen: value.Gen, Id: value.Id, NewId: this.n}\n\t\t\tthis.don_obj_stack[value.Id] = &PdfValue{Type: PDF_TYPE_OBJREF, Gen: value.Gen, Id: value.Id, NewId: this.n}\n\t\t}\n\n\t\t// Get object ID from don_obj_stack\n\t\tobjId := this.don_obj_stack[value.Id].NewId\n\t\tthis.outObjRef(objId)\n\t\t//this.out(fmt.Sprintf(\"%d 0 R\", objId))\n\t\tbreak\n\n\tcase PDF_TYPE_STRING:\n\t\t// A string\n\t\tthis.straightOut(\"(\" + value.String + \")\")\n\t\tbreak\n\n\tcase PDF_TYPE_STREAM:\n\t\t// A stream.  First, output the stream dictionary, then the stream data itself.\n\t\tthis.writeValue(value.Value)\n\t\tthis.out(\"stream\")\n\t\tthis.out(string(value.Stream.Bytes))\n\t\tthis.out(\"endstream\")\n\t\tbreak\n\n\tcase PDF_TYPE_HEX:\n\t\tthis.straightOut(\"<\" + value.String + \">\")\n\t\tbreak\n\n\tcase PDF_TYPE_BOOLEAN:\n\t\tif value.Bool {\n\t\t\tthis.straightOut(\"true\")\n\t\t} else {\n\t\t\tthis.straightOut(\"false\")\n\t\t}\n\t\tbreak\n\n\tcase PDF_TYPE_NULL:\n\t\t// The null object\n\t\tthis.straightOut(\"null \")\n\t\tbreak\n\t}\n}\n\n// Output Form XObjects (1 for each template)\n// returns a map of template names (e.g. /GOFPDITPL1) to PdfObjectId\nfunc (this *PdfWriter) PutFormXobjects(reader *PdfReader) (map[string]*PdfObjectId, error) {\n\t// Set current reader\n\tthis.r = reader\n\n\tvar err error\n\tvar result = make(map[string]*PdfObjectId, 0)\n\n\tcompress := true\n\tfilter := \"\"\n\tif compress {\n\t\tfilter = \"/Filter /FlateDecode \"\n\t}\n\n\tfor i := 0; i < len(this.tpls); i++ {\n\t\ttpl := this.tpls[i]\n\t\tif tpl == nil {\n\t\t\treturn nil, errors.New(\"Template is nil\")\n\t\t}\n\t\tvar p string\n\t\tif compress {\n\t\t\tvar b bytes.Buffer\n\t\t\tw := zlib.NewWriter(&b)\n\t\t\tw.Write([]byte(tpl.Buffer))\n\t\t\tw.Close()\n\n\t\t\tp = b.String()\n\t\t} else {\n\t\t\tp = tpl.Buffer\n\t\t}\n\n\t\t// Create new PDF object\n\t\tthis.newObj(-1, false)\n\n\t\tcN := this.n // remember current \"n\"\n\n\t\ttpl.N = this.n\n\n\t\t// Return xobject form name and object position\n\t\tpdfObjId := new(PdfObjectId)\n\t\tpdfObjId.id = cN\n\t\tpdfObjId.hash = this.shaOfInt(cN)\n\t\tresult[fmt.Sprintf(\"/GOFPDITPL%d\", i+this.tpl_id_offset)] = pdfObjId\n\n\t\tthis.out(\"<<\" + filter + \"/Type /XObject\")\n\t\tthis.out(\"/Subtype /Form\")\n\t\tthis.out(\"/FormType 1\")\n\n\t\tthis.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))\n\n\t\tvar c, s, tx, ty float64\n\t\tc = 1\n\n\t\t// Handle rotated pages\n\t\tif tpl.Box != nil {\n\t\t\ttx = -tpl.Box[\"llx\"]\n\t\t\tty = -tpl.Box[\"lly\"]\n\n\t\t\tif tpl.Rotation != 0 {\n\t\t\t\tangle := float64(tpl.Rotation) * math.Pi / 180.0\n\t\t\t\tc = math.Cos(float64(angle))\n\t\t\t\ts = math.Sin(float64(angle))\n\n\t\t\t\tswitch tpl.Rotation {\n\t\t\t\tcase -90:\n\t\t\t\t\ttx = -tpl.Box[\"lly\"]\n\t\t\t\t\tty = tpl.Box[\"urx\"]\n\t\t\t\t\tbreak\n\n\t\t\t\tcase -180:\n\t\t\t\t\ttx = tpl.Box[\"urx\"]\n\t\t\t\t\tty = tpl.Box[\"ury\"]\n\t\t\t\t\tbreak\n\n\t\t\t\tcase -270:\n\t\t\t\t\ttx = tpl.Box[\"ury\"]\n\t\t\t\t\tty = -tpl.Box[\"llx\"]\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\ttx = -tpl.Box[\"x\"] * 2\n\t\t\tty = tpl.Box[\"y\"] * 2\n\t\t}\n\n\t\ttx *= this.k\n\t\tty *= this.k\n\n\t\tif c != 1 || s != 0 || tx != 0 || ty != 0 {\n\t\t\tthis.out(fmt.Sprintf(\"/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]\", c, s, -s, c, tx, ty))\n\t\t}\n\n\t\t// Now write resources\n\t\tthis.out(\"/Resources \")\n\n\t\tif tpl.Resources != nil {\n\t\t\tthis.writeValue(tpl.Resources) // \"n\" will be changed\n\t\t} else {\n\t\t\treturn nil, errors.New(\"Template resources are empty\")\n\t\t}\n\n\t\tnN := this.n // remember new \"n\"\n\t\tthis.n = cN  // reset to current \"n\"\n\n\t\tthis.out(\"/Length \" + fmt.Sprintf(\"%d\", len(p)) + \" >>\")\n\n\t\tthis.out(\"stream\")\n\t\tthis.out(p)\n\t\tthis.out(\"endstream\")\n\n\t\tthis.endObj()\n\n\t\tthis.n = nN // reset to new \"n\"\n\n\t\t// Put imported objects, starting with the ones from the XObject's Resources,\n\t\t// then from dependencies of those resources).\n\t\terr = this.putImportedObjects(reader)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Failed to put imported objects\")\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\nfunc (this *PdfWriter) putImportedObjects(reader *PdfReader) error {\n\tvar err error\n\tvar nObj *PdfValue\n\n\t// obj_stack will have new items added to it in the inner loop, so do another loop to check for extras\n\t// TODO make the order of this the same every time\n\tfor {\n\t\tatLeastOne := false\n\n\t\t// FIXME:  How to determine number of objects before this loop?\n\t\tfor i := 0; i < 9999; i++ {\n\t\t\tk := i\n\t\t\tv := this.obj_stack[i]\n\n\t\t\tif v == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tatLeastOne = true\n\n\t\t\tnObj, err = reader.resolveObject(v)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Unable to resolve object\")\n\t\t\t}\n\n\t\t\t// New object with \"NewId\" field\n\t\t\tthis.newObj(v.NewId, false)\n\n\t\t\tif nObj.Type == PDF_TYPE_STREAM {\n\t\t\t\tthis.writeValue(nObj)\n\t\t\t} else {\n\t\t\t\tthis.writeValue(nObj.Value)\n\t\t\t}\n\n\t\t\tthis.endObj()\n\n\t\t\t// Remove from stack\n\t\t\tthis.obj_stack[k] = nil\n\t\t}\n\n\t\tif !atLeastOne {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Get the calculated size of a template\n// If one size is given, this method calculates the other one\nfunc (this *PdfWriter) getTemplateSize(tplid int, _w float64, _h float64) map[string]float64 {\n\tresult := make(map[string]float64, 2)\n\n\ttpl := this.tpls[tplid]\n\n\tw := tpl.W\n\th := tpl.H\n\n\tif _w == 0 && _h == 0 {\n\t\t_w = w\n\t\t_h = h\n\t}\n\n\tif _w == 0 {\n\t\t_w = _h * w / h\n\t}\n\n\tif _h == 0 {\n\t\t_h = _w * h / w\n\t}\n\n\tresult[\"w\"] = _w\n\tresult[\"h\"] = _h\n\n\treturn result\n}\n\nfunc (this *PdfWriter) UseTemplate(tplid int, _x float64, _y float64, _w float64, _h float64) (string, float64, float64, float64, float64) {\n\ttpl := this.tpls[tplid]\n\n\tw := tpl.W\n\th := tpl.H\n\n\t_x += tpl.X\n\t_y += tpl.Y\n\n\twh := this.getTemplateSize(0, _w, _h)\n\n\t_w = wh[\"w\"]\n\t_h = wh[\"h\"]\n\n\ttData := make(map[string]float64, 9)\n\ttData[\"x\"] = 0.0\n\ttData[\"y\"] = 0.0\n\ttData[\"w\"] = _w\n\ttData[\"h\"] = _h\n\ttData[\"scaleX\"] = (_w / w)\n\ttData[\"scaleY\"] = (_h / h)\n\ttData[\"tx\"] = _x\n\ttData[\"ty\"] = (0 - _y - _h)\n\ttData[\"lty\"] = (0 - _y - _h) - (0-h)*(_h/h)\n\n\treturn fmt.Sprintf(\"/GOFPDITPL%d\", tplid+this.tpl_id_offset), tData[\"scaleX\"], tData[\"scaleY\"], tData[\"tx\"] * this.k, tData[\"ty\"] * this.k\n}\n"
  },
  {
    "path": "vendor/github.com/pkg/errors/.gitignore",
    "content": "# 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 specific extensions/prefixes\n*.[568vq]\n[568vq].out\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n_testmain.go\n\n*.exe\n*.test\n*.prof\n"
  },
  {
    "path": "vendor/github.com/pkg/errors/.travis.yml",
    "content": "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.10.x\n  - 1.11.x\n  - tip\n\nscript:\n  - go test -v ./...\n"
  },
  {
    "path": "vendor/github.com/pkg/errors/LICENSE",
    "content": "Copyright (c) 2015, Dave Cheney <dave@cheney.net>\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "vendor/github.com/pkg/errors/README.md",
    "content": "# 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)\n\nPackage errors provides simple error handling primitives.\n\n`go get github.com/pkg/errors`\n\nThe traditional error handling idiom in Go is roughly akin to\n```go\nif err != nil {\n        return err\n}\n```\nwhich 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.\n\n## Adding context to an error\n\nThe errors.Wrap function returns a new error that adds context to the original error. For example\n```go\n_, err := ioutil.ReadAll(r)\nif err != nil {\n        return errors.Wrap(err, \"read failed\")\n}\n```\n## Retrieving the cause of an error\n\nUsing `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`.\n```go\ntype causer interface {\n        Cause() error\n}\n```\n`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:\n```go\nswitch err := errors.Cause(err).(type) {\ncase *MyError:\n        // handle specifically\ndefault:\n        // unknown error\n}\n```\n\n[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).\n\n## Contributing\n\nWe welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.\n\nBefore proposing a change, please discuss your change by raising an issue.\n\n## License\n\nBSD-2-Clause\n"
  },
  {
    "path": "vendor/github.com/pkg/errors/appveyor.yml",
    "content": "version: build-{build}.{branch}\n\nclone_folder: C:\\gopath\\src\\github.com\\pkg\\errors\nshallow_clone: true # for startup speed\n\nenvironment:\n  GOPATH: C:\\gopath\n\nplatform:\n  - x64\n\n# http://www.appveyor.com/docs/installed-software\ninstall:\n  # some helpful output for debugging builds\n  - go version\n  - go env\n  # pre-installed MinGW at C:\\MinGW is 32bit only\n  # but MSYS2 at C:\\msys64 has mingw64\n  - set PATH=C:\\msys64\\mingw64\\bin;%PATH%\n  - gcc --version\n  - g++ --version\n\nbuild_script:\n  - go install -v ./...\n\ntest_script:\n  - set PATH=C:\\gopath\\bin;%PATH%\n  - go test -v ./...\n\n#artifacts:\n#  - path: '%GOPATH%\\bin\\*.exe'\ndeploy: off\n"
  },
  {
    "path": "vendor/github.com/pkg/errors/errors.go",
    "content": "// Package errors provides simple error handling primitives.\n//\n// The traditional error handling idiom in Go is roughly akin to\n//\n//     if err != nil {\n//             return err\n//     }\n//\n// which when applied recursively up the call stack results in error reports\n// without context or debugging information. The errors package allows\n// programmers to add context to the failure path in their code in a way\n// that does not destroy the original value of the error.\n//\n// Adding context to an error\n//\n// The errors.Wrap function returns a new error that adds context to the\n// original error by recording a stack trace at the point Wrap is called,\n// together with the supplied message. For example\n//\n//     _, err := ioutil.ReadAll(r)\n//     if err != nil {\n//             return errors.Wrap(err, \"read failed\")\n//     }\n//\n// If additional control is required, the errors.WithStack and\n// errors.WithMessage functions destructure errors.Wrap into its component\n// operations: annotating an error with a stack trace and with a message,\n// respectively.\n//\n// Retrieving the cause of an error\n//\n// Using errors.Wrap constructs a stack of errors, adding context to the\n// preceding error. Depending on the nature of the error it may be necessary\n// to reverse the operation of errors.Wrap to retrieve the original error\n// for inspection. Any error value which implements this interface\n//\n//     type causer interface {\n//             Cause() error\n//     }\n//\n// can be inspected by errors.Cause. errors.Cause will recursively retrieve\n// the topmost error that does not implement causer, which is assumed to be\n// the original cause. For example:\n//\n//     switch err := errors.Cause(err).(type) {\n//     case *MyError:\n//             // handle specifically\n//     default:\n//             // unknown error\n//     }\n//\n// Although the causer interface is not exported by this package, it is\n// considered a part of its stable public interface.\n//\n// Formatted printing of errors\n//\n// All error values returned from this package implement fmt.Formatter and can\n// be formatted by the fmt package. The following verbs are supported:\n//\n//     %s    print the error. If the error has a Cause it will be\n//           printed recursively.\n//     %v    see %s\n//     %+v   extended format. Each Frame of the error's StackTrace will\n//           be printed in detail.\n//\n// Retrieving the stack trace of an error or wrapper\n//\n// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are\n// invoked. This information can be retrieved with the following interface:\n//\n//     type stackTracer interface {\n//             StackTrace() errors.StackTrace\n//     }\n//\n// The returned errors.StackTrace type is defined as\n//\n//     type StackTrace []Frame\n//\n// The Frame type represents a call site in the stack trace. Frame supports\n// the fmt.Formatter interface that can be used for printing information about\n// the stack trace of this error. For example:\n//\n//     if err, ok := err.(stackTracer); ok {\n//             for _, f := range err.StackTrace() {\n//                     fmt.Printf(\"%+s:%d\", f)\n//             }\n//     }\n//\n// Although the stackTracer interface is not exported by this package, it is\n// considered a part of its stable public interface.\n//\n// See the documentation for Frame.Format for more details.\npackage errors\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// New returns an error with the supplied message.\n// New also records the stack trace at the point it was called.\nfunc New(message string) error {\n\treturn &fundamental{\n\t\tmsg:   message,\n\t\tstack: callers(),\n\t}\n}\n\n// Errorf formats according to a format specifier and returns the string\n// as a value that satisfies error.\n// Errorf also records the stack trace at the point it was called.\nfunc Errorf(format string, args ...interface{}) error {\n\treturn &fundamental{\n\t\tmsg:   fmt.Sprintf(format, args...),\n\t\tstack: callers(),\n\t}\n}\n\n// fundamental is an error that has a message and a stack, but no caller.\ntype fundamental struct {\n\tmsg string\n\t*stack\n}\n\nfunc (f *fundamental) Error() string { return f.msg }\n\nfunc (f *fundamental) Format(s fmt.State, verb rune) {\n\tswitch verb {\n\tcase 'v':\n\t\tif s.Flag('+') {\n\t\t\tio.WriteString(s, f.msg)\n\t\t\tf.stack.Format(s, verb)\n\t\t\treturn\n\t\t}\n\t\tfallthrough\n\tcase 's':\n\t\tio.WriteString(s, f.msg)\n\tcase 'q':\n\t\tfmt.Fprintf(s, \"%q\", f.msg)\n\t}\n}\n\n// WithStack annotates err with a stack trace at the point WithStack was called.\n// If err is nil, WithStack returns nil.\nfunc WithStack(err error) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\treturn &withStack{\n\t\terr,\n\t\tcallers(),\n\t}\n}\n\ntype withStack struct {\n\terror\n\t*stack\n}\n\nfunc (w *withStack) Cause() error { return w.error }\n\nfunc (w *withStack) Format(s fmt.State, verb rune) {\n\tswitch verb {\n\tcase 'v':\n\t\tif s.Flag('+') {\n\t\t\tfmt.Fprintf(s, \"%+v\", w.Cause())\n\t\t\tw.stack.Format(s, verb)\n\t\t\treturn\n\t\t}\n\t\tfallthrough\n\tcase 's':\n\t\tio.WriteString(s, w.Error())\n\tcase 'q':\n\t\tfmt.Fprintf(s, \"%q\", w.Error())\n\t}\n}\n\n// Wrap returns an error annotating err with a stack trace\n// at the point Wrap is called, and the supplied message.\n// If err is nil, Wrap returns nil.\nfunc Wrap(err error, message string) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\terr = &withMessage{\n\t\tcause: err,\n\t\tmsg:   message,\n\t}\n\treturn &withStack{\n\t\terr,\n\t\tcallers(),\n\t}\n}\n\n// Wrapf returns an error annotating err with a stack trace\n// at the point Wrapf is called, and the format specifier.\n// If err is nil, Wrapf returns nil.\nfunc Wrapf(err error, format string, args ...interface{}) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\terr = &withMessage{\n\t\tcause: err,\n\t\tmsg:   fmt.Sprintf(format, args...),\n\t}\n\treturn &withStack{\n\t\terr,\n\t\tcallers(),\n\t}\n}\n\n// WithMessage annotates err with a new message.\n// If err is nil, WithMessage returns nil.\nfunc WithMessage(err error, message string) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\treturn &withMessage{\n\t\tcause: err,\n\t\tmsg:   message,\n\t}\n}\n\n// WithMessagef annotates err with the format specifier.\n// If err is nil, WithMessagef returns nil.\nfunc WithMessagef(err error, format string, args ...interface{}) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\treturn &withMessage{\n\t\tcause: err,\n\t\tmsg:   fmt.Sprintf(format, args...),\n\t}\n}\n\ntype withMessage struct {\n\tcause error\n\tmsg   string\n}\n\nfunc (w *withMessage) Error() string { return w.msg + \": \" + w.cause.Error() }\nfunc (w *withMessage) Cause() error  { return w.cause }\n\nfunc (w *withMessage) Format(s fmt.State, verb rune) {\n\tswitch verb {\n\tcase 'v':\n\t\tif s.Flag('+') {\n\t\t\tfmt.Fprintf(s, \"%+v\\n\", w.Cause())\n\t\t\tio.WriteString(s, w.msg)\n\t\t\treturn\n\t\t}\n\t\tfallthrough\n\tcase 's', 'q':\n\t\tio.WriteString(s, w.Error())\n\t}\n}\n\n// Cause returns the underlying cause of the error, if possible.\n// An error value has a cause if it implements the following\n// interface:\n//\n//     type causer interface {\n//            Cause() error\n//     }\n//\n// If the error does not implement Cause, the original error will\n// be returned. If the error is nil, nil will be returned without further\n// investigation.\nfunc Cause(err error) error {\n\ttype causer interface {\n\t\tCause() error\n\t}\n\n\tfor err != nil {\n\t\tcause, ok := err.(causer)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\terr = cause.Cause()\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "vendor/github.com/pkg/errors/stack.go",
    "content": "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 stack frame.\ntype Frame uintptr\n\n// pc returns the program counter for this frame;\n// multiple frames may have the same PC value.\nfunc (f Frame) pc() uintptr { return uintptr(f) - 1 }\n\n// file returns the full path to the file that contains the\n// function for this Frame's pc.\nfunc (f Frame) file() string {\n\tfn := runtime.FuncForPC(f.pc())\n\tif fn == nil {\n\t\treturn \"unknown\"\n\t}\n\tfile, _ := fn.FileLine(f.pc())\n\treturn file\n}\n\n// line returns the line number of source code of the\n// function for this Frame's pc.\nfunc (f Frame) line() int {\n\tfn := runtime.FuncForPC(f.pc())\n\tif fn == nil {\n\t\treturn 0\n\t}\n\t_, line := fn.FileLine(f.pc())\n\treturn line\n}\n\n// Format formats the frame according to the fmt.Formatter interface.\n//\n//    %s    source file\n//    %d    source line\n//    %n    function name\n//    %v    equivalent to %s:%d\n//\n// Format accepts flags that alter the printing of some verbs, as follows:\n//\n//    %+s   function name and path of source file relative to the compile time\n//          GOPATH separated by \\n\\t (<funcname>\\n\\t<path>)\n//    %+v   equivalent to %+s:%d\nfunc (f Frame) Format(s fmt.State, verb rune) {\n\tswitch verb {\n\tcase 's':\n\t\tswitch {\n\t\tcase s.Flag('+'):\n\t\t\tpc := f.pc()\n\t\t\tfn := runtime.FuncForPC(pc)\n\t\t\tif fn == nil {\n\t\t\t\tio.WriteString(s, \"unknown\")\n\t\t\t} else {\n\t\t\t\tfile, _ := fn.FileLine(pc)\n\t\t\t\tfmt.Fprintf(s, \"%s\\n\\t%s\", fn.Name(), file)\n\t\t\t}\n\t\tdefault:\n\t\t\tio.WriteString(s, path.Base(f.file()))\n\t\t}\n\tcase 'd':\n\t\tfmt.Fprintf(s, \"%d\", f.line())\n\tcase 'n':\n\t\tname := runtime.FuncForPC(f.pc()).Name()\n\t\tio.WriteString(s, funcname(name))\n\tcase 'v':\n\t\tf.Format(s, 's')\n\t\tio.WriteString(s, \":\")\n\t\tf.Format(s, 'd')\n\t}\n}\n\n// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).\ntype StackTrace []Frame\n\n// Format formats the stack of Frames according to the fmt.Formatter interface.\n//\n//    %s\tlists source files for each Frame in the stack\n//    %v\tlists the source file and line number for each Frame in the stack\n//\n// Format accepts flags that alter the printing of some verbs, as follows:\n//\n//    %+v   Prints filename, function, and line number for each Frame in the stack.\nfunc (st StackTrace) Format(s fmt.State, verb rune) {\n\tswitch verb {\n\tcase 'v':\n\t\tswitch {\n\t\tcase s.Flag('+'):\n\t\t\tfor _, f := range st {\n\t\t\t\tfmt.Fprintf(s, \"\\n%+v\", f)\n\t\t\t}\n\t\tcase s.Flag('#'):\n\t\t\tfmt.Fprintf(s, \"%#v\", []Frame(st))\n\t\tdefault:\n\t\t\tfmt.Fprintf(s, \"%v\", []Frame(st))\n\t\t}\n\tcase 's':\n\t\tfmt.Fprintf(s, \"%s\", []Frame(st))\n\t}\n}\n\n// stack represents a stack of program counters.\ntype stack []uintptr\n\nfunc (s *stack) Format(st fmt.State, verb rune) {\n\tswitch verb {\n\tcase 'v':\n\t\tswitch {\n\t\tcase st.Flag('+'):\n\t\t\tfor _, pc := range *s {\n\t\t\t\tf := Frame(pc)\n\t\t\t\tfmt.Fprintf(st, \"\\n%+v\", f)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (s *stack) StackTrace() StackTrace {\n\tf := make([]Frame, len(*s))\n\tfor i := 0; i < len(f); i++ {\n\t\tf[i] = Frame((*s)[i])\n\t}\n\treturn f\n}\n\nfunc callers() *stack {\n\tconst depth = 32\n\tvar pcs [depth]uintptr\n\tn := runtime.Callers(3, pcs[:])\n\tvar st stack = pcs[0:n]\n\treturn &st\n}\n\n// funcname removes the path prefix component of a function's name reported by func.Name().\nfunc funcname(name string) string {\n\ti := strings.LastIndex(name, \"/\")\n\tname = name[i+1:]\n\ti = strings.Index(name, \".\")\n\treturn name[i+1:]\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/.gitignore",
    "content": "##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 files\nbin/\ngen/\npkg/\n*.jar\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n##eclipse\n*.pydevproject\n.project\n.metadata\nbin/**\ntmp/**\ntmp/**/*\n*.tmp\n*.bak\n*.swp\n*~.nib\nlocal.properties\n.classpath\n.settings/\n.loadpath\n\n# External tool builders\n.externalToolBuilders/\n\n# Locally stored \"Eclipse launch configurations\"\n*.launch\n\n# CDT-specific\n.cproject\n\n# PDT-specific\n.buildpath\n\n##tmp\n*~\n*.bak\n\nproguard-project.txt\n/project.properties\nlint.xml\n.bzr\n\nfontmaker/tmp/\nfontmaker/fontmaker\nfontmaker/ttf/\n\n*.orig\n\n.vscode\ntest/out/\ntest/debug.test\n*.test\n*.out\n.DS_Store\n.idea\n.scannerwork\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/Changelog.md",
    "content": "### May 2016\n\nRemove old function\n- ```GoPdf.AddFont(family string, ifont IFont, zfontpath string)```.\n- Remove all font map file.\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 signintech\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/README.md",
    "content": "gopdf\n====\n\ngopdf is a simple library for generating PDF document written in Go lang.\n\n\n#### Features\n\n- Unicode subfont embedding. (Chinese, Japanese, Korean, etc.)\n- Draw line, oval, rect, curve\n- Draw image ( jpg, png )\n  - Set image mask\n- Password protection\n- Font [kerning](https://en.wikipedia.org/wiki/Kerning)\n\n\n## Installation\n ```\n go get -u github.com/signintech/gopdf\n ```\n\n\n### Print text \n\n```go\n  \npackage main\nimport (\n\t\"log\"\n\t\"github.com/signintech/gopdf\"\n)\n\nfunc main() {\n\n\tpdf := gopdf.GoPdf{}\n\tpdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 })  \n\tpdf.AddPage()\n\terr := pdf.AddTTFFont(\"wts11\", \"../ttf/wts11.ttf\")\n\tif err != nil {\n\t\tlog.Print(err.Error())\n\t\treturn\n\t}\n\n\terr = pdf.SetFont(\"wts11\", \"\", 14)\n\tif err != nil {\n\t\tlog.Print(err.Error())\n\t\treturn\n\t}\n\tpdf.Cell(nil, \"您好\")\n\tpdf.WritePdf(\"hello.pdf\")\n\n}\n\n```\n  \n### Image\n  \n```go\n\npackage main\nimport (\n\t\"log\"\n\t\"github.com/signintech/gopdf\"\n)\n\nfunc main() {\n\tpdf := gopdf.GoPdf{}\n\tpdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4 })  \n\tpdf.AddPage()\n\tvar err error\n\terr = pdf.AddTTFFont(\"loma\", \"../ttf/Loma.ttf\")\n\tif err != nil {\n\t\tlog.Print(err.Error())\n\t\treturn\n\t}\n\t\n\tpdf.Image(\"../imgs/gopher.jpg\", 200, 50, nil) //print image\n\terr = pdf.SetFont(\"loma\", \"\", 14)\n\tif err != nil {\n\t\tlog.Print(err.Error())\n\t\treturn\n\t}\n\tpdf.SetX(250) //move current location\n\tpdf.SetY(200)\n\tpdf.Cell(nil, \"gopher and gopher\") //print text\n\n\tpdf.WritePdf(\"image.pdf\")\n}\n``` \n\n### Links\n\n```go\n\npackage main\n\nimport (\n\t\"log\"\n\t\"github.com/signintech/gopdf\"\n)\n\nfunc main()  {\n\tpdf := gopdf.GoPdf{}\n\tpdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 }) //595.28, 841.89 = A4\n\tpdf.AddPage()\n\terr := pdf.AddTTFFont(\"times\", \"./test/res/times.ttf\")\n\tif err != nil {\n\t\tlog.Print(err.Error())\n\t\treturn\n\t}\n\n\terr = pdf.SetFont(\"times\", \"\", 14)\n\tif err != nil {\n\t\tlog.Print(err.Error())\n\t\treturn\n\t}\n\n\tpdf.SetX(30)\n\tpdf.SetY(40)\n\tpdf.Text(\"Link to example.com\")\n\tpdf.AddExternalLink(\"http://example.com/\", 27.5, 28, 125, 15)\n\n\tpdf.SetX(30)\n\tpdf.SetY(70)\n\tpdf.Text(\"Link to second page\")\n\tpdf.AddInternalLink(\"anchor\", 27.5, 58, 120, 15)\n\n\tpdf.AddPage()\n\tpdf.SetX(30)\n\tpdf.SetY(100)\n\tpdf.SetAnchor(\"anchor\")\n\tpdf.Text(\"Anchor position\")\n\n\tpdf.WritePdf(\"hello.tmp.pdf\")\n\n}\n```\n\n### Draw line\n```go\npdf.SetLineWidth(2)\npdf.SetLineType(\"dashed\")\npdf.Line(10, 30, 585, 30)\n```\n\n### Draw oval\n```go\npdf.SetLineWidth(1)\npdf.Oval(100, 200, 500, 500)\n```\n\n### Draw polygon\n```go\npdf.SetStrokeColor(255, 0, 0)\npdf.SetLineWidth(2)\npdf.SetFillColor(0, 255, 0)\npdf.Polygon([]gopdf.Point{{X: 10, Y: 30}, {X: 585, Y: 200}, {X: 585, Y: 250}}, \"DF\")\n```\n\n### Rotation text or image\n```go\npdf.SetX(100)\npdf.SetY(100)\npdf.Rotate(270.0, 100.0, 100.0)\npdf.Text(\"Hello...\")\npdf.RotateReset() //reset\n```\n\n### Set transparency\nRead about [transparency in pdf](https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf) `(page 320, section 11)`\n```go\n// alpha - value of transparency, can be between `0` and `1`\n// 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)`\n\ntransparency := Transparency{\n\tAlpha: 0.5,\n\tBlendModeType: \"\",\n}\npdf.SetTransparency(transparency Transparency)\n```\n\n### Password protection\n```go\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/signintech/gopdf\"\n)\n\n\nfunc main() {\n\n\tpdf := gopdf.GoPdf{}\n\tpdf.Start(gopdf.Config{\n\t\tPageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4\n\t\tProtection: gopdf.PDFProtectionConfig{\n\t\t\tUseProtection: true,\n\t\t\tPermissions: gopdf.PermissionsPrint | gopdf.PermissionsCopy | gopdf.PermissionsModify,\n\t\t\tOwnerPass:   []byte(\"123456\"),\n\t\t\tUserPass:    []byte(\"123456789\")},\n\t})\n\n\tpdf.AddPage()\n\tpdf.AddTTFFont(\"loma\", \"../ttf/loma.ttf\")\n\tpdf.Cell(nil,\"Hi\")\n\tpdf.WritePdf(\"protect.pdf\")\n}\n\n```\n### Import existing PDF \nImport existing PDF power by package [gofpdi](https://github.com/phpdave11/gofpdi) created by @phpdave11 (thank you :smile:)\n```go\npackage main\n\nimport (\n        \"github.com/signintech/gopdf\"\n        \"io\"\n        \"net/http\"\n        \"os\"\n)\n\nfunc main() {\n        var err error\n\n        // Download a Font\n        fontUrl := \"https://github.com/google/fonts/raw/master/ofl/daysone/DaysOne-Regular.ttf\"\n        if err = DownloadFile(\"example-font.ttf\", fontUrl); err != nil {\n            panic(err)\n        }\n\n        // Download a PDF\n        fileUrl := \"https://tcpdf.org/files/examples/example_012.pdf\"\n        if err = DownloadFile(\"example-pdf.pdf\", fileUrl); err != nil {\n            panic(err)\n        }\n\n        pdf := gopdf.GoPdf{}\n        pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4\n\n        pdf.AddPage()\n\n        err = pdf.AddTTFFont(\"daysone\", \"example-font.ttf\")\n        if err != nil {\n            panic(err)\n        }\n\n        err = pdf.SetFont(\"daysone\", \"\", 20)\n        if err != nil {\n            panic(err)\n        }\n\n        // Color the page\n        pdf.SetLineWidth(0.1)\n        pdf.SetFillColor(124, 252, 0) //setup fill color\n        pdf.RectFromUpperLeftWithStyle(50, 100, 400, 600, \"FD\")\n        pdf.SetFillColor(0, 0, 0)\n\n        pdf.SetX(50)\n        pdf.SetY(50)\n        pdf.Cell(nil, \"Import existing PDF into GoPDF Document\")\n\n        // Import page 1\n        tpl1 := pdf.ImportPage(\"example-pdf.pdf\", 1, \"/MediaBox\")\n\n        // Draw pdf onto page\n        pdf.UseImportedTemplate(tpl1, 50, 100, 400, 0)\n\n        pdf.WritePdf(\"example.pdf\")\n\n}\n\n// DownloadFile will download a url to a local file. It's efficient because it will\n// write as it downloads and not load the whole file into memory.\nfunc DownloadFile(filepath string, url string) error {\n        // Get the data\n        resp, err := http.Get(url)\n        if err != nil {\n            return err\n        }\n        defer resp.Body.Close()\n\n        // Create the file\n        out, err := os.Create(filepath)\n        if err != nil {\n            return err\n        }\n        defer out.Close()\n\n        // Write the body to file\n        _, err = io.Copy(out, resp.Body)\n        return err\n}\n\n```\n\n### Possible to set [Trim-box](https://wiki.scribus.net/canvas/PDF_Boxes_:_mediabox,_cropbox,_bleedbox,_trimbox,_artbox)\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/signintech/gopdf\"\n)\n\nfunc main() {\n\t\n    pdf := gopdf.GoPdf{}\n    mm6ToPx := 22.68\n    \n    // Base trim-box\n    pdf.Start(gopdf.Config{\n        PageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4\n        TrimBox: gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},\n    })\n\n    // Page trim-box\n    opt := gopdf.PageOption{\n        PageSize: gopdf.PageSizeA4, //595.28, 841.89 = A4\n        TrimBox: &gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},\n    }\n    pdf.AddPageWithOption(opt)\n\n    if err := pdf.AddTTFFont(\"wts11\", \"../ttf/wts11.ttf\"); err != nil {\n        log.Print(err.Error())\n        return\n    }\n    \n    if err := pdf.SetFont(\"wts11\", \"\", 14); err != nil {\n        log.Print(err.Error())\n        return\n    }\n\n    pdf.Cell(nil,\"Hi\")\n    pdf.WritePdf(\"hello.pdf\")\n}\n\n```\n\nvisit https://github.com/oneplus1000/gopdfsample for more samples.\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/box.go",
    "content": "package gopdf\n\ntype Box struct {\n\tLeft, Top, Right, Bottom float64\n\tunitOverride             int\n}\n\n// UnitsToPoints converts the box coordinates to Points. When this is called it is assumed the values of the box are in Units\nfunc (box *Box) UnitsToPoints(t int) (b *Box) {\n\tif box == nil {\n\t\treturn\n\t}\n\n\tif box.unitOverride != UnitUnset {\n\t\tt = box.unitOverride\n\t}\n\n\tb = &Box{\n\t\tLeft:   box.Left,\n\t\tTop:    box.Top,\n\t\tRight:  box.Right,\n\t\tBottom: box.Bottom,\n\t}\n\tUnitsToPointsVar(t, &b.Left, &b.Top, &b.Right, &b.Bottom)\n\treturn\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/buff.go",
    "content": "package gopdf\n\n//Buff for pdf content\ntype Buff struct {\n\tposition int\n\tdatas    []byte\n}\n\n//Write : write []byte to buffer\nfunc (b *Buff) Write(p []byte) (int, error) {\n\tfor len(b.datas) < b.position+len(p) {\n\t\tb.datas = append(b.datas, 0)\n\t}\n\ti := 0\n\tmax := len(p)\n\tfor i < max {\n\t\tb.datas[i+b.position] = p[i]\n\t\ti++\n\t}\n\tb.position += i\n\treturn 0, nil\n}\n\n//Len : len of buffer\nfunc (b *Buff) Len() int {\n\treturn len(b.datas)\n}\n\n//Bytes : get bytes\nfunc (b *Buff) Bytes() []byte {\n\treturn b.datas\n}\n\n//Position : get current postion\nfunc (b *Buff) Position() int {\n\treturn b.position\n}\n\n//SetPosition : set current postion\nfunc (b *Buff) SetPosition(pos int) {\n\tb.position = pos\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/buff_write.go",
    "content": "package gopdf\n\nimport \"io\"\n\n//WriteUInt32  writes a 32-bit unsigned integer value to w io.Writer\nfunc WriteUInt32(w io.Writer, v uint) error {\n\ta := byte(v >> 24)\n\tb := byte(v >> 16)\n\tc := byte(v >> 8)\n\td := byte(v)\n\t_, err := w.Write([]byte{a, b, c, d})\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//WriteUInt16 writes a 16-bit unsigned integer value to w io.Writer\nfunc WriteUInt16(w io.Writer, v uint) error {\n\n\ta := byte(v >> 8)\n\tb := byte(v)\n\t_, err := w.Write([]byte{a, b})\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//WriteTag writes string value to w io.Writer\nfunc WriteTag(w io.Writer, tag string) error {\n\tb := []byte(tag)\n\t_, err := w.Write(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//WriteBytes writes []byte value to w io.Writer\nfunc WriteBytes(w io.Writer, data []byte, offset int, count int) error {\n\n\t_, err := w.Write(data[offset : offset+count])\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/buffer_pool.go",
    "content": "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 a new instance is needed\n\tNew: func() interface{} {\n\t\treturn new(bytes.Buffer)\n\t},\n}\n\n// GetBuffer fetches a buffer from the pool\nfunc GetBuffer() *bytes.Buffer {\n\treturn buffers.Get().(*bytes.Buffer)\n}\n\n// PutBuffer returns a buffer to the pool\nfunc PutBuffer(buf *bytes.Buffer) {\n\tbuf.Reset()\n\tbuffers.Put(buf)\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_contact_color.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nconst colorTypeStroke = \"RG\"\n\nconst colorTypeFill = \"rg\"\n\ntype cacheContentColor struct {\n\tcolorType string\n\tr, g, b   uint8\n}\n\nfunc (c *cacheContentColor) write(w io.Writer, protection *PDFProtection) error {\n\tfmt.Fprintf(w, \"%.3f %.3f %.3f %s\\n\", float64(c.r)/255, float64(c.g)/255, float64(c.b)/255, c.colorType)\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_gray.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nconst grayTypeFill = \"g\"\nconst grayTypeStroke = \"G\"\n\ntype cacheContentGray struct {\n\tgrayType string\n\tscale    float64\n}\n\nfunc (c *cacheContentGray) write(w io.Writer, protection *PDFProtection) error {\n\tfmt.Fprintf(w, \"%.2f %s\\n\", c.scale, c.grayType)\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_image.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentImage struct {\n\tverticalFlip     bool\n\thorizontalFlip   bool\n\tindex            int\n\tx                float64\n\ty                float64\n\tpageHeight       float64\n\trect             Rect\n\tcrop             *CropOptions\n\textGStateIndexes []int\n}\n\nfunc (c *cacheContentImage) write(w io.Writer, protection *PDFProtection) error {\n\twidth := c.rect.W\n\theight := c.rect.H\n\n\tcontentStream := \"q\\n\"\n\n\tfor _, extGStateIndex := range c.extGStateIndexes {\n\t\tcontentStream += fmt.Sprintf(\"/GS%d gs\\n\", extGStateIndex)\n\t}\n\n\tif c.horizontalFlip || c.verticalFlip {\n\t\tfh := \"1\"\n\t\tif c.horizontalFlip {\n\t\t\tfh = \"-1\"\n\t\t}\n\n\t\tfv := \"1\"\n\t\tif c.verticalFlip {\n\t\t\tfv = \"-1\"\n\t\t}\n\n\t\tcontentStream += fmt.Sprintf(\"%s 0 0 %s 0 0 cm\\n\", fh, fv)\n\t}\n\n\tif c.crop != nil {\n\t\tclippingX := c.x\n\t\tif c.horizontalFlip {\n\t\t\tclippingX = -clippingX - c.crop.Width\n\t\t}\n\n\t\tclippingY := c.pageHeight - (c.y + c.crop.Height)\n\t\tif c.verticalFlip {\n\t\t\tclippingY = -clippingY - c.crop.Height\n\t\t}\n\n\t\tstartX := c.x - c.crop.X\n\t\tif c.horizontalFlip {\n\t\t\tstartX = -startX - width\n\t\t}\n\n\t\tstartY := c.pageHeight - (c.y - c.crop.Y + c.rect.H)\n\t\tif c.verticalFlip {\n\t\t\tstartY = -startY - height\n\t\t}\n\n\t\tcontentStream += fmt.Sprintf(\"%0.2f %0.2f %0.2f %0.2f re W* n\\n\", clippingX, clippingY, c.crop.Width, c.crop.Height)\n\t\tcontentStream += 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)\n\t} else {\n\t\tx := c.x\n\t\ty := c.pageHeight - (c.y + height)\n\n\t\tif c.horizontalFlip {\n\t\t\tx = -x - width\n\t\t}\n\n\t\tif c.verticalFlip {\n\t\t\ty = -y - height\n\t\t}\n\n\t\tcontentStream += 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)\n\t}\n\n\tcontentStream += \"Q\\n\"\n\n\tif _, err := io.WriteString(w, contentStream); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_imported_object.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentImportedTemplate struct {\n\tpageHeight float64\n\ttplName    string\n\tscaleX     float64\n\tscaleY     float64\n\ttX         float64\n\ttY         float64\n}\n\nfunc (c *cacheContentImportedTemplate) write(w io.Writer, protection *PDFProtection) error {\n\tc.tY += c.pageHeight\n\tfmt.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)\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_line.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentLine struct {\n\tpageHeight float64\n\tx1         float64\n\ty1         float64\n\tx2         float64\n\ty2         float64\n}\n\nfunc (c *cacheContentLine) write(w io.Writer, protection *PDFProtection) error {\n\tfmt.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)\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_line_type.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentLineType struct {\n\tlineType string\n}\n\nfunc (c *cacheContentLineType) write(w io.Writer, protection *PDFProtection) error {\n\tswitch c.lineType {\n\tcase \"dashed\":\n\t\tfmt.Fprint(w, \"[5] 2 d\\n\")\n\tcase \"dotted\":\n\t\tfmt.Fprint(w, \"[2 3] 11 d\\n\")\n\tdefault:\n\t\tfmt.Fprint(w, \"[] 0 d\\n\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_line_width.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentLineWidth struct {\n\twidth float64\n}\n\nfunc (c *cacheContentLineWidth) write(w io.Writer, protection *PDFProtection) error {\n\tfmt.Fprintf(w, \"%.2f w\\n\", c.width)\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_oval.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentOval struct {\n\tpageHeight float64\n\tx1         float64\n\ty1         float64\n\tx2         float64\n\ty2         float64\n}\n\nfunc (c *cacheContentOval) write(w io.Writer, protection *PDFProtection) error {\n\n\th := c.pageHeight\n\tx1 := c.x1\n\ty1 := c.y1\n\tx2 := c.x2\n\ty2 := c.y2\n\n\tcp := 0.55228                              // Magnification of the control point\n\tv1 := [2]float64{x1 + (x2-x1)/2, h - y2}   // Vertex of the lower\n\tv2 := [2]float64{x2, h - (y1 + (y2-y1)/2)} // .. Right\n\tv3 := [2]float64{x1 + (x2-x1)/2, h - y1}   // .. Upper\n\tv4 := [2]float64{x1, h - (y1 + (y2-y1)/2)} // .. Left\n\n\tfmt.Fprintf(w, \"%0.2f %0.2f m\\n\", v1[0], v1[1])\n\tfmt.Fprintf(w,\n\t\t\"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c\\n\",\n\t\tv1[0]+(x2-x1)/2*cp, v1[1], v2[0], v2[1]-(y2-y1)/2*cp, v2[0], v2[1],\n\t)\n\tfmt.Fprintf(w,\n\t\t\"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c\\n\",\n\t\tv2[0], v2[1]+(y2-y1)/2*cp, v3[0]+(x2-x1)/2*cp, v3[1], v3[0], v3[1],\n\t)\n\tfmt.Fprintf(w,\n\t\t\"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c\\n\",\n\t\tv3[0]-(x2-x1)/2*cp, v3[1], v4[0], v4[1]+(y2-y1)/2*cp, v4[0], v4[1],\n\t)\n\tfmt.Fprintf(w,\n\t\t\"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c S\\n\",\n\t\tv4[0], v4[1]-(y2-y1)/2*cp, v1[0]-(x2-x1)/2*cp, v1[1], v1[0], v1[1],\n\t)\n\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_polygon.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentPolygon struct {\n\tpageHeight float64\n\tstyle      string\n\tpoints     []Point\n}\n\nfunc (c *cacheContentPolygon) write(w io.Writer, protection *PDFProtection) error {\n\n\tfor i, point := range c.points {\n\t\tfmt.Fprintf(w, \"%.2f %.2f\", point.X, c.pageHeight-point.Y)\n\t\tif i == 0 {\n\t\t\tfmt.Fprintf(w, \" m \")\n\t\t} else {\n\t\t\tfmt.Fprintf(w, \" l \")\n\t\t}\n\n\t}\n\n\tif c.style == \"F\" {\n\t\tfmt.Fprintf(w, \" f\\n\")\n\t} else if c.style == \"FD\" || c.style == \"DF\" {\n\t\tfmt.Fprintf(w, \" b\\n\")\n\t} else {\n\t\tfmt.Fprintf(w, \" s\\n\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_rectangle.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentRectangle struct {\n\tpageHeight       float64\n\tx                float64\n\ty                float64\n\twidth            float64\n\theight           float64\n\tstyle            PaintStyle\n\textGStateIndexes []int\n}\n\nfunc NewCacheContentRectangle(pageHeight float64, rectOpts DrawableRectOptions) ICacheContent {\n\tif rectOpts.PaintStyle == \"\" {\n\t\trectOpts.PaintStyle = DrawPaintStyle\n\t}\n\n\treturn cacheContentRectangle{\n\t\tx:                rectOpts.X,\n\t\ty:                rectOpts.Y,\n\t\twidth:            rectOpts.W,\n\t\theight:           rectOpts.H,\n\t\tpageHeight:       pageHeight,\n\t\tstyle:            rectOpts.PaintStyle,\n\t\textGStateIndexes: rectOpts.extGStateIndexes,\n\t}\n}\n\nfunc (c cacheContentRectangle) write(w io.Writer, protection *PDFProtection) error {\n\tstream := \"q\\n\"\n\n\tfor _, extGStateIndex := range c.extGStateIndexes {\n\t\tstream += fmt.Sprintf(\"/GS%d gs\\n\", extGStateIndex)\n\t}\n\n\tstream += 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)\n\n\tstream += \"Q\\n\"\n\n\tif _, err := io.WriteString(w, stream); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_rotate.go",
    "content": "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\tangle, x, y float64\n}\n\nfunc (cc *cacheContentRotate) write(w io.Writer, protection *PDFProtection) error {\n\tif cc.isReset == true {\n\t\tfmt.Fprintf(w, \"Q\\n\")\n\t\treturn nil\n\t}\n\tangle := (cc.angle * 22.0) / (180.0 * 7.0)\n\tc := math.Cos(angle)\n\ts := math.Sin(angle)\n\tcy := cc.pageHeight - cc.y\n\n\tfmt.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)\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_content_text.go",
    "content": "package gopdf\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n)\n\n//ContentTypeCell cell\nconst ContentTypeCell = 0\n\n//ContentTypeText text\nconst ContentTypeText = 1\n\ntype cacheContentText struct {\n\t//---setup---\n\trectangle      *Rect\n\ttextColor      Rgb\n\tgrayFill       float64\n\ttxtColorMode   string\n\tfontCountIndex int //Curr.FontFontCount+1\n\tfontSize       int\n\tfontStyle      int\n\tsetXCount      int //จำนวนครั้งที่ใช้ setX\n\tx, y           float64\n\tfontSubset     *SubsetFontObj\n\tpageheight     float64\n\tcontentType    int\n\tcellOpt        CellOption\n\tlineWidth      float64\n\ttext           string\n\t//---result---\n\tcellWidthPdfUnit, textWidthPdfUnit float64\n\tcellHeightPdfUnit                  float64\n}\n\nfunc (c *cacheContentText) isSame(cache cacheContentText) bool {\n\tif c.rectangle != nil {\n\t\t//if rectangle != nil we assumes this is not same content\n\t\treturn false\n\t}\n\tif c.textColor.equal(cache.textColor) &&\n\t\tc.grayFill == cache.grayFill &&\n\t\tc.fontCountIndex == cache.fontCountIndex &&\n\t\tc.fontSize == cache.fontSize &&\n\t\tc.fontStyle == cache.fontStyle &&\n\t\tc.setXCount == cache.setXCount &&\n\t\tc.y == cache.y {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\nfunc (c *cacheContentText) setPageHeight(pageheight float64) {\n\tc.pageheight = pageheight\n}\n\nfunc (c *cacheContentText) pageHeight() float64 {\n\treturn c.pageheight //841.89\n}\n\nfunc convertTypoUnit(val float64, unitsPerEm uint, fontSize float64) float64 {\n\tval = val * 1000.00 / float64(unitsPerEm)\n\treturn val * fontSize / 1000.0\n}\n\nfunc (c *cacheContentText) calTypoAscender() float64 {\n\treturn convertTypoUnit(float64(c.fontSubset.ttfp.TypoAscender()), c.fontSubset.ttfp.UnitsPerEm(), float64(c.fontSize))\n}\n\nfunc (c *cacheContentText) calTypoDescender() float64 {\n\treturn convertTypoUnit(float64(c.fontSubset.ttfp.TypoDescender()), c.fontSubset.ttfp.UnitsPerEm(), float64(c.fontSize))\n}\n\nfunc (c *cacheContentText) calY() (float64, error) {\n\tpageHeight := c.pageHeight()\n\tif c.contentType == ContentTypeText {\n\t\treturn pageHeight - c.y, nil\n\t} else if c.contentType == ContentTypeCell {\n\t\ty := float64(0.0)\n\t\tif c.cellOpt.Align&Bottom == Bottom {\n\t\t\ty = pageHeight - c.y - c.cellHeightPdfUnit - c.calTypoDescender()\n\t\t} else if c.cellOpt.Align&Middle == Middle {\n\t\t\ty = pageHeight - c.y - c.cellHeightPdfUnit*0.5 - (c.calTypoDescender()+c.calTypoAscender())*0.5\n\t\t} else {\n\t\t\t//top\n\t\t\ty = pageHeight - c.y - c.calTypoAscender()\n\t\t}\n\n\t\treturn y, nil\n\t}\n\treturn 0.0, errors.New(\"contentType not found\")\n}\n\nfunc (c *cacheContentText) calX() (float64, error) {\n\tif c.contentType == ContentTypeText {\n\t\treturn c.x, nil\n\t} else if c.contentType == ContentTypeCell {\n\t\tx := float64(0.0)\n\t\tif c.cellOpt.Align&Right == Right {\n\t\t\tx = c.x + c.cellWidthPdfUnit - c.textWidthPdfUnit\n\t\t} else if c.cellOpt.Align&Center == Center {\n\t\t\tx = c.x + c.cellWidthPdfUnit*0.5 - c.textWidthPdfUnit*0.5\n\t\t} else {\n\t\t\tx = c.x\n\t\t}\n\t\treturn x, nil\n\t}\n\treturn 0.0, errors.New(\"contentType not found\")\n}\n\nfunc (c *cacheContentText) write(w io.Writer, protection *PDFProtection) error {\n\tr := c.textColor.r\n\tg := c.textColor.g\n\tb := c.textColor.b\n\tx, err := c.calX()\n\tif err != nil {\n\t\treturn err\n\t}\n\ty, err := c.calY()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, extGStateIndex := range c.cellOpt.extGStateIndexes {\n\t\tlinkToGSObj := fmt.Sprintf(\"/GS%d gs\\n\", extGStateIndex)\n\t\tif _, err := io.WriteString(w, linkToGSObj); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif _, err := io.WriteString(w, \"BT\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\tfmt.Fprintf(w, \"%0.2f %0.2f TD\\n\", x, y)\n\tfmt.Fprintf(w, \"/F%d %d Tf\\n\", c.fontCountIndex, c.fontSize)\n\tif c.txtColorMode == \"color\" {\n\t\tfmt.Fprintf(w, \"%0.3f %0.3f %0.3f rg\\n\", float64(r)/255, float64(g)/255, float64(b)/255)\n\t}\n\tio.WriteString(w, \"[<\")\n\n\tunitsPerEm := int(c.fontSubset.ttfp.UnitsPerEm())\n\tvar leftRune rune\n\tvar leftRuneIndex uint\n\tfor i, r := range c.text {\n\n\t\tglyphindex, err := c.fontSubset.CharIndex(r)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tpairvalPdfUnit := 0\n\t\tif i > 0 && c.fontSubset.ttfFontOption.UseKerning { //kerning\n\t\t\tpairval := kern(c.fontSubset, leftRune, r, leftRuneIndex, glyphindex)\n\t\t\tpairvalPdfUnit = convertTTFUnit2PDFUnit(int(pairval), unitsPerEm)\n\t\t\tif pairvalPdfUnit != 0 {\n\t\t\t\tfmt.Fprintf(w, \">%d<\", (-1)*pairvalPdfUnit)\n\t\t\t}\n\t\t}\n\n\t\tfmt.Fprintf(w, \"%04X\", glyphindex)\n\t\tleftRune = r\n\t\tleftRuneIndex = glyphindex\n\t}\n\n\tio.WriteString(w, \">] TJ\\n\")\n\tio.WriteString(w, \"ET\\n\")\n\n\tif c.fontStyle&Underline == Underline {\n\t\terr := c.underline(w, c.x, c.y, c.x+c.cellWidthPdfUnit, c.y)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tc.drawBorder(w)\n\n\treturn nil\n}\n\nfunc (c *cacheContentText) drawBorder(w io.Writer) error {\n\n\t//stream.WriteString(fmt.Sprintf(\"%.2f w\\n\", 0.1))\n\tlineOffset := c.lineWidth * 0.5\n\n\tif c.cellOpt.Border&Top == Top {\n\n\t\tstartX := c.x - lineOffset\n\t\tstartY := c.pageHeight() - c.y\n\t\tendX := c.x + c.cellWidthPdfUnit + lineOffset\n\t\tendY := startY\n\t\t_, err := fmt.Fprintf(w, \"%0.2f %0.2f m %0.2f %0.2f l s\\n\", startX, startY, endX, endY)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif c.cellOpt.Border&Left == Left {\n\t\tstartX := c.x\n\t\tstartY := c.pageHeight() - c.y\n\t\tendX := c.x\n\t\tendY := startY - c.cellHeightPdfUnit\n\t\t_, err := fmt.Fprintf(w, \"%0.2f %0.2f m %0.2f %0.2f l s\\n\", startX, startY, endX, endY)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif c.cellOpt.Border&Right == Right {\n\t\tstartX := c.x + c.cellWidthPdfUnit\n\t\tstartY := c.pageHeight() - c.y\n\t\tendX := c.x + c.cellWidthPdfUnit\n\t\tendY := startY - c.cellHeightPdfUnit\n\t\t_, err := fmt.Fprintf(w, \"%0.2f %0.2f m %0.2f %0.2f l s\\n\", startX, startY, endX, endY)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif c.cellOpt.Border&Bottom == Bottom {\n\t\tstartX := c.x - lineOffset\n\t\tstartY := c.pageHeight() - c.y - c.cellHeightPdfUnit\n\t\tendX := c.x + c.cellWidthPdfUnit + lineOffset\n\t\tendY := startY\n\t\t_, err := fmt.Fprintf(w, \"%0.2f %0.2f m %0.2f %0.2f l s\\n\", startX, startY, endX, endY)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (c *cacheContentText) underline(w io.Writer, startX float64, startY float64, endX float64, endY float64) error {\n\n\tif c.fontSubset == nil {\n\t\treturn errors.New(\"error AppendUnderline not found font\")\n\t}\n\tunitsPerEm := float64(c.fontSubset.ttfp.UnitsPerEm())\n\th := c.pageHeight()\n\tut := float64(c.fontSubset.GetUt())\n\tup := float64(c.fontSubset.GetUp())\n\ttextH := ContentObjCalTextHeight(c.fontSize)\n\targ3 := float64(h) - (float64(startY) - ((up / unitsPerEm) * float64(c.fontSize))) - textH\n\targ4 := (ut / unitsPerEm) * float64(c.fontSize)\n\tfmt.Fprintf(w, \"%0.2f %0.2f %0.2f -%0.2f re f\\n\", startX, arg3, endX-startX, arg4)\n\t//fmt.Printf(\"arg3=%f arg4=%f\\n\", arg3, arg4)\n\n\treturn nil\n}\n\nfunc (c *cacheContentText) createContent() (float64, float64, error) {\n\n\tcellWidthPdfUnit, cellHeightPdfUnit, textWidthPdfUnit, err := createContent(c.fontSubset, c.text, c.fontSize, c.rectangle)\n\tif err != nil {\n\t\treturn 0, 0, err\n\t}\n\tc.cellWidthPdfUnit = cellWidthPdfUnit\n\tc.cellHeightPdfUnit = cellHeightPdfUnit\n\tc.textWidthPdfUnit = textWidthPdfUnit\n\treturn cellWidthPdfUnit, cellHeightPdfUnit, nil\n}\n\nfunc createContent(f *SubsetFontObj, text string, fontSize int, rectangle *Rect) (float64, float64, float64, error) {\n\n\tunitsPerEm := int(f.ttfp.UnitsPerEm())\n\tvar leftRune rune\n\tvar leftRuneIndex uint\n\tsumWidth := int(0)\n\t//fmt.Printf(\"unitsPerEm = %d\", unitsPerEm)\n\tfor i, r := range text {\n\n\t\tglyphindex, err := f.CharIndex(r)\n\t\tif err != nil {\n\t\t\treturn 0, 0, 0, err\n\t\t}\n\n\t\tpairvalPdfUnit := 0\n\t\tif i > 0 && f.ttfFontOption.UseKerning { //kerning\n\t\t\tpairval := kern(f, leftRune, r, leftRuneIndex, glyphindex)\n\t\t\tpairvalPdfUnit = convertTTFUnit2PDFUnit(int(pairval), unitsPerEm)\n\t\t}\n\n\t\twidth, err := f.CharWidth(r)\n\t\tif err != nil {\n\t\t\treturn 0, 0, 0, err\n\t\t}\n\n\t\tsumWidth += int(width) + int(pairvalPdfUnit)\n\t\tleftRune = r\n\t\tleftRuneIndex = glyphindex\n\t}\n\n\tcellWidthPdfUnit := float64(0)\n\tcellHeightPdfUnit := float64(0)\n\tif rectangle == nil {\n\t\tcellWidthPdfUnit = float64(sumWidth) * (float64(fontSize) / 1000.0)\n\t\ttypoAscender := convertTypoUnit(float64(f.ttfp.TypoAscender()), f.ttfp.UnitsPerEm(), float64(fontSize))\n\t\ttypoDescender := convertTypoUnit(float64(f.ttfp.TypoDescender()), f.ttfp.UnitsPerEm(), float64(fontSize))\n\t\tcellHeightPdfUnit = typoAscender - typoDescender\n\t} else {\n\t\tcellWidthPdfUnit = rectangle.W\n\t\tcellHeightPdfUnit = rectangle.H\n\t}\n\ttextWidthPdfUnit := float64(sumWidth) * (float64(fontSize) / 1000.0)\n\treturn cellWidthPdfUnit, cellHeightPdfUnit, textWidthPdfUnit, nil\n}\n\nfunc kern(f *SubsetFontObj, leftRune rune, rightRune rune, leftIndex uint, rightIndex uint) int16 {\n\n\tpairVal := int16(0)\n\tif haveKerning, kval := f.KernValueByLeft(leftIndex); haveKerning {\n\t\tif ok, v := kval.ValueByRight(rightIndex); ok {\n\t\t\tpairVal = v\n\t\t}\n\t}\n\n\tif f.funcKernOverride != nil {\n\t\tpairVal = f.funcKernOverride(\n\t\t\tleftRune,\n\t\t\trightRune,\n\t\t\tleftIndex,\n\t\t\trightIndex,\n\t\t\tpairVal,\n\t\t)\n\t}\n\treturn pairVal\n}\n\n//CacheContent Export cacheContent\ntype CacheContent struct {\n\tcacheContentText\n}\n\n//Setup setup all information for cacheContent\nfunc (c *CacheContent) Setup(rectangle *Rect,\n\ttextColor Rgb,\n\tgrayFill float64,\n\tfontCountIndex int, //Curr.FontFontCount+1\n\tfontSize int,\n\tfontStyle int,\n\tsetXCount int, //จำนวนครั้งที่ใช้ setX\n\tx, y float64,\n\tfontSubset *SubsetFontObj,\n\tpageheight float64,\n\tcontentType int,\n\tcellOpt CellOption,\n\tlineWidth float64,\n) {\n\tc.cacheContentText = cacheContentText{\n\t\tfontSubset:     fontSubset,\n\t\trectangle:      rectangle,\n\t\ttextColor:      textColor,\n\t\tgrayFill:       grayFill,\n\t\tfontCountIndex: fontCountIndex,\n\t\tfontSize:       fontSize,\n\t\tfontStyle:      fontStyle,\n\t\tsetXCount:      setXCount,\n\t\tx:              x,\n\t\ty:              y,\n\t\tpageheight:     pageheight,\n\t\tcontentType:    ContentTypeCell,\n\t\tcellOpt:        cellOpt,\n\t\tlineWidth:      lineWidth,\n\t}\n}\n\n//WriteTextToContent write text to content\nfunc (c *CacheContent) WriteTextToContent(text string) {\n\tc.cacheContentText.text += text\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cache_contnent_curve.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype cacheContentCurve struct {\n\tpageHeight float64\n\tx0         float64\n\ty0         float64\n\tx1         float64\n\ty1         float64\n\tx2         float64\n\ty2         float64\n\tx3         float64\n\ty3         float64\n\tstyle      string\n}\n\nfunc (c *cacheContentCurve) write(w io.Writer, protection *PDFProtection) error {\n\n\th := c.pageHeight\n\tx0 := c.x0\n\ty0 := c.y0\n\tx1 := c.x1\n\ty1 := c.y1\n\tx2 := c.x2\n\ty2 := c.y2\n\tx3 := c.x3\n\ty3 := c.y3\n\tstyle := c.style\n\n\t//cp := 0.55228\n\tfmt.Fprintf(w, \"%0.2f %0.2f m\\n\", x0, h-y0)\n\tfmt.Fprintf(w,\n\t\t\"%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f c\",\n\t\tx1, h-y1, x2, h-y2, x3, h-y3,\n\t)\n\top := \"S\"\n\tif style == \"F\" {\n\t\top = \"f\"\n\t} else if style == \"FD\" || style == \"DF\" {\n\t\top = \"B\"\n\t}\n\tfmt.Fprintf(w, \" %s\\n\", op)\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/catalog_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//CatalogObj : catalog dictionary\ntype CatalogObj struct { //impl IObj\n\toutlinesObjID int\n}\n\nfunc (c *CatalogObj) init(funcGetRoot func() *GoPdf) {\n\tc.outlinesObjID = -1\n\n}\n\nfunc (c *CatalogObj) getType() string {\n\treturn \"Catalog\"\n}\n\nfunc (c *CatalogObj) write(w io.Writer, objID int) error {\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"  /Type /%s\\n\", c.getType())\n\tio.WriteString(w, \"  /Pages 2 0 R\\n\")\n\tif c.outlinesObjID >= 0 {\n\t\tio.WriteString(w, \"  /PageMode /UseOutlines\\n\")\n\t\tfmt.Fprintf(w, \"  /Outlines %d 0 R\\n\", c.outlinesObjID)\n\t}\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\nfunc (c *CatalogObj) SetIndexObjOutlines(index int) {\n\tc.outlinesObjID = index + 1\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cell_option.go",
    "content": "package gopdf\n\n//Left left\nconst Left = 8 //001000\n//Top top\nconst Top = 4 //000100\n//Right right\nconst Right = 2 //000010\n//Bottom bottom\nconst Bottom = 1 //000001\n//Center center\nconst Center = 16 //010000\n//Middle middle\nconst Middle = 32 //100000\n//AllBorders allborders\nconst AllBorders = 15 //001111\n\n//CellOption cell option\ntype CellOption struct {\n\tAlign        int //Allows to align the text. Possible values are: Left,Center,Right,Top,Bottom,Middle\n\tBorder       int //Indicates if borders must be drawn around the cell. Possible values are: Left, Top, Right, Bottom, ALL\n\tFloat        int //Indicates where the current position should go after the call. Possible values are: Right, Bottom\n\tTransparency *Transparency\n\n\textGStateIndexes []int\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/cid_font_obj.go",
    "content": "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/en/devnet/font/pdfs/5014.CIDFont_Spec.pdf\ntype CIDFontObj struct {\n\tPtrToSubsetFontObj        *SubsetFontObj\n\tindexObjSubfontDescriptor int\n}\n\nfunc (ci *CIDFontObj) init(funcGetRoot func() *GoPdf) {\n}\n\n//SetIndexObjSubfontDescriptor set  indexObjSubfontDescriptor\nfunc (ci *CIDFontObj) SetIndexObjSubfontDescriptor(index int) {\n\tci.indexObjSubfontDescriptor = index\n}\n\nfunc (ci *CIDFontObj) getType() string {\n\treturn \"CIDFont\"\n}\n\nfunc (ci *CIDFontObj) write(w io.Writer, objID int) error {\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"/BaseFont /%s\\n\", CreateEmbeddedFontSubsetName(ci.PtrToSubsetFontObj.GetFamily()))\n\tio.WriteString(w, \"/CIDSystemInfo\\n\")\n\tio.WriteString(w, \"<<\\n\")\n\tio.WriteString(w, \"  /Ordering (Identity)\\n\")\n\tio.WriteString(w, \"  /Registry (Adobe)\\n\")\n\tio.WriteString(w, \"  /Supplement 0\\n\")\n\tio.WriteString(w, \">>\\n\")\n\tfmt.Fprintf(w, \"/FontDescriptor %d 0 R\\n\", ci.indexObjSubfontDescriptor+1) //TODO fix\n\tio.WriteString(w, \"/Subtype /CIDFontType2\\n\")\n\tio.WriteString(w, \"/Type /Font\\n\")\n\tglyphIndexs := ci.PtrToSubsetFontObj.CharacterToGlyphIndex.AllVals()\n\tio.WriteString(w, \"/W [\")\n\tfor _, v := range glyphIndexs {\n\t\twidth := ci.PtrToSubsetFontObj.GlyphIndexToPdfWidth(v)\n\t\tfmt.Fprintf(w, \"%d[%d]\", v, width)\n\t}\n\tio.WriteString(w, \"]\\n\")\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\n//SetPtrToSubsetFontObj set PtrToSubsetFontObj\nfunc (ci *CIDFontObj) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {\n\tci.PtrToSubsetFontObj = ptr\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/config.go",
    "content": "package gopdf\n\n// The units that can be used in the document\nconst (\n\tUnitUnset = iota // No units were set, when conversion is called on nothing will happen\n\tUnitPT           // Points\n\tUnitMM           // Millimeters\n\tUnitCM           // centimeters\n\tUnitIN           // inches\n\n\t// The math needed to convert units to points\n\tconversionUnitPT = 1.0\n\tconversionUnitMM = 72.0 / 25.4\n\tconversionUnitCM = 72.0 / 2.54\n\tconversionUnitIN = 72.0\n)\n\n// The units that can be used in the document (for backward compatibility)\n// Deprecated: Use UnitUnset,UnitPT,UnitMM,UnitCM,UnitIN  instead\nconst (\n\tUnit_Unset = UnitUnset // No units were set, when conversion is called on nothing will happen\n\tUnit_PT    = UnitPT    // Points\n\tUnit_MM    = UnitMM    // Millimeters\n\tUnit_CM    = UnitCM    // centimeters\n\tUnit_IN    = UnitIN    // inches\n)\n\n//Config static config\ntype Config struct {\n\tUnit       int                 // The unit type to use when composing the document.\n\tTrimBox    Box                 // The default trim box for all pages in the document\n\tPageSize   Rect                // The default page size for all pages in the document\n\tK          float64             // Not sure\n\tProtection PDFProtectionConfig // Protection settings\n}\n\n//PDFProtectionConfig config of pdf protection\ntype PDFProtectionConfig struct {\n\tUseProtection bool\n\tPermissions   int\n\tUserPass      []byte\n\tOwnerPass     []byte\n}\n\n// UnitsToPoints converts units of the provided type to points\nfunc UnitsToPoints(t int, u float64) float64 {\n\tswitch t {\n\tcase UnitPT:\n\t\treturn u * conversionUnitPT\n\tcase UnitMM:\n\t\treturn u * conversionUnitMM\n\tcase UnitCM:\n\t\treturn u * conversionUnitCM\n\tcase UnitIN:\n\t\treturn u * conversionUnitIN\n\tdefault:\n\t\treturn u\n\t}\n}\n\n// PointsToUnits converts points to the provided units\nfunc PointsToUnits(t int, u float64) float64 {\n\tswitch t {\n\tcase UnitPT:\n\t\treturn u / conversionUnitPT\n\tcase UnitMM:\n\t\treturn u / conversionUnitMM\n\tcase UnitCM:\n\t\treturn u / conversionUnitCM\n\tcase UnitIN:\n\t\treturn u / conversionUnitIN\n\tdefault:\n\t\treturn u\n\t}\n}\n\n// UnitsToPointsVar converts units of the provided type to points for all variables supplied\nfunc UnitsToPointsVar(t int, u ...*float64) {\n\tfor x := 0; x < len(u); x++ {\n\t\t*u[x] = UnitsToPoints(t, *u[x])\n\t}\n}\n\n// PointsToUnitsVar converts points to the provided units for all variables supplied\nfunc PointsToUnitsVar(t int, u ...*float64) {\n\tfor x := 0; x < len(u); x++ {\n\t\t*u[x] = PointsToUnits(t, *u[x])\n\t}\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/content_obj.go",
    "content": "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 { //impl IObj\n\tlistCache listCacheContent\n\t//text bytes.Buffer\n\tgetRoot func() *GoPdf\n}\n\nfunc (c *ContentObj) protection() *PDFProtection {\n\treturn c.getRoot().protection()\n}\n\nfunc (c *ContentObj) init(funcGetRoot func() *GoPdf) {\n\tc.getRoot = funcGetRoot\n}\n\nfunc (c *ContentObj) write(w io.Writer, objID int) error {\n\tbuff := GetBuffer()\n\tdefer PutBuffer(buff)\n\n\tisFlate := (c.getRoot().compressLevel != zlib.NoCompression)\n\tif isFlate {\n\t\tww, err := zlib.NewWriterLevel(buff, c.getRoot().compressLevel)\n\t\tif err != nil {\n\t\t\t// should never happen...\n\t\t\treturn err\n\t\t}\n\t\tif err := c.listCache.write(ww, c.protection()); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := ww.Close(); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif err := c.listCache.write(buff, c.protection()); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif _, err := io.WriteString(w, \"<<\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\tif isFlate {\n\t\tif _, err := io.WriteString(w, \"/Filter/FlateDecode\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif _, err := fmt.Fprintf(w, \"/Length %d\\n\", buff.Len()); err != nil {\n\t\treturn err\n\t}\n\tif _, err := io.WriteString(w, \">>\\n\"); err != nil {\n\t\treturn err\n\t}\n\tif _, err := io.WriteString(w, \"stream\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\tif c.protection() != nil {\n\t\ttmp, err := rc4Cip(c.protection().objectkey(objID), buff.Bytes())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif _, err := w.Write(tmp); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err := io.WriteString(w, \"\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif _, err := buff.WriteTo(w); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif isFlate {\n\t\t\tif _, err := io.WriteString(w, \"\\n\"); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tif _, err := io.WriteString(w, \"endstream\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (c *ContentObj) getType() string {\n\treturn \"Content\"\n}\n\n//AppendStreamText append text\nfunc (c *ContentObj) AppendStreamText(text string) error {\n\n\t//support only CURRENT_FONT_TYPE_SUBSET\n\ttextColor := c.getRoot().curr.textColor()\n\tgrayFill := c.getRoot().curr.grayFill\n\tfontCountIndex := c.getRoot().curr.FontFontCount + 1\n\tfontSize := c.getRoot().curr.FontSize\n\tfontStyle := c.getRoot().curr.FontStyle\n\tx := c.getRoot().curr.X\n\ty := c.getRoot().curr.Y\n\tsetXCount := c.getRoot().curr.setXCount\n\tfontSubset := c.getRoot().curr.FontISubset\n\n\tcellOption := CellOption{Transparency: c.getRoot().curr.transparency}\n\n\tcache := cacheContentText{\n\t\tfontSubset:     fontSubset,\n\t\trectangle:      nil,\n\t\ttextColor:      textColor,\n\t\tgrayFill:       grayFill,\n\t\tfontCountIndex: fontCountIndex,\n\t\tfontSize:       fontSize,\n\t\tfontStyle:      fontStyle,\n\t\tsetXCount:      setXCount,\n\t\tx:              x,\n\t\ty:              y,\n\t\tcellOpt:        cellOption,\n\t\tpageheight:     c.getRoot().curr.pageSize.H,\n\t\tcontentType:    ContentTypeText,\n\t\tlineWidth:      c.getRoot().curr.lineWidth,\n\t\ttxtColorMode:   c.getRoot().curr.txtColorMode,\n\t}\n\n\tvar err error\n\tc.getRoot().curr.X, c.getRoot().curr.Y, err = c.listCache.appendContentText(cache, text)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n//AppendStreamSubsetFont add stream of text\nfunc (c *ContentObj) AppendStreamSubsetFont(rectangle *Rect, text string, cellOpt CellOption) error {\n\n\ttextColor := c.getRoot().curr.textColor()\n\tgrayFill := c.getRoot().curr.grayFill\n\tfontCountIndex := c.getRoot().curr.FontFontCount + 1\n\tfontSize := c.getRoot().curr.FontSize\n\tfontStyle := c.getRoot().curr.FontStyle\n\tx := c.getRoot().curr.X\n\ty := c.getRoot().curr.Y\n\tsetXCount := c.getRoot().curr.setXCount\n\tfontSubset := c.getRoot().curr.FontISubset\n\n\tcache := cacheContentText{\n\t\tfontSubset:     fontSubset,\n\t\trectangle:      rectangle,\n\t\ttextColor:      textColor,\n\t\tgrayFill:       grayFill,\n\t\tfontCountIndex: fontCountIndex,\n\t\tfontSize:       fontSize,\n\t\tfontStyle:      fontStyle,\n\t\tsetXCount:      setXCount,\n\t\tx:              x,\n\t\ty:              y,\n\t\tpageheight:     c.getRoot().curr.pageSize.H,\n\t\tcontentType:    ContentTypeCell,\n\t\tcellOpt:        cellOpt,\n\t\tlineWidth:      c.getRoot().curr.lineWidth,\n\t\ttxtColorMode:   c.getRoot().curr.txtColorMode,\n\t}\n\tvar err error\n\tc.getRoot().curr.X, c.getRoot().curr.Y, err = c.listCache.appendContentText(cache, text)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//AppendStreamLine append line\nfunc (c *ContentObj) AppendStreamLine(x1 float64, y1 float64, x2 float64, y2 float64) {\n\t//h := c.getRoot().config.PageSize.H\n\t//c.stream.WriteString(fmt.Sprintf(\"%0.2f %0.2f m %0.2f %0.2f l s\\n\", x1, h-y1, x2, h-y2))\n\tvar cache cacheContentLine\n\tcache.pageHeight = c.getRoot().curr.pageSize.H\n\tcache.x1 = x1\n\tcache.y1 = y1\n\tcache.x2 = x2\n\tcache.y2 = y2\n\tc.listCache.append(&cache)\n}\n\n//AppendStreamImportedTemplate append imported template\nfunc (c *ContentObj) AppendStreamImportedTemplate(tplName string, scaleX float64, scaleY float64, tX float64, tY float64) {\n\tvar cache cacheContentImportedTemplate\n\tcache.pageHeight = c.getRoot().curr.pageSize.H\n\tcache.tplName = tplName\n\tcache.scaleX = scaleX\n\tcache.scaleY = scaleY\n\tcache.tX = tX\n\tcache.tY = tY\n\tc.listCache.append(&cache)\n}\n\nfunc (c *ContentObj) AppendStreamRectangle(opts DrawableRectOptions) {\n\tcache := NewCacheContentRectangle(c.getRoot().curr.pageSize.H, opts)\n\tc.listCache.append(cache)\n}\n\n//AppendStreamOval append oval\nfunc (c *ContentObj) AppendStreamOval(x1 float64, y1 float64, x2 float64, y2 float64) {\n\tvar cache cacheContentOval\n\tcache.pageHeight = c.getRoot().curr.pageSize.H\n\tcache.x1 = x1\n\tcache.y1 = y1\n\tcache.x2 = x2\n\tcache.y2 = y2\n\tc.listCache.append(&cache)\n}\n\n//AppendStreamCurve draw curve\n// - x0, y0: Start point\n// - x1, y1: Control point 1\n// - x2, y2: Control point 2\n// - x3, y3: End point\n// - style: Style of rectangule (draw and/or fill: D, F, DF, FD)\n//\t\tD or empty string: draw. This is the default value.\n//\t\tF: fill\n//\t\tDF or FD: draw and fill\nfunc (c *ContentObj) AppendStreamCurve(x0 float64, y0 float64, x1 float64, y1 float64, x2 float64, y2 float64, x3 float64, y3 float64, style string) {\n\tvar cache cacheContentCurve\n\tcache.pageHeight = c.getRoot().curr.pageSize.H\n\tcache.x0 = x0\n\tcache.y0 = y0\n\tcache.x1 = x1\n\tcache.y1 = y1\n\tcache.x2 = x2\n\tcache.y2 = y2\n\tcache.x3 = x3\n\tcache.y3 = y3\n\tcache.style = strings.ToUpper(strings.TrimSpace(style))\n\tc.listCache.append(&cache)\n}\n\n//AppendStreamSetLineWidth : set line width\nfunc (c *ContentObj) AppendStreamSetLineWidth(w float64) {\n\tvar cache cacheContentLineWidth\n\tcache.width = w\n\tc.listCache.append(&cache)\n}\n\n//AppendStreamSetLineType : Set linetype [solid, dashed, dotted]\nfunc (c *ContentObj) AppendStreamSetLineType(t string) {\n\tvar cache cacheContentLineType\n\tcache.lineType = t\n\tc.listCache.append(&cache)\n\n}\n\n//AppendStreamSetGrayFill  set the grayscale fills\nfunc (c *ContentObj) AppendStreamSetGrayFill(w float64) {\n\tw = fixRange10(w)\n\tvar cache cacheContentGray\n\tcache.grayType = grayTypeFill\n\tcache.scale = w\n\tc.listCache.append(&cache)\n}\n\n//AppendStreamSetGrayStroke  set the grayscale stroke\nfunc (c *ContentObj) AppendStreamSetGrayStroke(w float64) {\n\tw = fixRange10(w)\n\tvar cache cacheContentGray\n\tcache.grayType = grayTypeStroke\n\tcache.scale = w\n\tc.listCache.append(&cache)\n}\n\n//AppendStreamSetColorStroke  set the color stroke\nfunc (c *ContentObj) AppendStreamSetColorStroke(r uint8, g uint8, b uint8) {\n\tvar cache cacheContentColor\n\tcache.colorType = colorTypeStroke\n\tcache.r = r\n\tcache.g = g\n\tcache.b = b\n\tc.listCache.append(&cache)\n}\n\n//AppendStreamSetColorFill  set the color fill\nfunc (c *ContentObj) AppendStreamSetColorFill(r uint8, g uint8, b uint8) {\n\tvar cache cacheContentColor\n\tcache.colorType = colorTypeFill\n\tcache.r = r\n\tcache.g = g\n\tcache.b = b\n\tc.listCache.append(&cache)\n}\n\nfunc (c *ContentObj) GetCacheContentImage(index int, opts ImageOptions) *cacheContentImage {\n\th := c.getRoot().curr.pageSize.H\n\n\treturn &cacheContentImage{\n\t\tpageHeight:       h,\n\t\tindex:            index,\n\t\tx:                opts.X,\n\t\ty:                opts.Y,\n\t\trect:             *opts.Rect,\n\t\tcrop:             opts.Crop,\n\t\tverticalFlip:     opts.VerticalFlip,\n\t\thorizontalFlip:   opts.HorizontalFlip,\n\t\textGStateIndexes: opts.extGStateIndexes,\n\t}\n}\n\n//AppendStreamImage append image\nfunc (c *ContentObj) AppendStreamImage(index int, opts ImageOptions) {\n\tcache := c.GetCacheContentImage(index, opts)\n\tc.listCache.append(cache)\n}\n\n//AppendStreamPolygon append polygon\nfunc (c *ContentObj) AppendStreamPolygon(points []Point, style string) {\n\tvar cache cacheContentPolygon\n\tcache.points = points\n\tcache.style = style\n\tcache.pageHeight = c.getRoot().curr.pageSize.H\n\tc.listCache.append(&cache)\n}\n\nfunc (c *ContentObj) appendRotate(angle, x, y float64) {\n\tvar cache cacheContentRotate\n\tcache.isReset = false\n\tcache.pageHeight = c.getRoot().curr.pageSize.H\n\tcache.angle = angle\n\tcache.x = x\n\tcache.y = y\n\tc.listCache.append(&cache)\n}\n\nfunc (c *ContentObj) appendRotateReset() {\n\tvar cache cacheContentRotate\n\tcache.isReset = true\n\tc.listCache.append(&cache)\n}\n\n//ContentObjCalTextHeight calculates height of text.\nfunc ContentObjCalTextHeight(fontsize int) float64 {\n\treturn (float64(fontsize) * 0.7)\n}\n\n// When setting colour and grayscales the value has to be between 0.00 and 1.00\n// This function takes a float64 and returns 0.0 if it is less than 0.0 and 1.0 if it\n// is more than 1.0\nfunc fixRange10(val float64) float64 {\n\tif val < 0.0 {\n\t\treturn 0.0\n\t}\n\tif val > 1.0 {\n\t\treturn 1.0\n\t}\n\treturn val\n}\n\nfunc convertTTFUnit2PDFUnit(n int, upem int) int {\n\tvar ret int\n\tif n < 0 {\n\t\trest1 := n % upem\n\t\tstorrest := 1000 * rest1\n\t\t//ledd2 := (storrest != 0 ? rest1 / storrest : 0);\n\t\tledd2 := 0\n\t\tif storrest != 0 {\n\t\t\tledd2 = rest1 / storrest\n\t\t} else {\n\t\t\tledd2 = 0\n\t\t}\n\t\tret = -((-1000*n)/upem - int(ledd2))\n\t} else {\n\t\tret = (n/upem)*1000 + ((n%upem)*1000)/upem\n\t}\n\treturn ret\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/current.go",
    "content": "package gopdf\n\n//Current current state\ntype Current struct {\n\tsetXCount int //many times we go func SetX()\n\tX         float64\n\tY         float64\n\n\t//font\n\tIndexOfFontObj int\n\tCountOfFont    int\n\tCountOfL       int\n\n\tFontSize      int\n\tFontStyle     int // Regular|Bold|Italic|Underline\n\tFontFontCount int\n\tFontType      int // CURRENT_FONT_TYPE_IFONT or  CURRENT_FONT_TYPE_SUBSET\n\n\tFontISubset *SubsetFontObj // FontType == CURRENT_FONT_TYPE_SUBSET\n\n\t//page\n\tIndexOfPageObj int\n\n\t//img\n\tCountOfImg int\n\t//cache of image in pdf file\n\tImgCaches map[int]ImageCache\n\n\t//text color mode\n\ttxtColorMode string //color, gray\n\n\t//text color\n\ttxtColor Rgb\n\n\t//text grayscale\n\tgrayFill float64\n\t//draw grayscale\n\tgrayStroke float64\n\n\tlineWidth float64\n\n\t//current page size\n\tpageSize *Rect\n\n\t//current trim box\n\ttrimBox *Box\n\n\tsMasksMap       SMaskMap\n\textGStatesMap   ExtGStatesMap\n\ttransparency    *Transparency\n\ttransparencyMap TransparencyMap\n}\n\nfunc (c *Current) setTextColor(rgb Rgb) {\n\tc.txtColor = rgb\n}\n\nfunc (c *Current) textColor() Rgb {\n\treturn c.txtColor\n}\n\n// ImageCache is metadata for caching images.\ntype ImageCache struct {\n\tPath  string //ID or Path\n\tIndex int\n\tRect  *Rect\n}\n\n//Rgb  rgb color\ntype Rgb struct {\n\tr uint8\n\tg uint8\n\tb uint8\n}\n\n//SetR set red\nfunc (rgb *Rgb) SetR(r uint8) {\n\trgb.r = r\n}\n\n//SetG set green\nfunc (rgb *Rgb) SetG(g uint8) {\n\trgb.g = g\n}\n\n//SetB set blue\nfunc (rgb *Rgb) SetB(b uint8) {\n\trgb.b = b\n}\n\nfunc (rgb Rgb) equal(obj Rgb) bool {\n\tif rgb.r == obj.r && rgb.g == obj.g && rgb.b == obj.b {\n\t\treturn true\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/device_rgb_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//DeviceRGBObj  DeviceRGB\ntype DeviceRGBObj struct {\n\tdata    []byte\n\tgetRoot func() *GoPdf\n}\n\nfunc (d *DeviceRGBObj) init(funcGetRoot func() *GoPdf) {\n\td.getRoot = funcGetRoot\n}\n\nfunc (d *DeviceRGBObj) protection() *PDFProtection {\n\treturn d.getRoot().protection()\n}\n\nfunc (d *DeviceRGBObj) getType() string {\n\treturn \"devicergb\"\n}\n\n//สร้าง ข้อมูลใน pdf\nfunc (d *DeviceRGBObj) write(w io.Writer, objID int) error {\n\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"/Length %d\\n\", len(d.data))\n\tio.WriteString(w, \">>\\n\")\n\tio.WriteString(w, \"stream\\n\")\n\tif d.protection() != nil {\n\t\ttmp, err := rc4Cip(d.protection().objectkey(objID), d.data)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tw.Write(tmp)\n\t\tio.WriteString(w, \"\\n\")\n\t} else {\n\t\tw.Write(d.data)\n\t}\n\tio.WriteString(w, \"endstream\\n\")\n\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/embedfont_obj.go",
    "content": "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 struct {\n\tData      string\n\tzfontpath string\n\tfont      IFont\n\tgetRoot   func() *GoPdf\n}\n\nfunc (e *EmbedFontObj) init(funcGetRoot func() *GoPdf) {\n\te.getRoot = funcGetRoot\n}\n\nfunc (e *EmbedFontObj) protection() *PDFProtection {\n\treturn e.getRoot().protection()\n}\n\nfunc (e *EmbedFontObj) write(w io.Writer, objID int) error {\n\tb, err := ioutil.ReadFile(e.zfontpath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfmt.Fprintf(w, \"<</Length %d\\n\", len(b))\n\tio.WriteString(w, \"/Filter /FlateDecode\\n\")\n\tfmt.Fprintf(w, \"/Length1 %d\\n\", e.font.GetOriginalsize())\n\tio.WriteString(w, \">>\\n\")\n\tio.WriteString(w, \"stream\\n\")\n\tif e.protection() != nil {\n\t\ttmp, err := rc4Cip(e.protection().objectkey(objID), b)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tw.Write(tmp)\n\t\tio.WriteString(w, \"\\n\")\n\t} else {\n\t\tw.Write(b)\n\t}\n\tio.WriteString(w, \"\\nendstream\\n\")\n\treturn nil\n}\n\nfunc (e *EmbedFontObj) getType() string {\n\treturn \"EmbedFont\"\n}\n\n// SetFont sets the font of an embedded font object.\nfunc (e *EmbedFontObj) SetFont(font IFont, zfontpath string) {\n\te.font = font\n\te.zfontpath = zfontpath\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/encoding_obj.go",
    "content": "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 *EncodingObj) init(funcGetRoot func() *GoPdf) {\n\n}\nfunc (e *EncodingObj) getType() string {\n\treturn \"Encoding\"\n}\nfunc (e *EncodingObj) write(w io.Writer, objID int) error {\n\tio.WriteString(w, \"<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [\")\n\tio.WriteString(w, e.font.GetDiff())\n\tio.WriteString(w, \"]>>\\n\")\n\treturn nil\n}\n\n// SetFont sets the font of an encoding object.\nfunc (e *EncodingObj) SetFont(font IFont) {\n\te.font = font\n}\n\n// GetFont gets the font from an encoding object.\nfunc (e *EncodingObj) GetFont() IFont {\n\treturn e.font\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/encryption_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n)\n\n//EncryptionObj  encryption object res\ntype EncryptionObj struct {\n\tuValue []byte //U entry in pdf document\n\toValue []byte //O entry in pdf document\n\tpValue int    //P entry in pdf document\n}\n\nfunc (e *EncryptionObj) init(func() *GoPdf) {\n\n}\n\nfunc (e *EncryptionObj) getType() string {\n\treturn \"Encryption\"\n}\n\nfunc (e *EncryptionObj) write(w io.Writer, objID int) error {\n\tio.WriteString(w, \"<<\\n\")\n\tio.WriteString(w, \"/Filter /Standard\\n\")\n\tio.WriteString(w, \"/V 1\\n\")\n\tio.WriteString(w, \"/R 2\\n\")\n\tfmt.Fprintf(w, \"/O (%s)\\n\", e.escape(e.oValue))\n\tfmt.Fprintf(w, \"/U (%s)\\n\", e.escape(e.uValue))\n\tfmt.Fprintf(w, \"/P %d\\n\", e.pValue)\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\nfunc (e *EncryptionObj) escape(b []byte) string {\n\ts := string(b)\n\ts = strings.Replace(s, \"\\\\\", \"\\\\\\\\\", -1)\n\ts = strings.Replace(s, \"(\", \"\\\\(\", -1)\n\ts = strings.Replace(s, \")\", \"\\\\)\", -1)\n\ts = strings.Replace(s, \"\\r\", \"\\\\r\", -1)\n\treturn s\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/ext_g_state_obj.go",
    "content": "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/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf 8.4.5 page 128\ntype ExtGState struct {\n\tIndex      int\n\tca         *float64\n\tCA         *float64\n\tBM         *BlendModeType\n\tSMaskIndex *int\n}\n\ntype ExtGStateOptions struct {\n\tStrokingCA    *float64\n\tNonStrokingCa *float64\n\tBlendMode     *BlendModeType\n\tSMaskIndex    *int\n}\n\nfunc (extOpt ExtGStateOptions) GetId() string {\n\tid := \"\"\n\tif extOpt.StrokingCA != nil {\n\t\tid += fmt.Sprintf(\"CA_%.3f;\", *extOpt.StrokingCA)\n\t}\n\tif extOpt.NonStrokingCa != nil {\n\t\tid += fmt.Sprintf(\"ca_%.3f;\", *extOpt.NonStrokingCa)\n\t}\n\tif extOpt.BlendMode != nil {\n\t\tid += fmt.Sprintf(\"BM_%s;\", *extOpt.BlendMode)\n\t}\n\tif extOpt.SMaskIndex != nil {\n\t\tid += fmt.Sprintf(\"SMask_%d_0_R;\", *extOpt.SMaskIndex)\n\t}\n\n\treturn id\n}\n\nfunc GetCachedExtGState(opts ExtGStateOptions, gp *GoPdf) (ExtGState, error) {\n\textGState, ok := gp.curr.extGStatesMap.Find(opts)\n\tif !ok {\n\t\textGState = ExtGState{\n\t\t\tBM:         opts.BlendMode,\n\t\t\tCA:         opts.StrokingCA,\n\t\t\tca:         opts.NonStrokingCa,\n\t\t\tSMaskIndex: opts.SMaskIndex,\n\t\t}\n\n\t\textGState.Index = gp.addObj(extGState)\n\n\t\tpdfObj := gp.pdfObjs[gp.indexOfProcSet]\n\t\tprocset, ok := pdfObj.(*ProcSetObj)\n\t\tif !ok {\n\t\t\treturn ExtGState{}, errors.New(\"can't convert pdfobject to procsetobj\")\n\t\t}\n\n\t\tprocset.ExtGStates = append(procset.ExtGStates, ExtGS{Index: extGState.Index})\n\n\t\tgp.curr.extGStatesMap.Save(opts.GetId(), extGState)\n\n\t\t//extGState = extGState\n\t}\n\n\treturn extGState, nil\n}\n\nfunc (egs ExtGState) init(func() *GoPdf) {}\n\nfunc (egs ExtGState) getType() string {\n\treturn \"ExtGState\"\n}\n\nfunc (egs ExtGState) write(w io.Writer, objID int) error {\n\tcontent := \"<<\\n\"\n\tcontent += \"\\t/Type /ExtGState\\n\"\n\n\tif egs.ca != nil {\n\t\tcontent += fmt.Sprintf(\"\\t/ca %.3F\\n\", *egs.ca)\n\t}\n\tif egs.CA != nil {\n\t\tcontent += fmt.Sprintf(\"\\t/CA %.3F\\n\", *egs.CA)\n\t}\n\tif egs.BM != nil {\n\t\tcontent += fmt.Sprintf(\"\\t/BM %s\\n\", *egs.BM)\n\t}\n\n\tif egs.SMaskIndex != nil {\n\t\tcontent += fmt.Sprintf(\"\\t/SMask %d 0 R\\n\", *egs.SMaskIndex+1)\n\t}\n\n\tcontent += \">>\\n\"\n\n\tif _, err := io.WriteString(w, content); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\ntype ExtGStatesMap struct {\n\tsyncer sync.Mutex\n\ttable  map[string]ExtGState\n}\n\nfunc NewExtGStatesMap() ExtGStatesMap {\n\treturn ExtGStatesMap{\n\t\tsyncer: sync.Mutex{},\n\t\ttable:  make(map[string]ExtGState),\n\t}\n}\n\nfunc (extm *ExtGStatesMap) Find(extGState ExtGStateOptions) (ExtGState, bool) {\n\tkey := extGState.GetId()\n\n\textm.syncer.Lock()\n\tdefer extm.syncer.Unlock()\n\n\tt, ok := extm.table[key]\n\tif !ok {\n\t\treturn ExtGState{}, false\n\t}\n\n\treturn t, ok\n\n}\n\nfunc (tm *ExtGStatesMap) Save(id string, extGState ExtGState) ExtGState {\n\ttm.syncer.Lock()\n\tdefer tm.syncer.Unlock()\n\n\ttm.table[id] = extGState\n\n\treturn extGState\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/font_obj.go",
    "content": "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 int\n\tIsEmbedFont bool\n\n\tindexObjWidth          int\n\tindexObjFontDescriptor int\n\tindexObjEncoding       int\n\n\tFont        IFont\n\tCountOfFont int\n}\n\nfunc (f *FontObj) init(funcGetRoot func() *GoPdf) {\n\tf.IsEmbedFont = false\n\t//me.CountOfFont = -1\n}\n\nfunc (f *FontObj) write(w io.Writer, objID int) error {\n\tbaseFont := f.Family\n\tif f.Font != nil {\n\t\tbaseFont = f.Font.GetName()\n\t}\n\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"  /Type /%s\\n\", f.getType())\n\tio.WriteString(w, \"  /Subtype /TrueType\\n\")\n\tfmt.Fprintf(w, \"  /BaseFont /%s\\n\", baseFont)\n\tif f.IsEmbedFont {\n\t\tio.WriteString(w, \"  /FirstChar 32 /LastChar 255\\n\")\n\t\tfmt.Fprintf(w, \"  /Widths %d 0 R\\n\", f.indexObjWidth)\n\t\tfmt.Fprintf(w, \"  /FontDescriptor %d 0 R\\n\", f.indexObjFontDescriptor)\n\t\tfmt.Fprintf(w, \"  /Encoding %d 0 R\\n\", f.indexObjEncoding)\n\t}\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\nfunc (f *FontObj) getType() string {\n\treturn \"Font\"\n}\n\n// SetIndexObjWidth sets the width of a font object.\nfunc (f *FontObj) SetIndexObjWidth(index int) {\n\tf.indexObjWidth = index\n}\n\n// SetIndexObjFontDescriptor sets the font descriptor.\nfunc (f *FontObj) SetIndexObjFontDescriptor(index int) {\n\tf.indexObjFontDescriptor = index\n}\n\n// SetIndexObjEncoding sets the encoding.\nfunc (f *FontObj) SetIndexObjEncoding(index int) {\n\tf.indexObjEncoding = index\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/font_option.go",
    "content": "package gopdf\n\nimport (\n\t\"strings\"\n)\n\n//Regular - font style regular\nconst Regular = 0 //000000\n//Italic - font style italic\nconst Italic = 1 //000001\n//Bold - font style bold\nconst Bold = 2 //000010\n//Underline - font style underline\nconst Underline = 4 //000100\n\nfunc getConvertedStyle(fontStyle string) (style int) {\n\tfontStyle = strings.ToUpper(fontStyle)\n\tif strings.Contains(fontStyle, \"B\") {\n\t\tstyle = style | Bold\n\t}\n\tif strings.Contains(fontStyle, \"I\") {\n\t\tstyle = style | Italic\n\t}\n\tif strings.Contains(fontStyle, \"U\") {\n\t\tstyle = style | Underline\n\t}\n\treturn\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontconverthelper.go",
    "content": "package gopdf\n\nimport (\n\t\"strconv\"\n\t//\"fmt\"\n\t\"bytes\"\n)\n\n// FontConvertHelperCw2Str converts main ASCII characters of a FontCW to a string.\nfunc FontConvertHelperCw2Str(cw FontCw) string {\n\tbuff := new(bytes.Buffer)\n\tbuff.WriteString(\" \")\n\ti := 32\n\tfor i <= 255 {\n\t\tbuff.WriteString(strconv.Itoa(cw[byte(i)]) + \" \")\n\t\ti++\n\t}\n\treturn buff.String()\n}\n\n// FontConvertHelper_Cw2Str converts main ASCII characters of a FontCW to a string. (for backward compatibility)\n// Deprecated: Use FontConvertHelperCw2Str(cw FontCw) instead\nfunc FontConvertHelper_Cw2Str(cw FontCw) string {\n\treturn FontConvertHelperCw2Str(cw)\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontdescriptor_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// FontDescriptorObj is a font descriptor object.\ntype FontDescriptorObj struct {\n\tfont              IFont\n\tfontFileObjRelate string\n}\n\nfunc (f *FontDescriptorObj) init(funcGetRoot func() *GoPdf) {\n\n}\n\nfunc (f *FontDescriptorObj) write(w io.Writer, objID int) error {\n\n\tfmt.Fprintf(w, \"<</Type /FontDescriptor /FontName /%s \", f.font.GetName())\n\tdescs := f.font.GetDesc()\n\ti := 0\n\tmax := len(descs)\n\tfor i < max {\n\t\tfmt.Fprintf(w, \"/%s %s \", descs[i].Key, descs[i].Val)\n\t\ti++\n\t}\n\n\tif f.getType() == \"Type1\" {\n\t\tio.WriteString(w, \"/FontFile \")\n\t} else {\n\t\tio.WriteString(w, \"/FontFile2 \")\n\t}\n\n\tio.WriteString(w, f.fontFileObjRelate)\n\tio.WriteString(w, \">>\\n\")\n\n\treturn nil\n}\n\nfunc (f *FontDescriptorObj) getType() string {\n\treturn \"FontDescriptor\"\n}\n\n// SetFont sets the font in descriptor.\nfunc (f *FontDescriptorObj) SetFont(font IFont) {\n\tf.font = font\n}\n\n// GetFont gets font from descriptor.\nfunc (f *FontDescriptorObj) GetFont() IFont {\n\treturn f.font\n}\n\n// SetFontFileObjRelate ???\nfunc (f *FontDescriptorObj) SetFontFileObjRelate(relate string) {\n\tf.fontFileObjRelate = relate\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/fontmaker.go",
    "content": "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\"\n\t\"strings\"\n)\n\n//ErrFontLicenseDoesNotAllowEmbedding Font license does not allow embedding\nvar ErrFontLicenseDoesNotAllowEmbedding = errors.New(\"Font license does not allow embedding\")\n\n//FontMaker font maker\ntype FontMaker struct {\n\tresults []string\n}\n\n//GetResults get result\nfunc (f *FontMaker) GetResults() []string {\n\treturn f.results\n}\n\n//NewFontMaker new FontMaker\nfunc NewFontMaker() *FontMaker {\n\treturn new(FontMaker)\n}\n\nfunc (f *FontMaker) MakeFont(fontpath string, mappath string, encode string, outfolderpath string) error {\n\n\tencodingpath := mappath + \"/\" + encode + \".map\"\n\n\t//read font file\n\tif _, err := os.Stat(fontpath); os.IsNotExist(err) {\n\t\treturn err\n\t}\n\n\tfileext := filepath.Ext(fontpath)\n\tif strings.ToLower(fileext) != \".ttf\" {\n\t\t//now support only ttf :-P\n\t\treturn errors.New(\"support only ttf \")\n\t}\n\n\tfontmaps, err := f.LoadMap(encodingpath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tinfo, err := f.GetInfoFromTrueType(fontpath, fontmaps)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t//zip\n\tbasename := filepath.Base(fontpath)\n\ttmp := strings.Split(basename, \".\")\n\tbasename = strings.Replace(tmp[0], \" \", \"_\", -1)\n\tgzfilename := basename + \".z\"\n\n\tvar buff bytes.Buffer\n\tgzipwriter := zlib.NewWriter(&buff)\n\n\tfontbytes, err := ioutil.ReadFile(fontpath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = gzipwriter.Write(fontbytes)\n\tif err != nil {\n\t\treturn err\n\t}\n\tgzipwriter.Close()\n\terr = ioutil.WriteFile(outfolderpath+\"/\"+gzfilename, buff.Bytes(), 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\tinfo.PushString(\"File\", gzfilename)\n\tf.results = append(f.results, fmt.Sprintf(\"Save Z file at %s.\", outfolderpath+\"/\"+gzfilename))\n\n\t//Definition File\n\t_, err = f.MakeDefinitionFile(f.GoStructName(basename), mappath, outfolderpath+\"/\"+basename+\".font.go\", encode, fontmaps, info)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (f *FontMaker) GoStructName(name string) string {\n\tgoname := strings.ToUpper(name[0:1]) + name[1:]\n\treturn goname\n}\n\nfunc (f *FontMaker) MakeDefinitionFile(gofontname string, mappath string, exportfile string, encode string, fontmaps []FontMap, info TtfInfo) (string, error) {\n\n\tfonttype := \"TrueType\"\n\tstr := \"\"\n\tstr += \"package fonts //change this\\n\"\n\tstr += \"import (\\n\"\n\tstr += \"\t\\\"github.com/signintech/gopdf\\\"\\n\"\n\tstr += \")\\n\"\n\tstr += \"type \" + gofontname + \" struct {\\n\"\n\tstr += \"\\tfamily string\\n\"\n\tstr += \"\\tfonttype string\\n\"\n\tstr += \"\\tname string\\n\"\n\tstr += \"\\tdesc  []gopdf.FontDescItem\\n\"\n\tstr += \"\\tup int\\n\"\n\tstr += \"\\tut int\\n\"\n\tstr += \"\\tcw gopdf.FontCw\\n\"\n\tstr += \"\\tenc string\\n\"\n\tstr += \"\\tdiff string\\n\"\n\tstr += \"}\\n\"\n\n\tstr += \"func (me * \" + gofontname + \") Init(){\\n\"\n\twidths, err := info.GetMapIntInt64(\"Widths\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\ttmpStr, err := f.MakeWidthArray(widths)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstr += tmpStr\n\n\ttmpInt64, err := info.GetInt64(\"UnderlinePosition\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstr += fmt.Sprintf(\"\\tme.up = %d\\n\", tmpInt64)\n\n\ttmpInt64, err = info.GetInt64(\"UnderlineThickness\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstr += fmt.Sprintf(\"\\tme.ut = %d\\n\", tmpInt64)\n\n\tstr += \"\\tme.fonttype = \\\"\" + fonttype + \"\\\"\\n\"\n\n\ttmpStr, err = info.GetString(\"FontName\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstr += fmt.Sprintf(\"\\tme.name = \\\"%s\\\"\\n\", tmpStr)\n\n\tstr += \"\\tme.enc = \\\"\" + encode + \"\\\"\\n\"\n\tdiff, err := f.MakeFontEncoding(mappath, fontmaps)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif diff != \"\" {\n\t\tstr += \"\\tme.diff = \\\"\" + diff + \"\\\"\\n\"\n\t}\n\n\tfd, err := f.MakeFontDescriptor(info)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstr += fd\n\n\tstr += \"}\\n\"\n\n\tstr += \"func (me * \" + gofontname + \")GetType() string{\\n\"\n\tstr += \"\\treturn me.fonttype\\n\"\n\tstr += \"}\\n\"\n\tstr += \"func (me * \" + gofontname + \")GetName() string{\\n\"\n\tstr += \"\\treturn me.name\\n\"\n\tstr += \"}\t\\n\"\n\tstr += \"func (me * \" + gofontname + \")GetDesc() []gopdf.FontDescItem{\\n\"\n\tstr += \"\\treturn me.desc\\n\"\n\tstr += \"}\\n\"\n\tstr += \"func (me * \" + gofontname + \")GetUp() int{\\n\"\n\tstr += \"\\treturn me.up\\n\"\n\tstr += \"}\\n\"\n\tstr += \"func (me * \" + gofontname + \")GetUt()  int{\\n\"\n\tstr += \"\\treturn me.ut\\n\"\n\tstr += \"}\\n\"\n\tstr += \"func (me * \" + gofontname + \")GetCw() gopdf.FontCw{\\n\"\n\tstr += \"\\treturn me.cw\\n\"\n\tstr += \"}\\n\"\n\tstr += \"func (me * \" + gofontname + \")GetEnc() string{\\n\"\n\tstr += \"\\treturn me.enc\\n\"\n\tstr += \"}\\n\"\n\tstr += \"func (me * \" + gofontname + \")GetDiff() string {\\n\"\n\tstr += \"\\treturn me.diff\\n\"\n\tstr += \"}\\n\"\n\n\tstr += \"func (me * \" + gofontname + \") GetOriginalsize() int{\\n\"\n\tstr += \"\\treturn 98764\\n\"\n\tstr += \"}\\n\"\n\n\tstr += \"func (me * \" + gofontname + \")  SetFamily(family string){\\n\"\n\tstr += \"\\tme.family = family\\n\"\n\tstr += \"}\\n\"\n\n\tstr += \"func (me * \" + gofontname + \") \tGetFamily() string{\\n\"\n\tstr += \"\\treturn me.family\\n\"\n\tstr += \"}\\n\"\n\n\terr = ioutil.WriteFile(exportfile, []byte(str), 0666)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tf.results = append(f.results, fmt.Sprintf(\"Save GO file at %s.\", exportfile))\n\treturn str, nil\n}\n\nfunc (f *FontMaker) MakeFontDescriptor(info TtfInfo) (string, error) {\n\n\tfd := \"\"\n\tfd = \"\\tme.desc = make([]gopdf.FontDescItem,8)\\n\"\n\n\t// Ascent\n\tascender, err := info.GetInt64(\"Ascender\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfd += fmt.Sprintf(\"\\tme.desc[0] =  gopdf.FontDescItem{ Key:\\\"Ascent\\\",Val : \\\"%d\\\" }\\n\", ascender)\n\n\t// Descent\n\tdescender, err := info.GetInt64(\"Descender\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfd += fmt.Sprintf(\"\\tme.desc[1] =  gopdf.FontDescItem{ Key: \\\"Descent\\\", Val : \\\"%d\\\" }\\n\", descender)\n\n\t// CapHeight\n\tcapHeight, err := info.GetInt64(\"CapHeight\")\n\tif err == nil {\n\t\tfd += fmt.Sprintf(\"\\tme.desc[2] =  gopdf.FontDescItem{ Key:\\\"CapHeight\\\", Val :  \\\"%d\\\" }\\n\", capHeight)\n\t} else if err == ERROR_NO_KEY_FOUND {\n\t\tfd += fmt.Sprintf(\"\\tme.desc[2] =  gopdf.FontDescItem{ Key:\\\"CapHeight\\\", Val :  \\\"%d\\\" }\\n\", ascender)\n\t} else {\n\t\treturn \"\", err\n\t}\n\n\t// Flags\n\tflags := 0\n\tisFixedPitch, err := info.GetBool(\"IsFixedPitch\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif isFixedPitch {\n\t\tflags += 1 << 0\n\t}\n\tflags += 1 << 5\n\titalicAngle, err := info.GetInt64(\"ItalicAngle\")\n\tif italicAngle != 0 {\n\t\tflags += 1 << 6\n\t}\n\tfd += fmt.Sprintf(\"\\tme.desc[3] =  gopdf.FontDescItem{ Key: \\\"Flags\\\", Val :  \\\"%d\\\" }\\n\", flags)\n\t//fmt.Printf(\"\\n----\\n\")\n\t// FontBBox\n\tfbb, err := info.GetInt64s(\"FontBBox\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfd += fmt.Sprintf(\"\\tme.desc[4] =  gopdf.FontDescItem{ Key:\\\"FontBBox\\\", Val :  \\\"[%d %d %d %d]\\\" }\\n\", fbb[0], fbb[1], fbb[2], fbb[3])\n\n\t// ItalicAngle\n\tfd += fmt.Sprintf(\"\\tme.desc[5] =  gopdf.FontDescItem{ Key:\\\"ItalicAngle\\\", Val :  \\\"%d\\\" }\\n\", italicAngle)\n\n\t// StemV\n\tstdVW, err := info.GetInt64(\"StdVW\")\n\tissetStdVW := false\n\tif err == nil {\n\t\tissetStdVW = true\n\t} else if err == ERROR_NO_KEY_FOUND {\n\t\tissetStdVW = false\n\t} else {\n\t\treturn \"\", err\n\t}\n\n\tbold, err := info.GetBool(\"Bold\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tstemv := int(0)\n\tif issetStdVW {\n\t\tstemv = stdVW\n\t} else if bold {\n\t\tstemv = 120\n\t} else {\n\t\tstemv = 70\n\t}\n\tfd += fmt.Sprintf(\"\\tme.desc[6] =  gopdf.FontDescItem{ Key:\\\"StemV\\\", Val :  \\\"%d\\\" }\\n \", stemv)\n\n\t// MissingWidth\n\tmissingWidth, err := info.GetInt64(\"MissingWidth\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfd += fmt.Sprintf(\"\\tme.desc[7] =  gopdf.FontDescItem{ Key:\\\"MissingWidth\\\", Val :  \\\"%d\\\" } \\n \", missingWidth)\n\treturn fd, nil\n}\n\nfunc (f *FontMaker) MakeFontEncoding(mappath string, fontmaps []FontMap) (string, error) {\n\n\trefpath := mappath + \"/cp1252.map\"\n\tref, err := f.LoadMap(refpath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\ts := \"\"\n\tlast := 0\n\tfor c := 0; c <= 255; c++ {\n\t\tif fontmaps[c].Name != ref[c].Name {\n\t\t\tif c != last+1 {\n\t\t\t\ts += fmt.Sprintf(\"%d \", c)\n\t\t\t}\n\t\t\tlast = c\n\t\t\ts += \"/\" + fontmaps[c].Name + \" \"\n\t\t}\n\t}\n\treturn strings.TrimSpace(s), nil\n}\n\nfunc (f *FontMaker) MakeWidthArray(widths map[int]int) (string, error) {\n\n\tstr := \"\\tme.cw = make(gopdf.FontCw)\\n\"\n\tfor c := 0; c <= 255; c++ {\n\t\tstr += \"\\tme.cw[\"\n\t\tchr := string(c)\n\t\tif chr == \"\\\"\" {\n\t\t\tstr += \"gopdf.ToByte(\\\"\\\\\\\"\\\")\"\n\t\t} else if chr == \"\\\\\" {\n\t\t\tstr += \"gopdf.ToByte(\\\"\\\\\\\\\\\")\"\n\t\t} else if c >= 32 && c <= 126 {\n\t\t\tstr += \"gopdf.ToByte(\\\"\" + chr + \"\\\")\"\n\t\t} else {\n\t\t\tstr += fmt.Sprintf(\"gopdf.Chr(%d)\", c)\n\t\t}\n\t\tstr += fmt.Sprintf(\"]=%d\\n\", widths[c])\n\t}\n\treturn str, nil\n}\n\nfunc (f *FontMaker) FileSize(path string) (int64, error) {\n\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn -1, err\n\t}\n\tdefer file.Close()\n\n\t// get the file size\n\tstat, err := file.Stat()\n\tif err != nil {\n\t\treturn -1, err\n\t}\n\treturn stat.Size(), nil\n}\n\nfunc (f *FontMaker) GetInfoFromTrueType(fontpath string, fontmaps []FontMap) (TtfInfo, error) {\n\n\tvar parser TTFParser\n\terr := parser.Parse(fontpath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !parser.Embeddable {\n\t\treturn nil, ErrFontLicenseDoesNotAllowEmbedding\n\t}\n\n\tinfo := NewTtfInfo()\n\n\tfileContent, err := ioutil.ReadFile(fontpath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tinfo.PushBytes(\"Data\", fileContent)\n\n\tsize, err := f.FileSize(fontpath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tinfo.PushInt64(\"OriginalSize\", size)\n\n\tk := float64(1000.0 / float64(parser.unitsPerEm))\n\tinfo.PushString(\"FontName\", parser.postScriptName)\n\tinfo.PushBool(\"Bold\", parser.Bold)\n\tinfo.PushInt(\"ItalicAngle\", parser.italicAngle)\n\tinfo.PushBool(\"IsFixedPitch\", parser.isFixedPitch)\n\tinfo.PushInt(\"Ascender\", f.MultiplyAndRound(k, parser.typoAscender))\n\tinfo.PushInt(\"Descender\", f.MultiplyAndRound(k, parser.typoDescender))\n\tinfo.PushInt(\"UnderlineThickness\", f.MultiplyAndRound(k, parser.underlineThickness))\n\tinfo.PushInt(\"UnderlinePosition\", f.MultiplyAndRound(k, parser.underlinePosition))\n\tfontBBoxs := []int{\n\t\tf.MultiplyAndRound(k, parser.xMin),\n\t\tf.MultiplyAndRound(k, parser.yMin),\n\t\tf.MultiplyAndRound(k, parser.xMax),\n\t\tf.MultiplyAndRound(k, parser.yMax),\n\t}\n\tinfo.PushInt64s(\"FontBBox\", fontBBoxs)\n\tinfo.PushInt(\"CapHeight\", f.MultiplyAndRound(k, parser.capHeight))\n\tmissingWidth := f.MultiplyAndRoundWithUInt64(k, parser.widths[0])\n\tinfo.PushInt(\"MissingWidth\", missingWidth)\n\n\twidths := make(map[int]int)\n\tmax := 256\n\tc := 0\n\tfor c < max {\n\t\twidths[c] = missingWidth\n\t\tc++\n\t}\n\n\tc = 0 //reset\n\tfor c < max {\n\t\tif fontmaps[c].Name != \".notdef\" {\n\t\t\tuv := fontmaps[c].Uv\n\t\t\tif val, ok := parser.chars[int(uv)]; ok {\n\t\t\t\tw := parser.widths[val]\n\t\t\t\twidths[c] = f.MultiplyAndRoundWithUInt64(k, w)\n\t\t\t} else {\n\t\t\t\tf.results = append(f.results, fmt.Sprintf(\"Warning: Character %s (%d) is missing\", fontmaps[c].Name, fontmaps[c].Uv))\n\t\t\t}\n\t\t}\n\t\tc++\n\t}\n\tinfo.PushMapIntInt64(\"Widths\", widths)\n\n\treturn info, nil\n}\n\nfunc (f *FontMaker) MultiplyAndRoundWithUInt64(k float64, v uint) int {\n\tr := k * float64(v)\n\treturn f.Round(r)\n}\n\nfunc (f *FontMaker) MultiplyAndRound(k float64, v int) int {\n\tr := k * float64(v)\n\treturn f.Round(r)\n}\n\nfunc (f *FontMaker) Round(value float64) int {\n\treturn Round(value)\n}\n\nfunc (f *FontMaker) LoadMap(encodingpath string) ([]FontMap, error) {\n\n\tif _, err := os.Stat(encodingpath); os.IsNotExist(err) {\n\t\treturn nil, err\n\t}\n\n\tvar fontmaps []FontMap\n\ti := 0\n\tmax := 256\n\tfor i < max {\n\t\tfontmaps = append(fontmaps, FontMap{Uv: -1, Name: \".notdef\"})\n\t\ti++\n\t}\n\n\tfile, err := os.Open(encodingpath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer file.Close()\n\n\tscanner := bufio.NewScanner(file)\n\tscanner.Split(bufio.ScanLines)\n\tfor scanner.Scan() {\n\t\tline := strings.TrimSpace(scanner.Text())\n\t\te := strings.Split(line, \" \")\n\t\tstrC := (e[0])[1:]\n\t\tstrUv := (e[1])[2:]\n\t\tc, err := strconv.ParseInt(strC, 16, 0)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tuv, err := strconv.ParseInt(strUv, 16, 0)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tname := e[2]\n\t\t//fmt.Println(\"strC = \"+strC+\"strUv = \"+strUv+\" c=%d , uv= %d\", c, uv)\n\t\tfontmaps[c].Name = name\n\t\tfontmaps[c].Uv = int(uv)\n\t}\n\n\treturn fontmaps, nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/fontmap.go",
    "content": "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",
    "content": "package core\n\n//KernTable https://www.microsoft.com/typography/otspec/kern.htm\ntype KernTable struct {\n\tVersion uint //for debug\n\tNTables uint //for debug\n\tKerning KernMap\n}\n\n//KernMap kerning map   map[left]KernValue\ntype KernMap map[uint]KernValue\n\n//KernValue kerning values  map[right]value\ntype KernValue map[uint]int16\n\n//ValueByRight  get value by right\nfunc (k KernValue) ValueByRight(right uint) (bool, int16) {\n\tif val, ok := k[uint(right)]; ok {\n\t\treturn true, val\n\t}\n\treturn false, 0\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/math.go",
    "content": "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(value)\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/table_directory_entry.go",
    "content": "package core\n\ntype TableDirectoryEntry struct {\n\tCheckSum uint\n\tOffset   uint\n\tLength   uint\n}\n\nfunc (t TableDirectoryEntry) PaddedLength() int {\n\tl := int(t.Length)\n\treturn (l + 3) & ^3\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttf_info.go",
    "content": "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 = errors.New(\"get wrong type\")\n\ntype TtfInfo map[string]interface{}\n\nfunc (t TtfInfo) PushString(key string, val string) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) PushBytes(key string, val []byte) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) PushInt64(key string, val int64) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) PushInt(key string, val int) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) PushUInt64(key string, val uint) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) PushBool(key string, val bool) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) PushInt64s(key string, val []int) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) PushMapIntInt64(key string, val map[int]int) {\n\tt[key] = val\n}\n\nfunc (t TtfInfo) GetBool(key string) (bool, error) {\n\tif val, ok := t[key]; ok {\n\n\t\tif m, ok := val.(bool); ok {\n\t\t\t/* act on str */\n\t\t\treturn m, nil\n\t\t} else {\n\t\t\treturn false, ERROR_NO_GET_WRONG_TYPE\n\t\t}\n\t} else {\n\t\treturn false, ERROR_NO_KEY_FOUND\n\t}\n}\n\nfunc (t TtfInfo) GetString(key string) (string, error) {\n\tif val, ok := t[key]; ok {\n\n\t\tif m, ok := val.(string); ok {\n\t\t\t/* act on str */\n\t\t\treturn m, nil\n\t\t} else {\n\t\t\treturn \"\", ERROR_NO_GET_WRONG_TYPE\n\t\t}\n\t} else {\n\t\treturn \"\", ERROR_NO_KEY_FOUND\n\t}\n}\n\nfunc (t TtfInfo) GetInt64(key string) (int, error) {\n\tif val, ok := t[key]; ok {\n\n\t\tif m, ok := val.(int); ok {\n\t\t\t/* act on str */\n\t\t\treturn m, nil\n\t\t} else {\n\t\t\treturn 0, ERROR_NO_GET_WRONG_TYPE\n\t\t}\n\t} else {\n\t\treturn 0, ERROR_NO_KEY_FOUND\n\t}\n}\n\nfunc (t TtfInfo) GetInt64s(key string) ([]int, error) {\n\tif val, ok := t[key]; ok {\n\n\t\tif m, ok := val.([]int); ok {\n\t\t\t/* act on str */\n\t\t\treturn m, nil\n\t\t} else {\n\t\t\treturn nil, ERROR_NO_GET_WRONG_TYPE\n\t\t}\n\t} else {\n\t\treturn nil, ERROR_NO_KEY_FOUND\n\t}\n}\n\nfunc (t TtfInfo) GetMapIntInt64(key string) (map[int]int, error) {\n\tif val, ok := t[key]; ok {\n\n\t\tif m, ok := val.(map[int]int); ok {\n\t\t\t/* act on str */\n\t\t\treturn m, nil\n\t\t} else {\n\t\t\treturn nil, ERROR_NO_GET_WRONG_TYPE\n\t\t}\n\t} else {\n\t\treturn nil, ERROR_NO_KEY_FOUND\n\t}\n}\n\nfunc NewTtfInfo() TtfInfo {\n\tinfo := make(TtfInfo)\n\treturn info\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser.go",
    "content": "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/ioutil\"\n\t\"os\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar ERROR_NO_UNICODE_ENCODING_FOUND = errors.New(\"No Unicode encoding found\")\nvar ERROR_UNEXPECTED_SUBTABLE_FORMAT = errors.New(\"Unexpected subtable format\")\nvar ERROR_INCORRECT_MAGIC_NUMBER = errors.New(\"Incorrect magic number\")\nvar ERROR_POSTSCRIPT_NAME_NOT_FOUND = errors.New(\"PostScript name not found\")\n\n//TTFParser true type font parser\ntype TTFParser struct {\n\ttables map[string]TableDirectoryEntry\n\t//head\n\tunitsPerEm       uint\n\txMin             int\n\tyMin             int\n\txMax             int\n\tyMax             int\n\tindexToLocFormat int\n\t//Hhea\n\tnumberOfHMetrics uint\n\tascender         int\n\tdescender        int\n\t//end Hhea\n\n\tnumGlyphs      uint\n\twidths         []uint\n\tchars          map[int]uint\n\tpostScriptName string\n\n\t//os2\n\tos2Version    uint\n\tEmbeddable    bool\n\tBold          bool\n\ttypoAscender  int\n\ttypoDescender int\n\tcapHeight     int\n\tsxHeight      int\n\n\t//post\n\titalicAngle        int\n\tunderlinePosition  int\n\tunderlineThickness int\n\tisFixedPitch       bool\n\tsTypoLineGap       int\n\tusWinAscent        uint\n\tusWinDescent       uint\n\n\t//cmap\n\tIsShortIndex  bool\n\tLocaTable     []uint\n\tSegCount      uint\n\tStartCount    []uint\n\tEndCount      []uint\n\tIdRangeOffset []uint\n\tIdDelta       []uint\n\tGlyphIdArray  []uint\n\tsymbol        bool\n\n\t//cmap format 12\n\tgroupingTables []CmapFormat12GroupingTable\n\n\t//data of font\n\tcachedFontData []byte\n\n\t//kerning\n\tuseKerning bool //user config for use or not use kerning\n\tkern       *KernTable\n}\n\nvar Symbolic = 1 << 2\nvar Nonsymbolic = (1 << 5)\n\n//Kern get KernTable\nfunc (t *TTFParser) Kern() *KernTable {\n\treturn t.kern\n}\n\n//UnderlinePosition postion of underline\nfunc (t *TTFParser) UnderlinePosition() int {\n\treturn t.underlinePosition\n}\n\n//GroupingTables get cmap format12 grouping table\nfunc (t *TTFParser) GroupingTables() []CmapFormat12GroupingTable {\n\treturn t.groupingTables\n}\n\n//UnderlineThickness thickness of underline\nfunc (t *TTFParser) UnderlineThickness() int {\n\treturn t.underlineThickness\n}\n\nfunc (t *TTFParser) XHeight() int {\n\tif t.os2Version >= 2 && t.sxHeight != 0 {\n\t\treturn t.sxHeight\n\t} else {\n\t\treturn int((0.66) * float64(t.ascender))\n\t}\n}\n\nfunc (t *TTFParser) XMin() int {\n\treturn t.xMin\n}\n\nfunc (t *TTFParser) YMin() int {\n\treturn t.yMin\n}\n\nfunc (t *TTFParser) XMax() int {\n\treturn t.xMax\n}\n\nfunc (t *TTFParser) YMax() int {\n\treturn t.yMax\n}\n\nfunc (t *TTFParser) ItalicAngle() int {\n\treturn t.italicAngle\n}\n\nfunc (t *TTFParser) Flag() int {\n\tflag := 0\n\tif t.symbol {\n\t\tflag |= Symbolic\n\t} else {\n\t\tflag |= Nonsymbolic\n\t}\n\treturn flag\n}\n\nfunc (t *TTFParser) Ascender() int {\n\tif t.typoAscender == 0 {\n\t\treturn t.ascender\n\t}\n\treturn int(t.usWinAscent)\n}\n\nfunc (t *TTFParser) Descender() int {\n\tif t.typoDescender == 0 {\n\t\treturn t.descender\n\t}\n\tdescender := int(t.usWinDescent)\n\tif t.descender < 0 {\n\t\tdescender = descender * (-1)\n\t}\n\treturn descender\n}\n\nfunc (t *TTFParser) TypoAscender() int {\n\treturn t.typoAscender\n}\n\nfunc (t *TTFParser) TypoDescender() int {\n\treturn t.typoDescender\n}\n\n//CapHeight https://en.wikipedia.org/wiki/Cap_height\nfunc (t *TTFParser) CapHeight() int {\n\treturn t.capHeight\n}\n\n//NumGlyphs number of glyph\nfunc (t *TTFParser) NumGlyphs() uint {\n\treturn t.numGlyphs\n}\n\nfunc (t *TTFParser) UnitsPerEm() uint {\n\treturn t.unitsPerEm\n}\n\nfunc (t *TTFParser) NumberOfHMetrics() uint {\n\treturn t.numberOfHMetrics\n}\n\nfunc (t *TTFParser) Widths() []uint {\n\treturn t.widths\n}\n\nfunc (t *TTFParser) Chars() map[int]uint {\n\treturn t.chars\n}\n\nfunc (t *TTFParser) GetTables() map[string]TableDirectoryEntry {\n\treturn t.tables\n}\n\n//SetUseKerning set useKerning must set before Parse\nfunc (t *TTFParser) SetUseKerning(use bool) {\n\tt.useKerning = use\n}\n\n//Parse parse\nfunc (t *TTFParser) Parse(filepath string) error {\n\tdata, err := ioutil.ReadFile(filepath)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn t.ParseFontData(data)\n}\n\n//ParseByReader parse by io.reader\nfunc (t *TTFParser) ParseByReader(rd io.Reader) error {\n\tfontData, err := ioutil.ReadAll(rd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn t.ParseFontData(fontData)\n}\n\n// ParseFontData parses font data.\nfunc (t *TTFParser) ParseFontData(fontData []byte) error {\n\tfd := bytes.NewReader(fontData)\n\n\tversion, err := t.Read(fd, 4)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !bytes.Equal(version, []byte{0x00, 0x01, 0x00, 0x00}) {\n\t\treturn errors.New(\"Unrecognized file (font) format\")\n\t}\n\n\ti := uint(0)\n\tnumTables, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.Skip(fd, 3*2) //searchRange, entrySelector, rangeShift\n\tt.tables = make(map[string]TableDirectoryEntry)\n\tfor i < numTables {\n\n\t\ttag, err := t.Read(fd, 4)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tchecksum, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\toffset, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tlength, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t//fmt.Printf(\"\\n\\ntag=%s  \\nOffset = %d\\n\", tag, offset)\n\t\tvar table TableDirectoryEntry\n\t\ttable.Offset = uint(offset)\n\t\ttable.CheckSum = checksum\n\t\ttable.Length = length\n\t\t//fmt.Printf(\"\\n\\ntag=%s  \\nOffset = %d\\nPaddedLength =%d\\n\\n \", tag, table.Offset, table.PaddedLength())\n\t\tt.tables[t.BytesToString(tag)] = table\n\t\ti++\n\t}\n\n\terr = t.ParseHead(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.ParseHhea(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.ParseMaxp(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = t.ParseHmtx(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = t.ParseCmap(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = t.ParseName(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = t.ParseOS2(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = t.ParsePost(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = t.ParseLoca(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif t.useKerning {\n\t\terr = t.Parsekern(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tt.cachedFontData = fontData\n\n\treturn nil\n}\n\nfunc (t *TTFParser) FontData() []byte {\n\treturn t.cachedFontData\n}\n\n//ParseLoca parse loca table https://www.microsoft.com/typography/otspec/loca.htm\nfunc (t *TTFParser) ParseLoca(fd *bytes.Reader) error {\n\n\tt.IsShortIndex = false\n\tif t.indexToLocFormat == 0 {\n\t\tt.IsShortIndex = true\n\t}\n\n\t//fmt.Printf(\"indexToLocFormat = %d\\n\", me.indexToLocFormat)\n\terr := t.Seek(fd, \"loca\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar locaTable []uint\n\ttable := t.tables[\"loca\"]\n\tif t.IsShortIndex {\n\t\t//do ShortIndex\n\t\tentries := table.Length / 2\n\t\ti := uint(0)\n\t\tfor i < entries {\n\t\t\titem, err := t.ReadUShort(fd)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tlocaTable = append(locaTable, item*2)\n\t\t\ti++\n\t\t}\n\t} else {\n\t\tentries := table.Length / 4\n\t\ti := uint(0)\n\t\tfor i < entries {\n\t\t\titem, err := t.ReadULong(fd)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tlocaTable = append(locaTable, item)\n\t\t\ti++\n\t\t}\n\t}\n\tt.LocaTable = locaTable\n\treturn nil\n}\n\n//ParsePost parse post table https://www.microsoft.com/typography/otspec/post.htm\nfunc (t *TTFParser) ParsePost(fd *bytes.Reader) error {\n\n\terr := t.Seek(fd, \"post\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.Skip(fd, 4) // version\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.italicAngle, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.Skip(fd, 2) // Skip decimal part\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.underlinePosition, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t//fmt.Printf(\"start>>>>>>>\\n\")\n\tt.underlineThickness, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\t//fmt.Printf(\"underlineThickness=%d\\n\", t.underlineThickness)\n\t//fmt.Printf(\">>>>>>>%d\\n\", me.underlineThickness)\n\n\tisFixedPitch, err := t.ReadULong(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.isFixedPitch = (isFixedPitch != 0)\n\n\treturn nil\n}\n\n//ParseOS2 parse OS2 table https://www.microsoft.com/typography/otspec/OS2.htm\nfunc (t *TTFParser) ParseOS2(fd *bytes.Reader) error {\n\terr := t.Seek(fd, \"OS/2\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tversion, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.os2Version = version\n\n\terr = t.Skip(fd, 3*2) // xAvgCharWidth, usWeightClass, usWidthClass\n\tif err != nil {\n\t\treturn err\n\t}\n\tfsType, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.Embeddable = (fsType != 2) && ((fsType & 0x200) == 0)\n\n\terr = t.Skip(fd, (11*2)+10+(4*4)+4)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfsSelection, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.Bold = ((fsSelection & 32) != 0)\n\terr = t.Skip(fd, 2*2) // usFirstCharIndex, usLastCharIndex\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.typoAscender, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.typoDescender, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.sTypoLineGap, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.usWinAscent, err = t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.usWinDescent, err = t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif version >= 2 {\n\n\t\terr = t.Skip(fd, 2*4)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tt.sxHeight, err = t.ReadShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tt.capHeight, err = t.ReadShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t} else {\n\t\tt.capHeight = t.ascender\n\t}\n\n\treturn nil\n}\n\n//ParseName parse name table https://www.microsoft.com/typography/otspec/name.htm\nfunc (t *TTFParser) ParseName(fd *bytes.Reader) error {\n\n\t//$this->Seek('name');\n\terr := t.Seek(fd, \"name\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ttableOffset, err := t.FTell(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.postScriptName = \"\"\n\terr = t.Skip(fd, 2) // format\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcount, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstringOffset, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor i := 0; i < int(count); i++ {\n\t\terr = t.Skip(fd, 3*2) // platformID, encodingID, languageID\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tnameID, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlength, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif nameID == 6 {\n\t\t\t// PostScript name\n\t\t\t_, err = fd.Seek(int64(tableOffset+stringOffset+offset), 0)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tstmp, err := t.Read(fd, int(length))\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tvar tmpStmp []byte\n\t\t\tfor _, v := range stmp {\n\t\t\t\tif v != 0 {\n\t\t\t\t\ttmpStmp = append(tmpStmp, v)\n\t\t\t\t}\n\t\t\t}\n\t\t\ts := fmt.Sprintf(\"%s\", string(tmpStmp)) //strings(stmp)\n\t\t\ts = strings.Replace(s, strconv.Itoa(0), \"\", -1)\n\t\t\ts, err = t.PregReplace(\"|[ \\\\[\\\\](){}<>/%]|\", \"\", s)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tt.postScriptName = s\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif t.postScriptName == \"\" {\n\t\treturn ERROR_POSTSCRIPT_NAME_NOT_FOUND\n\t}\n\n\t//fmt.Printf(\"%s\\n\", me.postScriptName)\n\treturn nil\n}\n\nfunc (t *TTFParser) PregReplace(pattern string, replacement string, subject string) (string, error) {\n\n\treg, err := regexp.Compile(pattern)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstr := reg.ReplaceAllString(subject, replacement)\n\treturn str, nil\n}\n\n//ParseCmap parse cmap table format 4 https://www.microsoft.com/typography/otspec/cmap.htm\nfunc (t *TTFParser) ParseCmap(fd *bytes.Reader) error {\n\tt.Seek(fd, \"cmap\")\n\tt.Skip(fd, 2) // version\n\tnumTables, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\toffset31 := uint(0)\n\tfor i := 0; i < int(numTables); i++ {\n\t\tplatformID, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tencodingID, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tt.symbol = false //init\n\t\tif platformID == 3 && encodingID == 1 {\n\t\t\tif encodingID == 0 {\n\t\t\t\tt.symbol = true\n\t\t\t}\n\t\t\toffset31 = offset\n\t\t}\n\t\t//fmt.Printf(\"me.symbol=%d\\n\", me.symbol)\n\t} //end for\n\n\tif offset31 == 0 {\n\t\t//No Unicode encoding found\n\t\treturn ERROR_NO_UNICODE_ENCODING_FOUND\n\t}\n\n\tvar startCount, endCount, idDelta, idRangeOffset, glyphIDArray []uint\n\n\t_, err = fd.Seek(int64(t.tables[\"cmap\"].Offset+offset31), 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tformat, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif format != 4 {\n\t\t//Unexpected subtable format\n\t\treturn ERROR_UNEXPECTED_SUBTABLE_FORMAT\n\t}\n\n\tlength, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\t//fmt.Printf(\"\\nlength=%d\\n\", length)\n\n\terr = t.Skip(fd, 2) // language\n\tif err != nil {\n\t\treturn err\n\t}\n\tsegCount, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tsegCount = segCount / 2\n\tt.SegCount = segCount\n\terr = t.Skip(fd, 3*2) // searchRange, entrySelector, rangeShift\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tglyphCount := (length - (16 + 8*segCount)) / 2\n\t//fmt.Printf(\"\\nglyphCount=%d\\n\", glyphCount)\n\n\tfor i := 0; i < int(segCount); i++ {\n\t\ttmp, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tendCount = append(endCount, tmp)\n\t}\n\tt.EndCount = endCount\n\n\terr = t.Skip(fd, 2) // reservedPad\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor i := 0; i < int(segCount); i++ {\n\t\ttmp, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tstartCount = append(startCount, tmp)\n\t}\n\tt.StartCount = startCount\n\n\tfor i := 0; i < int(segCount); i++ {\n\t\ttmp, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tidDelta = append(idDelta, tmp)\n\t}\n\tt.IdDelta = idDelta\n\n\toffset, err := t.FTell(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor i := 0; i < int(segCount); i++ {\n\t\ttmp, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tidRangeOffset = append(idRangeOffset, tmp)\n\t}\n\tt.IdRangeOffset = idRangeOffset\n\t//_ = glyphIdArray\n\tfor i := 0; i < int(glyphCount); i++ {\n\t\ttmp, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tglyphIDArray = append(glyphIDArray, tmp)\n\t}\n\tt.GlyphIdArray = glyphIDArray\n\n\tt.chars = make(map[int]uint)\n\tfor i := 0; i < int(segCount); i++ {\n\t\tc1 := startCount[i]\n\t\tc2 := endCount[i]\n\t\td := idDelta[i]\n\t\tro := idRangeOffset[i]\n\t\tif ro > 0 {\n\t\t\t_, err = fd.Seek(int64(offset+uint(2*i)+ro), 0)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tfor c := c1; c <= c2; c++ {\n\t\t\tvar gid uint\n\t\t\tif c == 0xFFFF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif ro > 0 {\n\t\t\t\tgid, err = t.ReadUShort(fd)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif gid > 0 {\n\t\t\t\t\tgid += d\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tgid = c + d\n\t\t\t}\n\n\t\t\tif gid >= 65536 {\n\t\t\t\tgid -= 65536\n\t\t\t}\n\t\t\tif gid > 0 {\n\t\t\t\t//fmt.Printf(\"%d gid = %d, \", int(c), gid)\n\t\t\t\tt.chars[int(c)] = gid\n\t\t\t}\n\t\t}\n\n\t}\n\n\t_, err = t.ParseCmapFormat12(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (t *TTFParser) FTell(fd *bytes.Reader) (uint, error) {\n\toffset, err := fd.Seek(0, os.SEEK_CUR)\n\treturn uint(offset), err\n}\n\n//ParseHmtx parse hmtx table  https://www.microsoft.com/typography/otspec/hmtx.htm\nfunc (t *TTFParser) ParseHmtx(fd *bytes.Reader) error {\n\n\tt.Seek(fd, \"hmtx\")\n\ti := uint(0)\n\tfor i < t.numberOfHMetrics {\n\t\tadvanceWidth, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = t.Skip(fd, 2)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tt.widths = append(t.widths, advanceWidth)\n\t\ti++\n\t}\n\tif t.numberOfHMetrics < t.numGlyphs {\n\t\tvar err error\n\t\tlastWidth := t.widths[t.numberOfHMetrics-1]\n\t\tt.widths, err = t.ArrayPadUint(t.widths, t.numGlyphs, lastWidth)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (t *TTFParser) ArrayPadUint(arr []uint, size uint, val uint) ([]uint, error) {\n\tvar result []uint\n\ti := uint(0)\n\tfor i < size {\n\t\tif int(i) < len(arr) {\n\t\t\tresult = append(result, arr[i])\n\t\t} else {\n\t\t\tresult = append(result, val)\n\t\t}\n\t\ti++\n\t}\n\n\treturn result, nil\n}\n\n//ParseHead parse head table  https://www.microsoft.com/typography/otspec/Head.htm\nfunc (t *TTFParser) ParseHead(fd *bytes.Reader) error {\n\n\t//fmt.Printf(\"\\nParseHead\\n\")\n\terr := t.Seek(fd, \"head\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.Skip(fd, 3*4) // version, fontRevision, checkSumAdjustment\n\tif err != nil {\n\t\treturn err\n\t}\n\tmagicNumber, err := t.ReadULong(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t//fmt.Printf(\"\\nmagicNumber = %d\\n\", magicNumber)\n\tif magicNumber != 0x5F0F3CF5 {\n\t\treturn ERROR_INCORRECT_MAGIC_NUMBER\n\t}\n\n\terr = t.Skip(fd, 2)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.unitsPerEm, err = t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.Skip(fd, 2*8) // created, modified\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.xMin, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.yMin, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.xMax, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.yMax, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.Skip(fd, 2*3) //skip macStyle,lowestRecPPEM,fontDirectionHint\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.indexToLocFormat, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n//ParseHhea parse hhea table  https://www.microsoft.com/typography/otspec/hhea.htm\nfunc (t *TTFParser) ParseHhea(fd *bytes.Reader) error {\n\n\terr := t.Seek(fd, \"hhea\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.Skip(fd, 4) //skip version\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.ascender, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.descender, err = t.ReadShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = t.Skip(fd, 13*2)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.numberOfHMetrics, err = t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n//ParseMaxp parse maxp table  https://www.microsoft.com/typography/otspec/Maxp.htm\nfunc (t *TTFParser) ParseMaxp(fd *bytes.Reader) error {\n\terr := t.Seek(fd, \"maxp\")\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = t.Skip(fd, 4)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.numGlyphs, err = t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//ErrTableNotFound error table not found\nvar ErrTableNotFound = errors.New(\"table not found\")\n\n//Seek seek by tag\nfunc (t *TTFParser) Seek(fd *bytes.Reader, tag string) error {\n\ttable, ok := t.tables[tag]\n\tif !ok {\n\t\treturn ErrTableNotFound\n\t}\n\tval := table.Offset\n\t_, err := fd.Seek(int64(val), 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//BytesToString convert bytes to string\nfunc (t *TTFParser) BytesToString(b []byte) string {\n\treturn string(b) //strings.TrimSpace(string(b))\n}\n\n//ReadUShort read ushort\nfunc (t *TTFParser) ReadUShort(fd *bytes.Reader) (uint, error) {\n\tbuff, err := t.Read(fd, 2)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tn := binary.BigEndian.Uint16(buff)\n\treturn uint(n), nil\n}\n\n//ReadShort read short\nfunc (t *TTFParser) ReadShort(fd *bytes.Reader) (int, error) {\n\tu, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t//fmt.Printf(\"%#v\\n\", buff)\n\tvar v int\n\tif u >= 0x8000 {\n\t\tv = int(u) - 65536\n\t} else {\n\t\tv = int(u)\n\t}\n\treturn v, nil\n}\n\n//ReadShortInt16 read short return int16\nfunc (t *TTFParser) ReadShortInt16(fd *bytes.Reader) (int16, error) {\n\tn, err := t.ReadShort(fd)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn int16(n), nil\n}\n\n//ReadULong read ulong\nfunc (t *TTFParser) ReadULong(fd *bytes.Reader) (uint, error) {\n\tbuff, err := t.Read(fd, 4)\n\t//fmt.Printf(\"%#v\\n\", buff)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tn := binary.BigEndian.Uint32(buff)\n\treturn uint(n), nil\n}\n\n//Skip skip\nfunc (t *TTFParser) Skip(fd *bytes.Reader, length int) error {\n\t_, err := fd.Seek(int64(length), 1)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//Read read\nfunc (t *TTFParser) Read(fd *bytes.Reader, length int) ([]byte, error) {\n\tbuff := make([]byte, length)\n\treadlength, err := fd.Read(buff)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif readlength != length {\n\t\treturn nil, errors.New(\"file out of length\")\n\t}\n\t//fmt.Printf(\"%d,%s\\n\", readlength, string(buff))\n\treturn buff, nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser_cmap_other_format.go",
    "content": "package core\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n)\n\n//ParseCmapFormat12 parse cmap table format 12 https://www.microsoft.com/typography/otspec/cmap.htm\nfunc (t *TTFParser) ParseCmapFormat12(fd *bytes.Reader) (bool, error) {\n\n\tt.Seek(fd, \"cmap\")\n\tt.Skip(fd, 2) //skip version\n\tnumTables, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tvar cEncodingSubtables []cmapFormat12EncodingSubtable\n\tfor i := 0; i < int(numTables); i++ {\n\t\tplatformID, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tencodingID, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\toffset, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tvar ce cmapFormat12EncodingSubtable\n\t\tce.platformID = platformID\n\t\tce.encodingID = encodingID\n\t\tce.offset = offset\n\t\tcEncodingSubtables = append(cEncodingSubtables, ce)\n\t}\n\n\tisFound := false\n\toffset := uint(0)\n\tfor _, ce := range cEncodingSubtables {\n\t\tif ce.platformID == 3 && ce.encodingID == 10 {\n\t\t\toffset = ce.offset\n\t\t\tisFound = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif !isFound {\n\t\treturn false, nil\n\t}\n\n\t_, err = fd.Seek(int64(t.tables[\"cmap\"].Offset+offset), 0)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tformat, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tif format != 12 {\n\t\treturn false, errors.New(\"format != 12\")\n\t}\n\n\treserved, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tif reserved != 0 {\n\t\treturn false, errors.New(\"reserved != 0\")\n\t}\n\n\terr = t.Skip(fd, 4) //skip length\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\terr = t.Skip(fd, 4) //skip language\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tnGroups, err := t.ReadULong(fd)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tg := uint(0)\n\tfor g < nGroups {\n\t\tstartCharCode, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tendCharCode, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tglyphID, err := t.ReadULong(fd)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tvar gTb CmapFormat12GroupingTable\n\t\tgTb.StartCharCode = startCharCode\n\t\tgTb.EndCharCode = endCharCode\n\t\tgTb.GlyphID = glyphID\n\t\tt.groupingTables = append(t.groupingTables, gTb)\n\t\tg++\n\t}\n\n\treturn true, nil\n}\n\ntype cmapFormat12EncodingSubtable struct {\n\tplatformID uint\n\tencodingID uint\n\toffset     uint\n}\n\ntype CmapFormat12GroupingTable struct {\n\tStartCharCode, EndCharCode, GlyphID uint\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/fontmaker/core/ttfparser_kern.go",
    "content": "package core\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n//Parsekern parse kerning table  https://www.microsoft.com/typography/otspec/kern.htm\nfunc (t *TTFParser) Parsekern(fd *bytes.Reader) error {\n\n\tt.kern = nil //clear\n\terr := t.Seek(fd, \"kern\")\n\tif err == ErrTableNotFound {\n\t\treturn nil\n\t} else if err != nil {\n\t\treturn err\n\t}\n\n\tt.kern = new(KernTable) //init\n\n\tversion, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.kern.Version = version\n\n\tnTables, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.kern.NTables = nTables\n\n\ti := uint(0)\n\tfor i < nTables {\n\t\terr = t.parsekernSubTable(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ti++\n\t}\n\n\treturn nil\n}\n\nfunc (t *TTFParser) parsekernSubTable(fd *bytes.Reader) error {\n\n\tt.Skip(fd, 2+2) //skip version and length\n\n\tcoverage, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tformat := coverage & 0xf0\n\t//fmt.Printf(\"format = %d\\n\", format) //debug\n\tt.kern.Kerning = make(KernMap) //init\n\tif format == 0 {\n\t\tt.parsekernSubTableFormat0(fd)\n\t} else {\n\t\t//not support other format yet\n\t\treturn fmt.Errorf(\"not support kerning format %d\", format)\n\t}\n\n\treturn nil\n}\n\nfunc (t *TTFParser) parsekernSubTableFormat0(fd *bytes.Reader) error {\n\tnPairs, err := t.ReadUShort(fd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.Skip(fd, 2+2+2) //skip searchRange , entrySelector , rangeShift\n\n\ti := uint(0)\n\tfor i < nPairs {\n\t\tleft, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tright, err := t.ReadUShort(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tvalue, err := t.ReadShortInt16(fd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif _, ok := t.kern.Kerning[left]; !ok {\n\t\t\tkval := make(KernValue)\n\t\t\tkval[right] = value\n\t\t\tt.kern.Kerning[left] = kval\n\t\t} else {\n\t\t\t(t.kern.Kerning[left])[right] = value\n\t\t}\n\t\t//_ = fmt.Sprintf(\"nPairs %d left %d right %d value %d\\n\", nPairs, left, right, value) //debug\n\t\ti++\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/func_kern_override.go",
    "content": "package gopdf\n\n//FuncKernOverride  return your custome pair value\ntype FuncKernOverride func(\n\tleftRune rune,\n\trightRune rune,\n\tleftPair uint,\n\trightPair uint,\n\tpairVal int16,\n) int16\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/go.mod",
    "content": "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.1\n)\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/go.sum",
    "content": "github.com/phpdave11/gofpdi v1.0.11 h1:wsBNx+3S0wy1dEp6fzv281S74ogZGgIdYWV2PugWgho=\ngithub.com/phpdave11/gofpdi v1.0.11/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/gopdf.go",
    "content": "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/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/phpdave11/gofpdi\"\n\t\"github.com/pkg/errors\"\n)\n\nconst subsetFont = \"SubsetFont\"\n\n// the default margin if no margins are set\nconst defaultMargin = 10.0 //for backward compatible\n\n//GoPdf : A simple library for generating PDF written in Go lang\ntype GoPdf struct {\n\n\t//page Margin\n\t//leftMargin float64\n\t//topMargin  float64\n\tmargins Margins\n\n\tpdfObjs []IObj\n\tconfig  Config\n\tanchors map[string]anchorOption\n\n\tindexOfCatalogObj int\n\n\t/*---index ของ obj สำคัญๆ เก็บเพื่อลด loop ตอนค้นหา---*/\n\t//index ของ obj pages\n\tindexOfPagesObj int\n\n\t//number of pages\n\tnumOfPagesObj int\n\n\t//index ของ obj page อันแรก\n\tindexOfFirstPageObj int\n\n\t//ต่ำแหน่งปัจจุบัน\n\tcurr Current\n\n\tindexEncodingObjFonts []int\n\tindexOfContent        int\n\n\t//index ของ procset ซึ่งควรจะมีอันเดียว\n\tindexOfProcSet int\n\n\t//IsUnderline bool\n\n\t// Buffer for io.Reader compliance\n\tbuf bytes.Buffer\n\n\t//pdf PProtection\n\tpdfProtection   *PDFProtection\n\tencryptionObjID int\n\n\t// content streams only\n\tcompressLevel int\n\n\t//info\n\tisUseInfo bool\n\tinfo      *PdfInfo\n\n\t//outlines\n\toutlines           *OutlinesObj\n\tindexOfOutlinesObj int\n\n\t// gofpdi free pdf document importer\n\tfpdi *gofpdi.Importer\n}\n\ntype DrawableRectOptions struct {\n\tRect\n\tX            float64\n\tY            float64\n\tPaintStyle   PaintStyle\n\tTransparency *Transparency\n\n\textGStateIndexes []int\n}\n\ntype CropOptions struct {\n\tX      float64\n\tY      float64\n\tWidth  float64\n\tHeight float64\n}\n\ntype ImageOptions struct {\n\tVerticalFlip   bool\n\tHorizontalFlip bool\n\tX              float64\n\tY              float64\n\tRect           *Rect\n\tMask           *MaskOptions\n\tCrop           *CropOptions\n\tTransparency   *Transparency\n\n\textGStateIndexes []int\n}\n\ntype MaskOptions struct {\n\tImageOptions\n\tHolder ImageHolder\n}\n\n//SetLineWidth : set line width\nfunc (gp *GoPdf) SetLineWidth(width float64) {\n\tgp.curr.lineWidth = gp.UnitsToPoints(width)\n\tgp.getContent().AppendStreamSetLineWidth(gp.UnitsToPoints(width))\n}\n\n//SetCompressLevel : set compress Level for content streams\n// Possible values for level:\n//    -2 HuffmanOnly, -1 DefaultCompression (which is level 6)\n//     0 No compression,\n//     1 fastest compression, but not very good ratio\n//     9 best compression, but slowest\nfunc (gp *GoPdf) SetCompressLevel(level int) {\n\terrfmt := \"compress level too %s, using %s instead\\n\"\n\tif level < -2 { //-2 = zlib.HuffmanOnly\n\t\tfmt.Fprintf(os.Stderr, errfmt, \"small\", \"DefaultCompression\")\n\t\tlevel = zlib.DefaultCompression\n\t} else if level > zlib.BestCompression {\n\t\tfmt.Fprintf(os.Stderr, errfmt, \"big\", \"BestCompression\")\n\t\tlevel = zlib.BestCompression\n\t\treturn\n\t}\n\t// sanity check complete\n\tgp.compressLevel = level\n}\n\n//SetNoCompression : compressLevel = 0\nfunc (gp *GoPdf) SetNoCompression() {\n\tgp.compressLevel = zlib.NoCompression\n}\n\n//SetLineType : set line type  (\"dashed\" ,\"dotted\")\n//  Usage:\n//  pdf.SetLineType(\"dashed\")\n//  pdf.Line(50, 200, 550, 200)\n//  pdf.SetLineType(\"dotted\")\n//  pdf.Line(50, 400, 550, 400)\nfunc (gp *GoPdf) SetLineType(linetype string) {\n\tgp.getContent().AppendStreamSetLineType(linetype)\n}\n\n//Line : draw line\nfunc (gp *GoPdf) Line(x1 float64, y1 float64, x2 float64, y2 float64) {\n\tgp.UnitsToPointsVar(&x1, &y1, &x2, &y2)\n\tgp.getContent().AppendStreamLine(x1, y1, x2, y2)\n}\n\n//RectFromLowerLeft : draw rectangle from lower-left corner (x, y)\nfunc (gp *GoPdf) RectFromLowerLeft(x float64, y float64, wdth float64, hght float64) {\n\tgp.UnitsToPointsVar(&x, &y, &wdth, &hght)\n\n\topts := DrawableRectOptions{\n\t\tX:          x,\n\t\tY:          y,\n\t\tPaintStyle: DrawPaintStyle,\n\t\tRect:       Rect{W: wdth, H: hght},\n\t}\n\n\tgp.getContent().AppendStreamRectangle(opts)\n}\n\n//RectFromUpperLeft : draw rectangle from upper-left corner (x, y)\nfunc (gp *GoPdf) RectFromUpperLeft(x float64, y float64, wdth float64, hght float64) {\n\tgp.UnitsToPointsVar(&x, &y, &wdth, &hght)\n\n\topts := DrawableRectOptions{\n\t\tX:          x,\n\t\tY:          y + hght,\n\t\tPaintStyle: DrawPaintStyle,\n\t\tRect:       Rect{W: wdth, H: hght},\n\t}\n\n\tgp.getContent().AppendStreamRectangle(opts)\n}\n\n//RectFromLowerLeftWithStyle : draw rectangle from lower-left corner (x, y)\n// - style: Style of rectangule (draw and/or fill: D, F, DF, FD)\n//\t\tD or empty string: draw. This is the default value.\n//\t\tF: fill\n//\t\tDF or FD: draw and fill\nfunc (gp *GoPdf) RectFromLowerLeftWithStyle(x float64, y float64, wdth float64, hght float64, style string) {\n\topts := DrawableRectOptions{\n\t\tX: x,\n\t\tY: y,\n\t\tRect: Rect{\n\t\t\tH: hght,\n\t\t\tW: wdth,\n\t\t},\n\t\tPaintStyle: parseStyle(style),\n\t}\n\tgp.RectFromLowerLeftWithOpts(opts)\n}\n\nfunc (gp *GoPdf) RectFromLowerLeftWithOpts(opts DrawableRectOptions) error {\n\tgp.UnitsToPointsVar(&opts.X, &opts.Y, &opts.W, &opts.H)\n\n\timageTransparency, err := gp.getCachedTransparency(opts.Transparency)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif imageTransparency != nil {\n\t\topts.extGStateIndexes = append(opts.extGStateIndexes, imageTransparency.extGStateIndex)\n\t}\n\n\tgp.getContent().AppendStreamRectangle(opts)\n\n\treturn nil\n}\n\n//RectFromUpperLeftWithStyle : draw rectangle from upper-left corner (x, y)\n// - style: Style of rectangule (draw and/or fill: D, F, DF, FD)\n//\t\tD or empty string: draw. This is the default value.\n//\t\tF: fill\n//\t\tDF or FD: draw and fill\nfunc (gp *GoPdf) RectFromUpperLeftWithStyle(x float64, y float64, wdth float64, hght float64, style string) {\n\topts := DrawableRectOptions{\n\t\tX: x,\n\t\tY: y,\n\t\tRect: Rect{\n\t\t\tH: hght,\n\t\t\tW: wdth,\n\t\t},\n\t\tPaintStyle: parseStyle(style),\n\t}\n\tgp.RectFromUpperLeftWithOpts(opts)\n}\n\nfunc (gp *GoPdf) RectFromUpperLeftWithOpts(opts DrawableRectOptions) error {\n\tgp.UnitsToPointsVar(&opts.X, &opts.Y, &opts.W, &opts.H)\n\n\topts.Y += opts.H\n\n\timageTransparency, err := gp.getCachedTransparency(opts.Transparency)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif imageTransparency != nil {\n\t\topts.extGStateIndexes = append(opts.extGStateIndexes, imageTransparency.extGStateIndex)\n\t}\n\n\tgp.getContent().AppendStreamRectangle(opts)\n\n\treturn nil\n}\n\n//Oval : draw oval\nfunc (gp *GoPdf) Oval(x1 float64, y1 float64, x2 float64, y2 float64) {\n\tgp.UnitsToPointsVar(&x1, &y1, &x2, &y2)\n\tgp.getContent().AppendStreamOval(x1, y1, x2, y2)\n}\n\n//Br : new line\nfunc (gp *GoPdf) Br(h float64) {\n\tgp.UnitsToPointsVar(&h)\n\tgp.curr.Y += h\n\tgp.curr.X = gp.margins.Left\n}\n\n//SetGrayFill set the grayscale for the fill, takes a float64 between 0.0 and 1.0\nfunc (gp *GoPdf) SetGrayFill(grayScale float64) {\n\tgp.curr.txtColorMode = \"gray\"\n\tgp.curr.grayFill = grayScale\n\tgp.getContent().AppendStreamSetGrayFill(grayScale)\n}\n\n//SetGrayStroke set the grayscale for the stroke, takes a float64 between 0.0 and 1.0\nfunc (gp *GoPdf) SetGrayStroke(grayScale float64) {\n\tgp.curr.grayStroke = grayScale\n\tgp.getContent().AppendStreamSetGrayStroke(grayScale)\n}\n\n//SetX : set current position X\nfunc (gp *GoPdf) SetX(x float64) {\n\tgp.UnitsToPointsVar(&x)\n\tgp.curr.setXCount++\n\tgp.curr.X = x\n}\n\n//GetX : get current position X\nfunc (gp *GoPdf) GetX() float64 {\n\treturn gp.PointsToUnits(gp.curr.X)\n}\n\n//SetY : set current position y\nfunc (gp *GoPdf) SetY(y float64) {\n\tgp.UnitsToPointsVar(&y)\n\tgp.curr.Y = y\n}\n\n//GetY : get current position y\nfunc (gp *GoPdf) GetY() float64 {\n\treturn gp.PointsToUnits(gp.curr.Y)\n}\n\n//ImageByHolder : draw image by ImageHolder\nfunc (gp *GoPdf) ImageByHolder(img ImageHolder, x float64, y float64, rect *Rect) error {\n\tgp.UnitsToPointsVar(&x, &y)\n\n\trect = rect.UnitsToPoints(gp.config.Unit)\n\n\timageOptions := ImageOptions{\n\t\tX:    x,\n\t\tY:    y,\n\t\tRect: rect,\n\t}\n\n\treturn gp.imageByHolder(img, imageOptions)\n}\n\nfunc (gp *GoPdf) ImageByHolderWithOptions(img ImageHolder, opts ImageOptions) error {\n\tgp.UnitsToPointsVar(&opts.X, &opts.Y)\n\n\topts.Rect = opts.Rect.UnitsToPoints(gp.config.Unit)\n\n\timageTransparency, err := gp.getCachedTransparency(opts.Transparency)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif imageTransparency != nil {\n\t\topts.extGStateIndexes = append(opts.extGStateIndexes, imageTransparency.extGStateIndex)\n\t}\n\n\tif opts.Mask != nil {\n\t\tmaskTransparency, err := gp.getCachedTransparency(opts.Mask.ImageOptions.Transparency)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif maskTransparency != nil {\n\t\t\topts.Mask.ImageOptions.extGStateIndexes = append(opts.Mask.ImageOptions.extGStateIndexes, maskTransparency.extGStateIndex)\n\t\t}\n\n\t\tgp.UnitsToPointsVar(&opts.Mask.ImageOptions.X, &opts.Mask.ImageOptions.Y)\n\t\topts.Mask.ImageOptions.Rect = opts.Mask.ImageOptions.Rect.UnitsToPoints(gp.config.Unit)\n\n\t\textGStateIndex, err := gp.maskHolder(opts.Mask.Holder, opts.Mask.ImageOptions)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\topts.extGStateIndexes = append(opts.extGStateIndexes, extGStateIndex)\n\t}\n\n\treturn gp.imageByHolder(img, opts)\n}\n\nfunc (gp *GoPdf) maskHolder(img ImageHolder, opts ImageOptions) (int, error) {\n\tvar cacheImage *ImageCache\n\tvar cacheContentImage *cacheContentImage\n\n\tfor _, imgcache := range gp.curr.ImgCaches {\n\t\tif img.ID() == imgcache.Path {\n\t\t\tcacheImage = &imgcache\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif cacheImage == nil {\n\t\tmaskImgobj := &ImageObj{IsMask: true}\n\t\tmaskImgobj.init(func() *GoPdf {\n\t\t\treturn gp\n\t\t})\n\t\tmaskImgobj.setProtection(gp.protection())\n\n\t\terr := maskImgobj.SetImage(img)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\tif opts.Rect == nil {\n\t\t\tif opts.Rect, err = maskImgobj.getRect(); err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t}\n\n\t\tif err := maskImgobj.parse(); err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\tif gp.indexOfProcSet != -1 {\n\t\t\tindex := gp.addObj(maskImgobj)\n\t\t\tcacheContentImage = gp.getContent().GetCacheContentImage(index, opts)\n\t\t\tprocset := gp.pdfObjs[gp.indexOfProcSet].(*ProcSetObj)\n\t\t\tprocset.RelateXobjs = append(procset.RelateXobjs, RelateXobject{IndexOfObj: index})\n\n\t\t\timgcache := ImageCache{\n\t\t\t\tIndex: index,\n\t\t\t\tPath:  img.ID(),\n\t\t\t\tRect:  opts.Rect,\n\t\t\t}\n\t\t\tgp.curr.ImgCaches[index] = imgcache\n\t\t\tgp.curr.CountOfImg++\n\t\t}\n\t} else {\n\t\tif opts.Rect == nil {\n\t\t\topts.Rect = gp.curr.ImgCaches[cacheImage.Index].Rect\n\t\t}\n\n\t\tcacheContentImage = gp.getContent().GetCacheContentImage(cacheImage.Index, opts)\n\t}\n\n\tif cacheContentImage != nil {\n\t\textGStateInd, err := gp.createTransparencyXObjectGroup(cacheContentImage, opts)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\treturn extGStateInd, nil\n\t}\n\n\treturn 0, errors.New(\"cacheContentImage is undefined\")\n}\n\nfunc (gp *GoPdf) createTransparencyXObjectGroup(image *cacheContentImage, opts ImageOptions) (int, error) {\n\tgroupOpts := TransparencyXObjectGroupOptions{\n\t\tExtGStateIndexes: opts.extGStateIndexes,\n\t\tXObjects:         []cacheContentImage{*image},\n\t\tBBox: [4]float64{\n\t\t\t// correct BBox values is [opts.X, gp.curr.pageSize.H - opts.Y - opts.Rect.H, opts.X + opts.Rect.W, gp.curr.pageSize.H - opts.Y]\n\t\t\t// but if compress pdf through ghostscript result file can't open correctly in mac viewer, because mac viewer can't parse BBox value correctly\n\t\t\t// all other viewers parse BBox correctly (like Adobe Acrobat Reader, Chrome, even Internet Explorer)\n\t\t\t// that's why we need to set [0, 0, gp.curr.pageSize.W, gp.curr.pageSize.H]\n\t\t\t0,\n\t\t\t0,\n\t\t\tgp.curr.pageSize.W,\n\t\t\tgp.curr.pageSize.H,\n\t\t},\n\t}\n\n\ttransparencyXObjectGroup, err := GetCachedTransparencyXObjectGroup(groupOpts, gp)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tsMaskOptions := SMaskOptions{\n\t\tSubtype:                       SMaskLuminositySubtype,\n\t\tTransparencyXObjectGroupIndex: transparencyXObjectGroup.Index,\n\t}\n\tsMask := GetCachedMask(sMaskOptions, gp)\n\n\textGStateOpts := ExtGStateOptions{SMaskIndex: &sMask.Index}\n\textGState, err := GetCachedExtGState(extGStateOpts, gp)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn extGState.Index + 1, nil\n}\n\nfunc (gp *GoPdf) imageByHolder(img ImageHolder, opts ImageOptions) error {\n\tcacheImageIndex := -1\n\n\tfor _, imgcache := range gp.curr.ImgCaches {\n\t\tif img.ID() == imgcache.Path {\n\t\t\tcacheImageIndex = imgcache.Index\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif cacheImageIndex == -1 { //new image\n\n\t\t//create img object\n\t\timgobj := new(ImageObj)\n\t\tif opts.Mask != nil {\n\t\t\timgobj.SplittedMask = true\n\t\t}\n\n\t\timgobj.init(func() *GoPdf {\n\t\t\treturn gp\n\t\t})\n\t\timgobj.setProtection(gp.protection())\n\n\t\terr := imgobj.SetImage(img)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif opts.Rect == nil {\n\t\t\tif opts.Rect, err = imgobj.getRect(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\terr = imgobj.parse()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tindex := gp.addObj(imgobj)\n\t\tif gp.indexOfProcSet != -1 {\n\t\t\t//ยัดรูป\n\t\t\tprocset := gp.pdfObjs[gp.indexOfProcSet].(*ProcSetObj)\n\t\t\tgp.getContent().AppendStreamImage(index, opts)\n\t\t\tprocset.RelateXobjs = append(procset.RelateXobjs, RelateXobject{IndexOfObj: index})\n\t\t\t//เก็บข้อมูลรูปเอาไว้\n\t\t\tvar imgcache ImageCache\n\t\t\timgcache.Index = index\n\t\t\timgcache.Path = img.ID()\n\t\t\timgcache.Rect = opts.Rect\n\t\t\tgp.curr.ImgCaches[index] = imgcache\n\t\t\tgp.curr.CountOfImg++\n\t\t}\n\n\t\tif imgobj.haveSMask() {\n\t\t\tsmaskObj, err := imgobj.createSMask()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\timgobj.imginfo.smarkObjID = gp.addObj(smaskObj)\n\t\t}\n\n\t\tif imgobj.isColspaceIndexed() {\n\t\t\tdRGB, err := imgobj.createDeviceRGB()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdRGB.getRoot = func() *GoPdf {\n\t\t\t\treturn gp\n\t\t\t}\n\t\t\timgobj.imginfo.deviceRGBObjID = gp.addObj(dRGB)\n\t\t}\n\n\t} else { //same img\n\t\tif opts.Rect == nil {\n\t\t\topts.Rect = gp.curr.ImgCaches[cacheImageIndex].Rect\n\t\t}\n\n\t\tgp.getContent().AppendStreamImage(cacheImageIndex, opts)\n\t}\n\treturn nil\n}\n\n//Image : draw image\nfunc (gp *GoPdf) Image(picPath string, x float64, y float64, rect *Rect) error {\n\tgp.UnitsToPointsVar(&x, &y)\n\trect = rect.UnitsToPoints(gp.config.Unit)\n\timgh, err := ImageHolderByPath(picPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\timageOptions := ImageOptions{\n\t\tX:    x,\n\t\tY:    y,\n\t\tRect: rect,\n\t}\n\n\treturn gp.imageByHolder(imgh, imageOptions)\n}\n\nfunc (gp *GoPdf) ImageFrom(img image.Image, x float64, y float64, rect *Rect) error {\n\tgp.UnitsToPointsVar(&x, &y)\n\trect = rect.UnitsToPoints(gp.config.Unit)\n\tr, w := io.Pipe()\n\tgo func() {\n\t\tbw := bufio.NewWriter(w)\n\t\terr := jpeg.Encode(bw, img, nil)\n\t\tbw.Flush()\n\t\tif err != nil {\n\t\t\tw.CloseWithError(err)\n\t\t} else {\n\t\t\tw.Close()\n\t\t}\n\t}()\n\n\timgh, err := ImageHolderByReader(bufio.NewReader(r))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\timageOptions := ImageOptions{\n\t\tX:    x,\n\t\tY:    y,\n\t\tRect: rect,\n\t}\n\n\treturn gp.imageByHolder(imgh, imageOptions)\n}\n\n//AddPage : add new page\nfunc (gp *GoPdf) AddPage() {\n\temptyOpt := PageOption{}\n\tgp.AddPageWithOption(emptyOpt)\n}\n\n//AddPageWithOption  : add new page with option\nfunc (gp *GoPdf) AddPageWithOption(opt PageOption) {\n\topt.TrimBox = opt.TrimBox.UnitsToPoints(gp.config.Unit)\n\topt.PageSize = opt.PageSize.UnitsToPoints(gp.config.Unit)\n\n\tpage := new(PageObj)\n\tpage.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\n\tif !opt.isEmpty() { //use page option\n\t\tpage.setOption(opt)\n\t\tgp.curr.pageSize = opt.PageSize\n\n\t\tif opt.isTrimBoxSet() {\n\t\t\tgp.curr.trimBox = opt.TrimBox\n\t\t}\n\t} else { //use default\n\t\tgp.curr.pageSize = &gp.config.PageSize\n\t\tgp.curr.trimBox = &gp.config.TrimBox\n\t}\n\n\tpage.ResourcesRelate = strconv.Itoa(gp.indexOfProcSet+1) + \" 0 R\"\n\tindex := gp.addObj(page)\n\tif gp.indexOfFirstPageObj == -1 {\n\t\tgp.indexOfFirstPageObj = index\n\t}\n\tgp.curr.IndexOfPageObj = index\n\n\tgp.numOfPagesObj++\n\n\t//reset\n\tgp.indexOfContent = -1\n\tgp.resetCurrXY()\n}\n\nfunc (gp *GoPdf) AddOutline(title string) {\n\tgp.outlines.AddOutline(gp.curr.IndexOfPageObj+1, title)\n}\n\n//Start : init gopdf\nfunc (gp *GoPdf) Start(config Config) {\n\n\tgp.config = config\n\tgp.init()\n\t//สร้าง obj พื้นฐาน\n\tcatalog := new(CatalogObj)\n\tcatalog.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tpages := new(PagesObj)\n\tpages.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tgp.outlines = new(OutlinesObj)\n\tgp.outlines.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tgp.indexOfCatalogObj = gp.addObj(catalog)\n\tgp.indexOfPagesObj = gp.addObj(pages)\n\tgp.indexOfOutlinesObj = gp.addObj(gp.outlines)\n\tgp.outlines.SetIndexObjOutlines(gp.indexOfOutlinesObj)\n\n\t//indexOfProcSet\n\tprocset := new(ProcSetObj)\n\tprocset.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tgp.indexOfProcSet = gp.addObj(procset)\n\n\tif gp.isUseProtection() {\n\t\tgp.pdfProtection = gp.createProtection()\n\t}\n\n}\n\n// SetFontWithStyle : set font style support Regular or Underline\n// for Bold|Italic should be loaded apropriate fonts with same styles defined\nfunc (gp *GoPdf) SetFontWithStyle(family string, style int, size int) error {\n\n\tfound := false\n\ti := 0\n\tmax := len(gp.pdfObjs)\n\tfor i < max {\n\t\tif gp.pdfObjs[i].getType() == subsetFont {\n\t\t\tobj := gp.pdfObjs[i]\n\t\t\tsub, ok := obj.(*SubsetFontObj)\n\t\t\tif ok {\n\t\t\t\tif sub.GetFamily() == family && sub.GetTtfFontOption().Style == style&^Underline {\n\t\t\t\t\tgp.curr.FontSize = size\n\t\t\t\t\tgp.curr.FontStyle = style\n\t\t\t\t\tgp.curr.FontFontCount = sub.CountOfFont\n\t\t\t\t\tgp.curr.FontISubset = sub\n\t\t\t\t\tfound = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n\n\tif !found {\n\t\treturn errors.New(\"not found font family\")\n\t}\n\n\treturn nil\n}\n\n//SetFont : set font style support \"\" or \"U\"\n// for \"B\" and \"I\" should be loaded apropriate fonts with same styles defined\nfunc (gp *GoPdf) SetFont(family string, style string, size int) error {\n\treturn gp.SetFontWithStyle(family, getConvertedStyle(style), size)\n}\n\n//WritePdf : wirte pdf file\nfunc (gp *GoPdf) WritePdf(pdfPath string) error {\n\treturn ioutil.WriteFile(pdfPath, gp.GetBytesPdf(), 0644)\n}\n\nfunc (gp *GoPdf) Write(w io.Writer) error {\n\treturn gp.compilePdf(w)\n}\n\nfunc (gp *GoPdf) Read(p []byte) (int, error) {\n\tif gp.buf.Len() == 0 && gp.buf.Cap() == 0 {\n\t\tif err := gp.compilePdf(&gp.buf); err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\treturn gp.buf.Read(p)\n}\n\n// Close clears the gopdf buffer.\nfunc (gp *GoPdf) Close() error {\n\tgp.buf = bytes.Buffer{}\n\treturn nil\n}\n\nfunc (gp *GoPdf) compilePdf(w io.Writer) error {\n\tgp.prepare()\n\terr := gp.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\tmax := len(gp.pdfObjs)\n\twriter := newCountingWriter(w)\n\t//io.WriteString(w, \"%PDF-1.7\\n\\n\")\n\tfmt.Fprint(writer, \"%PDF-1.7\\n\\n\")\n\tlinelens := make([]int, max)\n\ti := 0\n\n\tfor i < max {\n\t\tobjID := i + 1\n\t\tlinelens[i] = writer.offset\n\t\tpdfObj := gp.pdfObjs[i]\n\t\tfmt.Fprintf(writer, \"%d 0 obj\\n\", objID)\n\t\tpdfObj.write(writer, objID)\n\t\tio.WriteString(writer, \"endobj\\n\\n\")\n\t\ti++\n\t}\n\tgp.xref(writer, writer.offset, linelens, i)\n\treturn nil\n}\n\ntype (\n\tcountingWriter struct {\n\t\toffset int\n\t\twriter io.Writer\n\t}\n)\n\nfunc newCountingWriter(w io.Writer) *countingWriter {\n\treturn &countingWriter{writer: w}\n}\n\nfunc (cw *countingWriter) Write(b []byte) (int, error) {\n\tn, err := cw.writer.Write(b)\n\tcw.offset += n\n\treturn n, err\n}\n\n//GetBytesPdfReturnErr : get bytes of pdf file\nfunc (gp *GoPdf) GetBytesPdfReturnErr() ([]byte, error) {\n\terr := gp.Close()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\terr = gp.compilePdf(&gp.buf)\n\treturn gp.buf.Bytes(), err\n}\n\n//GetBytesPdf : get bytes of pdf file\nfunc (gp *GoPdf) GetBytesPdf() []byte {\n\tb, err := gp.GetBytesPdfReturnErr()\n\tif err != nil {\n\t\tlog.Fatalf(\"%s\", err.Error())\n\t}\n\treturn b\n}\n\n//Text write text start at current x,y ( current y is the baseline of text )\nfunc (gp *GoPdf) Text(text string) error {\n\n\terr := gp.curr.FontISubset.AddChars(text)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = gp.getContent().AppendStreamText(text)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n//CellWithOption create cell of text ( use current x,y is upper-left corner of cell)\nfunc (gp *GoPdf) CellWithOption(rectangle *Rect, text string, opt CellOption) error {\n\ttransparency, err := gp.getCachedTransparency(opt.Transparency)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif transparency != nil {\n\t\topt.extGStateIndexes = append(opt.extGStateIndexes, transparency.extGStateIndex)\n\t}\n\n\trectangle = rectangle.UnitsToPoints(gp.config.Unit)\n\tif err := gp.curr.FontISubset.AddChars(text); err != nil {\n\t\treturn err\n\t}\n\tif err := gp.getContent().AppendStreamSubsetFont(rectangle, text, opt); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n//Cell : create cell of text ( use current x,y is upper-left corner of cell)\n//Note that this has no effect on Rect.H pdf (now). Fix later :-)\nfunc (gp *GoPdf) Cell(rectangle *Rect, text string) error {\n\trectangle = rectangle.UnitsToPoints(gp.config.Unit)\n\tdefaultopt := CellOption{\n\t\tAlign:  Left | Top,\n\t\tBorder: 0,\n\t\tFloat:  Right,\n\t}\n\n\terr := gp.curr.FontISubset.AddChars(text)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = gp.getContent().AppendStreamSubsetFont(rectangle, text, defaultopt)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n//MultiCell : create of text with line breaks ( use current x,y is upper-left corner of cell)\nfunc (gp *GoPdf) MultiCell(rectangle *Rect, text string) error {\n\tvar line []rune\n\tx := gp.GetX()\n\tvar totalLineHeight float64\n\tlength := len([]rune(text))\n\n\t// get lineHeight\n\tif err := gp.curr.FontISubset.AddChars(text); err != nil {\n\t\treturn err\n\t}\n\t_, lineHeight, _, err := createContent(gp.curr.FontISubset, text, gp.curr.FontSize, nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor i, v := range []rune(text) {\n\t\tif totalLineHeight+lineHeight > rectangle.H {\n\t\t\tbreak\n\t\t}\n\t\tlineWidth, _ := gp.MeasureTextWidth(string(line))\n\t\truneWidth, _ := gp.MeasureTextWidth(string(v))\n\n\t\tif lineWidth+runeWidth > rectangle.W {\n\t\t\tgp.Cell(&Rect{W: rectangle.W, H: lineHeight}, string(line))\n\t\t\tgp.Br(lineHeight)\n\t\t\tgp.SetX(x)\n\t\t\ttotalLineHeight = totalLineHeight + lineHeight\n\t\t\tline = nil\n\t\t}\n\n\t\tline = append(line, v)\n\n\t\tif i == length-1 {\n\t\t\tgp.Cell(&Rect{W: rectangle.W, H: lineHeight}, string(line))\n\t\t\tgp.Br(lineHeight)\n\t\t\tgp.SetX(x)\n\t\t}\n\t}\n\treturn nil\n}\n\n// SplitText splits text into multiple lines based on width.\nfunc (gp *GoPdf) SplitText(text string, width float64) ([]string, error) {\n\tvar lineText []rune\n\tvar lineTexts []string\n\tutf8Texts := []rune(text)\n\tutf8TextsLen := len(utf8Texts) // utf8 string quantity\n\tif utf8TextsLen == 0 {\n\t\treturn lineTexts, errors.New(\"empty string\")\n\t}\n\tfor i := 0; i < utf8TextsLen; i++ {\n\t\tlineWidth, err := gp.MeasureTextWidth(string(lineText))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\truneWidth, err := gp.MeasureTextWidth(string(utf8Texts[i]))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif lineWidth+runeWidth > width && utf8Texts[i] != '\\n' {\n\t\t\tlineTexts = append(lineTexts, string(lineText))\n\t\t\tlineText = lineText[0:0]\n\t\t\ti--\n\t\t\tcontinue\n\t\t}\n\t\tif utf8Texts[i] == '\\n' {\n\t\t\tlineTexts = append(lineTexts, string(lineText))\n\t\t\tlineText = lineText[0:0]\n\t\t\tcontinue\n\t\t}\n\t\tif i == utf8TextsLen-1 {\n\t\t\tlineText = append(lineText, utf8Texts[i])\n\t\t\tlineTexts = append(lineTexts, string(lineText))\n\t\t}\n\t\tlineText = append(lineText, utf8Texts[i])\n\n\t}\n\treturn lineTexts, nil\n}\n\n// ImportPage imports a page and return template id.\n// gofpdi code\nfunc (gp *GoPdf) ImportPage(sourceFile string, pageno int, box string) int {\n\t// Set source file for fpdi\n\tgp.fpdi.SetSourceFile(sourceFile)\n\n\t// gofpdi needs to know where to start the object id at.\n\t// By default, it starts at 1, but gopdf adds a few objects initially.\n\tstartObjID := gp.GetNextObjectID()\n\n\t// Set gofpdi next object ID to  whatever the value of startObjID is\n\tgp.fpdi.SetNextObjectID(startObjID)\n\n\t// Import page\n\ttpl := gp.fpdi.ImportPage(pageno, box)\n\n\t// Import objects into current pdf document\n\ttplObjIDs := gp.fpdi.PutFormXobjects()\n\n\t// Set template names and ids in gopdf\n\tgp.ImportTemplates(tplObjIDs)\n\n\t// Get a map[int]string of the imported objects.\n\t// The map keys will be the ID of each object.\n\timported := gp.fpdi.GetImportedObjects()\n\n\t// Import gofpdi objects into gopdf, starting at whatever the value of startObjID is\n\tgp.ImportObjects(imported, startObjID)\n\n\t// Return template ID\n\treturn tpl\n}\n\n// ImportPageStream imports page using a stream.\n// Return template id after importing.\n// gofpdi code\nfunc (gp *GoPdf) ImportPageStream(sourceStream *io.ReadSeeker, pageno int, box string) int {\n\t// Set source file for fpdi\n\tgp.fpdi.SetSourceStream(sourceStream)\n\n\t// gofpdi needs to know where to start the object id at.\n\t// By default, it starts at 1, but gopdf adds a few objects initially.\n\tstartObjID := gp.GetNextObjectID()\n\n\t// Set gofpdi next object ID to  whatever the value of startObjID is\n\tgp.fpdi.SetNextObjectID(startObjID)\n\n\t// Import page\n\ttpl := gp.fpdi.ImportPage(pageno, box)\n\n\t// Import objects into current pdf document\n\ttplObjIDs := gp.fpdi.PutFormXobjects()\n\n\t// Set template names and ids in gopdf\n\tgp.ImportTemplates(tplObjIDs)\n\n\t// Get a map[int]string of the imported objects.\n\t// The map keys will be the ID of each object.\n\timported := gp.fpdi.GetImportedObjects()\n\n\t// Import gofpdi objects into gopdf, starting at whatever the value of startObjID is\n\tgp.ImportObjects(imported, startObjID)\n\n\t// Return template ID\n\treturn tpl\n}\n\n// UseImportedTemplate draws an imported PDF page.\nfunc (gp *GoPdf) UseImportedTemplate(tplid int, x float64, y float64, w float64, h float64) {\n\tgp.UnitsToPointsVar(&x, &y, &w, &h)\n\t// Get template values to draw\n\ttplName, scaleX, scaleY, tX, tY := gp.fpdi.UseTemplate(tplid, x, y, w, h)\n\tgp.getContent().AppendStreamImportedTemplate(tplName, scaleX, scaleY, tX, tY)\n}\n\n// GetNextObjectID gets the next object ID so that gofpdi knows where to start the object IDs.\nfunc (gp *GoPdf) GetNextObjectID() int {\n\treturn len(gp.pdfObjs) + 1\n}\n\n// GetNumberOfPages gets the number of pages from the PDF.\nfunc (gp *GoPdf) GetNumberOfPages() int {\n\treturn gp.numOfPagesObj\n}\n\n// ImportObjects imports objects from gofpdi into current document.\nfunc (gp *GoPdf) ImportObjects(objs map[int]string, startObjID int) {\n\tfor i := startObjID; i < len(objs)+startObjID; i++ {\n\t\tif objs[i] != \"\" {\n\t\t\tgp.addObj(&ImportedObj{Data: objs[i]})\n\t\t}\n\t}\n}\n\n// ImportTemplates names into procset dictionary.\nfunc (gp *GoPdf) ImportTemplates(tpls map[string]int) {\n\tprocset := gp.pdfObjs[gp.indexOfProcSet].(*ProcSetObj)\n\tfor tplName, tplID := range tpls {\n\t\tprocset.ImportedTemplateIds[tplName] = tplID\n\t}\n}\n\n// AddExternalLink adds a new external link.\nfunc (gp *GoPdf) AddExternalLink(url string, x, y, w, h float64) {\n\tgp.UnitsToPointsVar(&x, &y, &w, &h)\n\tpage := gp.pdfObjs[gp.curr.IndexOfPageObj].(*PageObj)\n\tpage.Links = append(page.Links, linkOption{x, gp.config.PageSize.H - y, w, h, url, \"\"})\n}\n\n// AddInternalLink adds a new internal link.\nfunc (gp *GoPdf) AddInternalLink(anchor string, x, y, w, h float64) {\n\tgp.UnitsToPointsVar(&x, &y, &w, &h)\n\tpage := gp.pdfObjs[gp.curr.IndexOfPageObj].(*PageObj)\n\tpage.Links = append(page.Links, linkOption{x, gp.config.PageSize.H - y, w, h, \"\", anchor})\n}\n\n// SetAnchor creates a new anchor.\nfunc (gp *GoPdf) SetAnchor(name string) {\n\ty := gp.config.PageSize.H - gp.curr.Y + float64(gp.curr.FontSize)\n\tgp.anchors[name] = anchorOption{gp.curr.IndexOfPageObj, y}\n}\n\n// AddTTFFontByReader adds font data by reader.\nfunc (gp *GoPdf) AddTTFFontData(family string, fontData []byte) error {\n\treturn gp.AddTTFFontDataWithOption(family, fontData, defaultTtfFontOption())\n}\n\n// AddTTFFontDataWithOption adds font data with option.\nfunc (gp *GoPdf) AddTTFFontDataWithOption(family string, fontData []byte, option TtfOption) error {\n\tsubsetFont := new(SubsetFontObj)\n\tsubsetFont.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tsubsetFont.SetTtfFontOption(option)\n\tsubsetFont.SetFamily(family)\n\terr := subsetFont.SetTTFData(fontData)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn gp.setSubsetFontObject(subsetFont, family, option)\n}\n\n// AddTTFFontByReader adds font file by reader.\nfunc (gp *GoPdf) AddTTFFontByReader(family string, rd io.Reader) error {\n\treturn gp.AddTTFFontByReaderWithOption(family, rd, defaultTtfFontOption())\n}\n\n// AddTTFFontByReaderWithOption adds font file by reader with option.\nfunc (gp *GoPdf) AddTTFFontByReaderWithOption(family string, rd io.Reader, option TtfOption) error {\n\tsubsetFont := new(SubsetFontObj)\n\tsubsetFont.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tsubsetFont.SetTtfFontOption(option)\n\tsubsetFont.SetFamily(family)\n\terr := subsetFont.SetTTFByReader(rd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn gp.setSubsetFontObject(subsetFont, family, option)\n}\n\n// setSubsetFontObject sets SubsetFontObj.\n// The given SubsetFontObj is expected to be configured in advance.\nfunc (gp *GoPdf) setSubsetFontObject(subsetFont *SubsetFontObj, family string, option TtfOption) error {\n\tunicodemap := new(UnicodeMap)\n\tunicodemap.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tunicodemap.setProtection(gp.protection())\n\tunicodemap.SetPtrToSubsetFontObj(subsetFont)\n\tunicodeindex := gp.addObj(unicodemap)\n\n\tpdfdic := new(PdfDictionaryObj)\n\tpdfdic.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tpdfdic.setProtection(gp.protection())\n\tpdfdic.SetPtrToSubsetFontObj(subsetFont)\n\tpdfdicindex := gp.addObj(pdfdic)\n\n\tsubfontdesc := new(SubfontDescriptorObj)\n\tsubfontdesc.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tsubfontdesc.SetPtrToSubsetFontObj(subsetFont)\n\tsubfontdesc.SetIndexObjPdfDictionary(pdfdicindex)\n\tsubfontdescindex := gp.addObj(subfontdesc)\n\n\tcidfont := new(CIDFontObj)\n\tcidfont.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\tcidfont.SetPtrToSubsetFontObj(subsetFont)\n\tcidfont.SetIndexObjSubfontDescriptor(subfontdescindex)\n\tcidindex := gp.addObj(cidfont)\n\n\tsubsetFont.SetIndexObjCIDFont(cidindex)\n\tsubsetFont.SetIndexObjUnicodeMap(unicodeindex)\n\tindex := gp.addObj(subsetFont) //add หลังสุด\n\n\tif gp.indexOfProcSet != -1 {\n\t\tprocset := gp.pdfObjs[gp.indexOfProcSet].(*ProcSetObj)\n\t\tif !procset.Relates.IsContainsFamilyAndStyle(family, option.Style&^Underline) {\n\t\t\tprocset.Relates = append(procset.Relates, RelateFont{Family: family, IndexOfObj: index, CountOfFont: gp.curr.CountOfFont, Style: option.Style &^ Underline})\n\t\t\tsubsetFont.CountOfFont = gp.curr.CountOfFont\n\t\t\tgp.curr.CountOfFont++\n\t\t}\n\t}\n\treturn nil\n}\n\n//AddTTFFontWithOption : add font file\nfunc (gp *GoPdf) AddTTFFontWithOption(family string, ttfpath string, option TtfOption) error {\n\n\tif _, err := os.Stat(ttfpath); os.IsNotExist(err) {\n\t\treturn err\n\t}\n\tdata, err := ioutil.ReadFile(ttfpath)\n\tif err != nil {\n\t\treturn err\n\t}\n\trd := bytes.NewReader(data)\n\treturn gp.AddTTFFontByReaderWithOption(family, rd, option)\n}\n\n//AddTTFFont : add font file\nfunc (gp *GoPdf) AddTTFFont(family string, ttfpath string) error {\n\treturn gp.AddTTFFontWithOption(family, ttfpath, defaultTtfFontOption())\n}\n\n//KernOverride override kern value\nfunc (gp *GoPdf) KernOverride(family string, fn FuncKernOverride) error {\n\ti := 0\n\tmax := len(gp.pdfObjs)\n\tfor i < max {\n\t\tif gp.pdfObjs[i].getType() == subsetFont {\n\t\t\tobj := gp.pdfObjs[i]\n\t\t\tsub, ok := obj.(*SubsetFontObj)\n\t\t\tif ok {\n\t\t\t\tif sub.GetFamily() == family {\n\t\t\t\t\tsub.funcKernOverride = fn\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n\treturn errors.New(\"font family not found\")\n}\n\n//SetTextColor :  function sets the text color\nfunc (gp *GoPdf) SetTextColor(r uint8, g uint8, b uint8) {\n\tgp.curr.txtColorMode = \"color\"\n\trgb := Rgb{\n\t\tr: r,\n\t\tg: g,\n\t\tb: b,\n\t}\n\tgp.curr.setTextColor(rgb)\n}\n\n//SetStrokeColor set the color for the stroke\nfunc (gp *GoPdf) SetStrokeColor(r uint8, g uint8, b uint8) {\n\tgp.getContent().AppendStreamSetColorStroke(r, g, b)\n}\n\n//SetFillColor set the color for the stroke\nfunc (gp *GoPdf) SetFillColor(r uint8, g uint8, b uint8) {\n\tgp.getContent().AppendStreamSetColorFill(r, g, b)\n}\n\n//MeasureTextWidth : measure Width of text (use current font)\nfunc (gp *GoPdf) MeasureTextWidth(text string) (float64, error) {\n\n\terr := gp.curr.FontISubset.AddChars(text) //AddChars for create CharacterToGlyphIndex\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t_, _, textWidthPdfUnit, err := createContent(gp.curr.FontISubset, text, gp.curr.FontSize, nil)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn PointsToUnits(gp.config.Unit, textWidthPdfUnit), nil\n}\n\n//Curve Draws a Bézier curve (the Bézier curve is tangent to the line between the control points at either end of the curve)\n// Parameters:\n// - x0, y0: Start point\n// - x1, y1: Control point 1\n// - x2, y2: Control point 2\n// - x3, y3: End point\n// - style: Style of rectangule (draw and/or fill: D, F, DF, FD)\nfunc (gp *GoPdf) Curve(x0 float64, y0 float64, x1 float64, y1 float64, x2 float64, y2 float64, x3 float64, y3 float64, style string) {\n\tgp.UnitsToPointsVar(&x0, &y0, &x1, &y1, &x2, &y2, &x3, &y3)\n\tgp.getContent().AppendStreamCurve(x0, y0, x1, y1, x2, y2, x3, y3, style)\n}\n\n/*\n//SetProtection set permissions as well as user and owner passwords\nfunc (gp *GoPdf) SetProtection(permissions int, userPass []byte, ownerPass []byte) {\n\tgp.pdfProtection = new(PDFProtection)\n\tgp.pdfProtection.setProtection(permissions, userPass, ownerPass)\n}*/\n\n//SetInfo set Document Information Dictionary\nfunc (gp *GoPdf) SetInfo(info PdfInfo) {\n\tgp.info = &info\n\tgp.isUseInfo = true\n}\n\n//Rotate rotate text or image\n// angle is angle in degrees.\n// x, y is rotation center\nfunc (gp *GoPdf) Rotate(angle, x, y float64) {\n\tgp.UnitsToPointsVar(&x, &y)\n\tgp.getContent().appendRotate(angle, x, y)\n}\n\n//RotateReset reset rotate\nfunc (gp *GoPdf) RotateReset() {\n\tgp.getContent().appendRotateReset()\n}\n\n//Polygon : draw polygon\n// - style: Style of polygon (draw and/or fill: D, F, DF, FD)\n//\t\tD or empty string: draw. This is the default value.\n//\t\tF: fill\n//\t\tDF or FD: draw and fill\n// Usage:\n//  pdf.SetStrokeColor(255, 0, 0)\n//\tpdf.SetLineWidth(2)\n//\tpdf.SetFillColor(0, 255, 0)\n//\tpdf.Polygon([]gopdf.Point{{X: 10, Y: 30}, {X: 585, Y: 200}, {X: 585, Y: 250}}, \"DF\")\nfunc (gp *GoPdf) Polygon(points []Point, style string) {\n\tvar pointReals []Point\n\tfor _, p := range points {\n\t\tx := p.X\n\t\ty := p.Y\n\t\tgp.UnitsToPointsVar(&x, &y)\n\t\tpointReals = append(pointReals, Point{X: x, Y: y})\n\t}\n\tgp.getContent().AppendStreamPolygon(pointReals, style)\n}\n\n/*---private---*/\n\n//init\nfunc (gp *GoPdf) init() {\n\n\t//default\n\tgp.margins = Margins{\n\t\tLeft:   defaultMargin,\n\t\tTop:    defaultMargin,\n\t\tRight:  defaultMargin,\n\t\tBottom: defaultMargin,\n\t}\n\n\t//init curr\n\tgp.resetCurrXY()\n\tgp.curr.IndexOfPageObj = -1\n\tgp.curr.CountOfFont = 0\n\tgp.curr.CountOfL = 0\n\tgp.curr.CountOfImg = 0                       //img\n\tgp.curr.ImgCaches = make(map[int]ImageCache) //= *new([]ImageCache)\n\tgp.curr.sMasksMap = NewSMaskMap()\n\tgp.curr.extGStatesMap = NewExtGStatesMap()\n\tgp.curr.transparencyMap = NewTransparencyMap()\n\tgp.anchors = make(map[string]anchorOption)\n\tgp.curr.txtColorMode = \"gray\"\n\n\t//init index\n\tgp.indexOfPagesObj = -1\n\tgp.indexOfFirstPageObj = -1\n\tgp.indexOfContent = -1\n\n\t//No underline\n\t//gp.IsUnderline = false\n\tgp.curr.lineWidth = 1\n\n\t// default to zlib.DefaultCompression\n\tgp.compressLevel = zlib.DefaultCompression\n\n\t// change the unit type\n\tgp.config.PageSize = *gp.config.PageSize.UnitsToPoints(gp.config.Unit)\n\tgp.config.TrimBox = *gp.config.TrimBox.UnitsToPoints(gp.config.Unit)\n\n\t// init gofpdi free pdf document importer\n\tgp.fpdi = gofpdi.NewImporter()\n}\n\nfunc (gp *GoPdf) resetCurrXY() {\n\tgp.curr.X = gp.margins.Left\n\tgp.curr.Y = gp.margins.Top\n}\n\n// UnitsToPoints converts the units to the documents unit type\nfunc (gp *GoPdf) UnitsToPoints(u float64) float64 {\n\treturn UnitsToPoints(gp.config.Unit, u)\n}\n\n// UnitsToPointsVar converts the units to the documents unit type for all variables passed in\nfunc (gp *GoPdf) UnitsToPointsVar(u ...*float64) {\n\tUnitsToPointsVar(gp.config.Unit, u...)\n}\n\n// PointsToUnits converts the points to the documents unit type\nfunc (gp *GoPdf) PointsToUnits(u float64) float64 {\n\treturn PointsToUnits(gp.config.Unit, u)\n}\n\n//PointsToUnitsVar converts the points to the documents unit type for all variables passed in\nfunc (gp *GoPdf) PointsToUnitsVar(u ...*float64) {\n\tPointsToUnitsVar(gp.config.Unit, u...)\n}\n\nfunc (gp *GoPdf) isUseProtection() bool {\n\treturn gp.config.Protection.UseProtection\n}\n\nfunc (gp *GoPdf) createProtection() *PDFProtection {\n\tvar prot PDFProtection\n\tprot.setProtection(\n\t\tgp.config.Protection.Permissions,\n\t\tgp.config.Protection.UserPass,\n\t\tgp.config.Protection.OwnerPass,\n\t)\n\treturn &prot\n}\n\nfunc (gp *GoPdf) protection() *PDFProtection {\n\treturn gp.pdfProtection\n}\n\nfunc (gp *GoPdf) prepare() {\n\n\tif gp.isUseProtection() {\n\t\tencObj := gp.pdfProtection.encryptionObj()\n\t\tgp.addObj(encObj)\n\t}\n\n\tif gp.outlines.Count() > 0 {\n\t\tcatalogObj := gp.pdfObjs[gp.indexOfCatalogObj].(*CatalogObj)\n\t\tcatalogObj.SetIndexObjOutlines(gp.indexOfOutlinesObj)\n\t}\n\n\tif gp.indexOfPagesObj != -1 {\n\t\tindexCurrPage := -1\n\t\tvar pagesObj *PagesObj\n\t\tpagesObj = gp.pdfObjs[gp.indexOfPagesObj].(*PagesObj)\n\t\ti := 0 //gp.indexOfFirstPageObj\n\t\tmax := len(gp.pdfObjs)\n\t\tfor i < max {\n\t\t\tobjtype := gp.pdfObjs[i].getType()\n\t\t\t//fmt.Printf(\" objtype = %s , %d \\n\", objtype , i)\n\t\t\tswitch objtype {\n\t\t\tcase \"Page\":\n\t\t\t\tpagesObj.Kids = fmt.Sprintf(\"%s %d 0 R \", pagesObj.Kids, i+1)\n\t\t\t\tpagesObj.PageCount++\n\t\t\t\tindexCurrPage = i\n\t\t\tcase \"Content\":\n\t\t\t\tif indexCurrPage != -1 {\n\t\t\t\t\tgp.pdfObjs[indexCurrPage].(*PageObj).Contents = fmt.Sprintf(\"%s %d 0 R \", gp.pdfObjs[indexCurrPage].(*PageObj).Contents, i+1)\n\t\t\t\t}\n\t\t\tcase \"Font\":\n\t\t\t\ttmpfont := gp.pdfObjs[i].(*FontObj)\n\t\t\t\tj := 0\n\t\t\t\tjmax := len(gp.indexEncodingObjFonts)\n\t\t\t\tfor j < jmax {\n\t\t\t\t\ttmpencoding := gp.pdfObjs[gp.indexEncodingObjFonts[j]].(*EncodingObj).GetFont()\n\t\t\t\t\tif tmpfont.Family == tmpencoding.GetFamily() { //ใส่ ข้อมูลของ embed font\n\t\t\t\t\t\ttmpfont.IsEmbedFont = true\n\t\t\t\t\t\ttmpfont.SetIndexObjEncoding(gp.indexEncodingObjFonts[j] + 1)\n\t\t\t\t\t\ttmpfont.SetIndexObjWidth(gp.indexEncodingObjFonts[j] + 2)\n\t\t\t\t\t\ttmpfont.SetIndexObjFontDescriptor(gp.indexEncodingObjFonts[j] + 3)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tj++\n\t\t\t\t}\n\t\t\tcase \"Encryption\":\n\t\t\t\tgp.encryptionObjID = i + 1\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\nfunc (gp *GoPdf) xref(w io.Writer, xrefbyteoffset int, linelens []int, i int) error {\n\n\tio.WriteString(w, \"xref\\n\")\n\tfmt.Fprintf(w, \"0 %d\\n\", i+1)\n\tio.WriteString(w, \"0000000000 65535 f \\n\")\n\tj := 0\n\tmax := len(linelens)\n\tfor j < max {\n\t\tlinelen := linelens[j]\n\t\tfmt.Fprintf(w, \"%s 00000 n \\n\", gp.formatXrefline(linelen))\n\t\tj++\n\t}\n\tio.WriteString(w, \"trailer\\n\")\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"/Size %d\\n\", max+1)\n\tio.WriteString(w, \"/Root 1 0 R\\n\")\n\tif gp.isUseProtection() {\n\t\tfmt.Fprintf(w, \"/Encrypt %d 0 R\\n\", gp.encryptionObjID)\n\t\tio.WriteString(w, \"/ID [()()]\\n\")\n\t}\n\tif gp.isUseInfo {\n\t\tgp.writeInfo(w)\n\t}\n\tio.WriteString(w, \">>\\n\")\n\tio.WriteString(w, \"startxref\\n\")\n\tfmt.Fprintf(w, \"%d\", xrefbyteoffset)\n\tio.WriteString(w, \"\\n%%EOF\\n\")\n\n\treturn nil\n}\n\nfunc (gp *GoPdf) writeInfo(w io.Writer) {\n\tvar zerotime time.Time\n\tio.WriteString(w, \"/Info <<\\n\")\n\n\tif gp.info.Author != \"\" {\n\t\tfmt.Fprintf(w, \"/Author <FEFF%s>\\n\", encodeUtf8(gp.info.Author))\n\t}\n\n\tif gp.info.Title != \"\" {\n\t\tfmt.Fprintf(w, \"/Title <FEFF%s>\\n\", encodeUtf8(gp.info.Title))\n\t}\n\n\tif gp.info.Subject != \"\" {\n\t\tfmt.Fprintf(w, \"/Subject <FEFF%s>\\n\", encodeUtf8(gp.info.Subject))\n\t}\n\n\tif gp.info.Creator != \"\" {\n\t\tfmt.Fprintf(w, \"/Creator <FEFF%s>\\n\", encodeUtf8(gp.info.Creator))\n\t}\n\n\tif gp.info.Producer != \"\" {\n\t\tfmt.Fprintf(w, \"/Producer <FEFF%s>\\n\", encodeUtf8(gp.info.Producer))\n\t}\n\n\tif !zerotime.Equal(gp.info.CreationDate) {\n\t\tfmt.Fprintf(w, \"/CreationDate(D:%s)>>\\n\", infodate(gp.info.CreationDate))\n\t}\n\n\tio.WriteString(w, \" >>\\n\")\n}\n\n//ปรับ xref ให้เป็น 10 หลัก\nfunc (gp *GoPdf) formatXrefline(n int) string {\n\tstr := strconv.Itoa(n)\n\tfor len(str) < 10 {\n\t\tstr = \"0\" + str\n\t}\n\treturn str\n}\n\nfunc (gp *GoPdf) addObj(iobj IObj) int {\n\tindex := len(gp.pdfObjs)\n\tgp.pdfObjs = append(gp.pdfObjs, iobj)\n\treturn index\n}\n\nfunc (gp *GoPdf) getContent() *ContentObj {\n\tvar content *ContentObj\n\tif gp.indexOfContent <= -1 {\n\t\tcontent = new(ContentObj)\n\t\tcontent.init(func() *GoPdf {\n\t\t\treturn gp\n\t\t})\n\t\tgp.indexOfContent = gp.addObj(content)\n\t} else {\n\t\tcontent = gp.pdfObjs[gp.indexOfContent].(*ContentObj)\n\t}\n\treturn content\n}\n\nfunc encodeUtf8(str string) string {\n\tvar buff bytes.Buffer\n\tfor _, r := range str {\n\t\tc := fmt.Sprintf(\"%X\", r)\n\t\tfor len(c) < 4 {\n\t\t\tc = \"0\" + c\n\t\t}\n\t\tbuff.WriteString(c)\n\t}\n\treturn buff.String()\n}\n\nfunc infodate(t time.Time) string {\n\tft := t.Format(\"20060102150405-07'00'\")\n\treturn ft\n}\n\n// SetTransparency sets transparency.\n// alpha: \t\tvalue from 0 (transparent) to 1 (opaque)\n// blendMode:   blend mode, one of the following:\n//          \t\tNormal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn,\n//          \t\tHardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity\nfunc (gp *GoPdf) SetTransparency(transparency Transparency) error {\n\tt, err := gp.saveTransparency(&transparency)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tgp.curr.transparency = t\n\n\treturn nil\n}\n\nfunc (gp *GoPdf) getCachedTransparency(transparency *Transparency) (*Transparency, error) {\n\tif transparency == nil {\n\t\ttransparency = gp.curr.transparency\n\t} else {\n\t\tcached, err := gp.saveTransparency(transparency)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\ttransparency = cached\n\t}\n\n\treturn transparency, nil\n}\n\nfunc (gp *GoPdf) saveTransparency(transparency *Transparency) (*Transparency, error) {\n\tcached, ok := gp.curr.transparencyMap.Find(*transparency)\n\tif ok {\n\t\treturn &cached, nil\n\t} else if transparency.Alpha != DefaultAplhaValue {\n\t\tbm := transparency.BlendModeType\n\t\topts := ExtGStateOptions{\n\t\t\tBlendMode:     &bm,\n\t\t\tStrokingCA:    &transparency.Alpha,\n\t\t\tNonStrokingCa: &transparency.Alpha,\n\t\t}\n\n\t\textGState, err := GetCachedExtGState(opts, gp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\ttransparency.extGStateIndex = extGState.Index + 1\n\n\t\tgp.curr.transparencyMap.Save(*transparency)\n\n\t\treturn transparency, nil\n\t}\n\n\treturn nil, nil\n}\n\n// IsCurrFontContainGlyph defines is current font contains to a glyph\n// r:           any rune\nfunc (gp *GoPdf) IsCurrFontContainGlyph(r rune) (bool, error) {\n\tfontISubset := gp.curr.FontISubset\n\tif fontISubset == nil {\n\t\treturn false, nil\n\t}\n\n\tglyphIndex, err := fontISubset.CharCodeToGlyphIndex(r)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tif glyphIndex == 0 {\n\t\treturn false, nil\n\t}\n\n\treturn true, nil\n}\n\n//tool for validate pdf https://www.pdf-online.com/osa/validate.aspx\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/i_cache_contneter.go",
    "content": "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",
    "content": "package gopdf\n\n// IFont represents a font interface.\ntype IFont interface {\n\tInit()\n\tGetType() string\n\tGetName() string\n\tGetDesc() []FontDescItem\n\tGetUp() int\n\tGetUt() int\n\tGetCw() FontCw\n\tGetEnc() string\n\tGetDiff() string\n\tGetOriginalsize() int\n\n\tSetFamily(family string)\n\tGetFamily() string\n}\n\n// FontCw maps characters to integers.\ntype FontCw map[byte]int\n\n// FontDescItem is a (key, value) pair.\ntype FontDescItem struct {\n\tKey string\n\tVal string\n}\n\n// // Chr\n// func Chr(n int) byte {\n// \treturn byte(n) //ToByte(fmt.Sprintf(\"%c\", n ))\n// }\n\n// ToByte returns the first byte of a string.\nfunc ToByte(chr string) byte {\n\treturn []byte(chr)[0]\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/image_holder.go",
    "content": "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 ImageHolder interface {\n\tID() string\n\tio.Reader\n}\n\n//ImageHolderByBytes create ImageHolder by []byte\nfunc ImageHolderByBytes(b []byte) (ImageHolder, error) {\n\treturn newImageBuff(b)\n}\n\n//ImageHolderByPath create ImageHolder by image path\nfunc ImageHolderByPath(path string) (ImageHolder, error) {\n\treturn newImageBuffByPath(path)\n}\n\n//ImageHolderByReader create ImageHolder by io.Reader\nfunc ImageHolderByReader(r io.Reader) (ImageHolder, error) {\n\treturn newImageBuffByReader(r)\n}\n\n//imageBuff image holder (impl ImageHolder)\ntype imageBuff struct {\n\tid string\n\tbytes.Buffer\n}\n\nfunc newImageBuff(b []byte) (*imageBuff, error) {\n\th := md5.New()\n\t_, err := h.Write(b)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar i imageBuff\n\ti.id = fmt.Sprintf(\"%x\", h.Sum(nil))\n\ti.Write(b)\n\treturn &i, nil\n}\n\nfunc newImageBuffByPath(path string) (*imageBuff, error) {\n\tvar i imageBuff\n\ti.id = path\n\tb, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ti.Write(b)\n\treturn &i, nil\n}\n\nfunc newImageBuffByReader(r io.Reader) (*imageBuff, error) {\n\n\tb, err := ioutil.ReadAll(r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\th := md5.New()\n\t_, err = h.Write(b)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar i imageBuff\n\ti.id = fmt.Sprintf(\"%x\", h.Sum(nil))\n\ti.Write(b)\n\treturn &i, nil\n}\n\nfunc (i *imageBuff) ID() string {\n\treturn i.id\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/image_obj.go",
    "content": "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 code below,\n\t// but are imported for their initialization side-effect, which allows\n\t// image.Decode to understand JPEG formatted images.\n\t_ \"image/jpeg\"\n\t_ \"image/png\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n)\n\n//ImageObj image object\ntype ImageObj struct {\n\t//imagepath string\n\tIsMask        bool\n\tSplittedMask  bool\n\trawImgReader  *bytes.Reader\n\timginfo       imgInfo\n\tpdfProtection *PDFProtection\n\t//getRoot func() *GoPdf\n}\n\nfunc (i *ImageObj) init(funcGetRoot func() *GoPdf) {\n\n}\n\nfunc (i *ImageObj) setProtection(p *PDFProtection) {\n\ti.pdfProtection = p\n}\n\nfunc (i *ImageObj) protection() *PDFProtection {\n\treturn i.pdfProtection\n}\n\nfunc (i *ImageObj) write(w io.Writer, objID int) error {\n\tdata := i.imginfo.data\n\n\tif i.IsMask {\n\t\tdata = i.imginfo.smask\n\t\tif err := writeMaskImgProps(w, i.imginfo); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif err := writeImgProps(w, i.imginfo, i.SplittedMask); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif _, err := fmt.Fprintf(w, \"\\t/Length %d\\n>>\\n\", len(data)); err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := io.WriteString(w, \"stream\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\tif i.protection() != nil {\n\t\ttmp, err := rc4Cip(i.protection().objectkey(objID), data)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif _, err := w.Write(tmp); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err := io.WriteString(w, \"\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif _, err := w.Write(data); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif _, err := io.WriteString(w, \"\\nendstream\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (i *ImageObj) isColspaceIndexed() bool {\n\treturn isColspaceIndexed(i.imginfo)\n}\n\nfunc (i *ImageObj) haveSMask() bool {\n\treturn haveSMask(i.imginfo)\n}\n\nfunc (i *ImageObj) createSMask() (*SMask, error) {\n\tvar smk SMask\n\tsmk.setProtection(i.protection())\n\tsmk.w = i.imginfo.w\n\tsmk.h = i.imginfo.h\n\tsmk.colspace = \"DeviceGray\"\n\tsmk.bitsPerComponent = \"8\"\n\tsmk.filter = i.imginfo.filter\n\tsmk.data = i.imginfo.smask\n\tsmk.decodeParms = fmt.Sprintf(\"/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns %d\", i.imginfo.w)\n\treturn &smk, nil\n}\n\nfunc (i *ImageObj) createDeviceRGB() (*DeviceRGBObj, error) {\n\tvar dRGB DeviceRGBObj\n\tdRGB.data = i.imginfo.pal\n\treturn &dRGB, nil\n}\n\nfunc (i *ImageObj) getType() string {\n\treturn \"Image\"\n}\n\n//SetImagePath set image path\nfunc (i *ImageObj) SetImagePath(path string) error {\n\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer file.Close()\n\n\terr = i.SetImage(file)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//SetImage set image\nfunc (i *ImageObj) SetImage(r io.Reader) error {\n\n\tdata, err := ioutil.ReadAll(r)\n\tif err != nil {\n\t\treturn err\n\t}\n\ti.rawImgReader = bytes.NewReader(data)\n\n\treturn nil\n}\n\n//GetRect get rect of img\nfunc (i *ImageObj) GetRect() *Rect {\n\n\trect, err := i.getRect()\n\tif err != nil {\n\t\tlog.Fatalf(\"%+v\", err)\n\t}\n\treturn rect\n}\n\n//GetRect get rect of img\nfunc (i *ImageObj) getRect() (*Rect, error) {\n\n\ti.rawImgReader.Seek(0, 0)\n\tm, _, err := image.Decode(i.rawImgReader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\timageRect := m.Bounds()\n\tk := 1\n\tw := -128 //init\n\th := -128 //init\n\tif w < 0 {\n\t\tw = -imageRect.Dx() * 72 / w / k\n\t}\n\tif h < 0 {\n\t\th = -imageRect.Dy() * 72 / h / k\n\t}\n\tif w == 0 {\n\t\tw = h * imageRect.Dx() / imageRect.Dy()\n\t}\n\tif h == 0 {\n\t\th = w * imageRect.Dy() / imageRect.Dx()\n\t}\n\n\tvar rect = new(Rect)\n\trect.H = float64(h)\n\trect.W = float64(w)\n\n\treturn rect, nil\n}\n\nfunc (i *ImageObj) parse() error {\n\n\ti.rawImgReader.Seek(0, 0)\n\timginfo, err := parseImg(i.rawImgReader)\n\tif err != nil {\n\t\treturn err\n\t}\n\ti.imginfo = imginfo\n\n\treturn nil\n}\n\n//Parse parse img\nfunc (i *ImageObj) Parse() error {\n\treturn i.parse()\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/image_obj_parse.go",
    "content": "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/ioutil\"\n\t\"strings\"\n)\n\ntype ColorSpaces string\n\nconst (\n\tDeviceGray = \"DeviceGray\"\n)\n\nfunc writeMaskImgProps(w io.Writer, imginfo imgInfo) error {\n\tif err := writeBaseImgProps(w, imginfo, DeviceGray); err != nil {\n\t\treturn err\n\t}\n\n\tdecode := \"\\t/DecodeParms <<\\n\"\n\tdecode += \"\\t\\t/Predictor 15\\n\"\n\tdecode += \"\\t\\t/Colors 1\\n\"\n\tdecode += \"\\t\\t/BitsPerComponent 8\\n\"\n\tdecode += fmt.Sprintf(\"\\t\\t/Columns %d\\n\", imginfo.w)\n\tdecode += \"\\t>>\\n\"\n\n\tif _, err := io.WriteString(w, decode); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc writeImgProps(w io.Writer, imginfo imgInfo, splittedMask bool) error {\n\tif err := writeBaseImgProps(w, imginfo, imginfo.colspace); err != nil {\n\t\treturn err\n\t}\n\n\tif strings.TrimSpace(imginfo.decodeParms) != \"\" {\n\t\tif _, err := fmt.Fprintf(w, \"\\t/DecodeParms <<%s>>\\n\", imginfo.decodeParms); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif splittedMask {\n\t\treturn nil\n\t}\n\n\tif imginfo.trns != nil && len(imginfo.trns) > 0 {\n\t\tj := 0\n\t\tcontent := \"\\t/Mask [\"\n\t\tmax := len(imginfo.trns)\n\n\t\tfor j < max {\n\t\t\tcontent += fmt.Sprintf(\"\\t\\t%d \", imginfo.trns[j])\n\t\t\tcontent += fmt.Sprintf(\"\\t\\t%d \", imginfo.trns[j])\n\t\t\tj++\n\t\t}\n\n\t\tcontent += \"\\t]\\n\"\n\n\t\tif _, err := io.WriteString(w, content); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif haveSMask(imginfo) {\n\t\tif _, err := fmt.Fprintf(w, \"\\t/SMask %d 0 R\\n\", imginfo.smarkObjID+1); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc writeBaseImgProps(w io.Writer, imginfo imgInfo, colorSpace string) error {\n\tcontent := \"<<\\n\"\n\tcontent += \"\\t/Type /XObject\\n\"\n\tcontent += \"\\t/Subtype /Image\\n\"\n\tcontent += fmt.Sprintf(\"\\t/Width %d\\n\", imginfo.w)\n\tcontent += fmt.Sprintf(\"\\t/Height %d\\n\", imginfo.h)\n\n\tif isColspaceIndexed(imginfo) {\n\t\tsize := len(imginfo.pal)/3 - 1\n\t\tcontent += fmt.Sprintf(\"\\t/ColorSpace [/Indexed /DeviceRGB %d %d 0 R]\\n\", size, imginfo.deviceRGBObjID+1)\n\t} else {\n\t\tcontent += fmt.Sprintf(\"\\t/ColorSpace /%s\\n\", colorSpace)\n\t\tif imginfo.colspace == \"DeviceCMYK\" {\n\t\t\tcontent += \"\\t/Decode [1 0 1 0 1 0 1 0]\\n\"\n\t\t}\n\t}\n\n\tcontent += fmt.Sprintf(\"\\t/BitsPerComponent %s\\n\", imginfo.bitsPerComponent)\n\n\tif strings.TrimSpace(imginfo.filter) != \"\" {\n\t\tcontent += fmt.Sprintf(\"\\t/Filter /%s\\n\", imginfo.filter)\n\t}\n\n\tif _, err := io.WriteString(w, content); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc isColspaceIndexed(imginfo imgInfo) bool {\n\tif imginfo.colspace == \"Indexed\" {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc haveSMask(imginfo imgInfo) bool {\n\tif imginfo.smask != nil && len(imginfo.smask) > 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc parseImgByPath(path string) (imgInfo, error) {\n\tdata, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn imgInfo{}, err\n\t}\n\treturn parseImg(bytes.NewReader(data))\n}\n\nfunc parseImg(raw *bytes.Reader) (imgInfo, error) {\n\t//fmt.Printf(\"----------\\n\")\n\tvar info imgInfo\n\traw.Seek(0, 0)\n\timgConfig, formatname, err := image.DecodeConfig(raw)\n\tif err != nil {\n\t\treturn info, err\n\t}\n\tinfo.formatName = formatname\n\n\tif formatname == \"jpeg\" {\n\n\t\terr = parseImgJpg(&info, imgConfig)\n\t\tif err != nil {\n\t\t\treturn info, err\n\t\t}\n\t\traw.Seek(0, 0)\n\t\tinfo.data, err = ioutil.ReadAll(raw)\n\t\tif err != nil {\n\t\t\treturn info, err\n\t\t}\n\n\t} else if formatname == \"png\" {\n\t\terr = parsePng(raw, &info, imgConfig)\n\t\tif err != nil {\n\t\t\treturn info, err\n\t\t}\n\t}\n\n\t//fmt.Printf(\"%#v\\n\", info)\n\n\treturn info, nil\n}\n\nfunc parseImgJpg(info *imgInfo, imgConfig image.Config) error {\n\tswitch imgConfig.ColorModel {\n\tcase color.YCbCrModel:\n\t\tinfo.colspace = \"DeviceRGB\"\n\tcase color.GrayModel:\n\t\tinfo.colspace = \"DeviceGray\"\n\tcase color.CMYKModel:\n\t\tinfo.colspace = \"DeviceCMYK\"\n\tdefault:\n\t\treturn errors.New(\"color model not support\")\n\t}\n\tinfo.bitsPerComponent = \"8\"\n\tinfo.filter = \"DCTDecode\"\n\n\tinfo.h = imgConfig.Height\n\tinfo.w = imgConfig.Width\n\n\treturn nil\n}\n\nvar pngMagicNumber = []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}\nvar pngIHDR = []byte{0x49, 0x48, 0x44, 0x52}\n\nfunc parsePng(f *bytes.Reader, info *imgInfo, imgConfig image.Config) error {\n\t//f := bytes.NewReader(raw)\n\tf.Seek(0, 0)\n\tb, err := readBytes(f, 8)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !bytes.Equal(b, pngMagicNumber) {\n\t\treturn errors.New(\"Not a PNG file\")\n\t}\n\n\tf.Seek(4, 1) //skip header chunk\n\tb, err = readBytes(f, 4)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !bytes.Equal(b, pngIHDR) {\n\t\treturn errors.New(\"Incorrect PNG file\")\n\t}\n\n\tw, err := readInt(f)\n\tif err != nil {\n\t\treturn err\n\t}\n\th, err := readInt(f)\n\tif err != nil {\n\t\treturn err\n\t}\n\t//fmt.Printf(\"w=%d h=%d\\n\", w, h)\n\n\tbpc, err := readBytes(f, 1)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif bpc[0] > 8 {\n\t\treturn errors.New(\"16-bit depth not supported\")\n\t}\n\n\tct, err := readBytes(f, 1)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar colspace string\n\tswitch ct[0] {\n\tcase 0, 4:\n\t\tcolspace = \"DeviceGray\"\n\tcase 2, 6:\n\t\tcolspace = \"DeviceRGB\"\n\tcase 3:\n\t\tcolspace = \"Indexed\"\n\tdefault:\n\t\treturn errors.New(\"Unknown color type\")\n\t}\n\n\tcompressionMethod, err := readBytes(f, 1)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif compressionMethod[0] != 0 {\n\t\treturn errors.New(\"Unknown compression method\")\n\t}\n\n\tfilterMethod, err := readBytes(f, 1)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif filterMethod[0] != 0 {\n\t\treturn errors.New(\"Unknown filter method\")\n\t}\n\n\tinterlacing, err := readBytes(f, 1)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif interlacing[0] != 0 {\n\t\treturn errors.New(\"Interlacing not supported\")\n\t}\n\n\t_, err = f.Seek(4, 1) //skip\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t//decodeParms := \"/Predictor 15 /Colors '.($colspace=='DeviceRGB' ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w;\n\n\tvar pal []byte\n\tvar trns []byte\n\tvar data []byte\n\tfor {\n\t\tun, err := readUInt(f)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tn := int(un)\n\t\ttyp, err := readBytes(f, 4)\n\t\t//fmt.Printf(\">>>>%+v-%s-%d\\n\", typ, string(typ), n)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif string(typ) == \"PLTE\" {\n\t\t\tpal, err = readBytes(f, n)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t_, err = f.Seek(int64(4), 1) //skip\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else if string(typ) == \"tRNS\" {\n\n\t\t\tvar t []byte\n\t\t\tt, err = readBytes(f, n)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif ct[0] == 0 {\n\t\t\t\ttrns = []byte{(t[1])}\n\t\t\t} else if ct[0] == 2 {\n\t\t\t\ttrns = []byte{t[1], t[3], t[5]}\n\t\t\t} else {\n\t\t\t\tpos := strings.Index(string(t), \"\\x00\")\n\t\t\t\tif pos >= 0 {\n\t\t\t\t\ttrns = []byte{byte(pos)}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_, err = f.Seek(int64(4), 1) //skip\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t} else if string(typ) == \"IDAT\" {\n\t\t\t//fmt.Printf(\"n=%d\\n\\n\", n)\n\t\t\tvar d []byte\n\t\t\td, err = readBytes(f, n)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdata = append(data, d...)\n\t\t\t_, err = f.Seek(int64(4), 1) //skip\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else if string(typ) == \"IEND\" {\n\t\t\tbreak\n\t\t} else {\n\t\t\t_, err = f.Seek(int64(n+4), 1) //skip\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tif n <= 0 {\n\t\t\tbreak\n\t\t}\n\t} //end for\n\n\t//info.data = data //ok\n\tinfo.trns = trns\n\tinfo.pal = pal\n\n\t//fmt.Printf(\"data= %x\", md5.Sum(data))\n\n\tif colspace == \"Indexed\" && strings.TrimSpace(string(pal)) == \"\" {\n\t\treturn errors.New(\"Missing palette\")\n\t}\n\n\tinfo.w = w\n\tinfo.h = h\n\tinfo.colspace = colspace\n\tinfo.bitsPerComponent = fmt.Sprintf(\"%d\", int(bpc[0]))\n\tinfo.filter = \"FlateDecode\"\n\n\tcolors := 1\n\tif colspace == \"DeviceRGB\" {\n\t\tcolors = 3\n\t}\n\tinfo.decodeParms = fmt.Sprintf(\"/Predictor 15 /Colors  %d /BitsPerComponent %s /Columns %d\", colors, info.bitsPerComponent, w)\n\n\t//fmt.Printf(\"%d = ct[0]\\n\", ct[0])\n\t//fmt.Printf(\"%x\\n\", md5.Sum(data))\n\tif ct[0] >= 4 {\n\t\tzipReader, err := zlib.NewReader(bytes.NewReader(data))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer zipReader.Close()\n\t\tafterZipData, err := ioutil.ReadAll(zipReader)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tvar color []byte\n\t\tvar alpha []byte\n\t\tif ct[0] == 4 {\n\t\t\t// Gray image\n\t\t\tlength := 2 * w\n\t\t\ti := 0\n\t\t\tfor i < h {\n\t\t\t\tpos := (1 + length) * i\n\t\t\t\tcolor = append(color, afterZipData[pos])\n\t\t\t\talpha = append(alpha, afterZipData[pos])\n\t\t\t\tline := afterZipData[pos+1 : pos+length+1]\n\t\t\t\tj := 0\n\t\t\t\tmax := len(line)\n\t\t\t\tfor j < max {\n\t\t\t\t\tcolor = append(color, line[j])\n\t\t\t\t\tj++\n\t\t\t\t\talpha = append(alpha, line[j])\n\t\t\t\t\tj++\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\t//fmt.Print(\"aaaaa\")\n\n\t\t} else {\n\t\t\t// RGB image\n\t\t\tlength := 4 * w\n\t\t\ti := 0\n\t\t\tfor i < h {\n\t\t\t\tpos := (1 + length) * i\n\t\t\t\tcolor = append(color, afterZipData[pos])\n\t\t\t\talpha = append(alpha, afterZipData[pos])\n\t\t\t\tline := afterZipData[pos+1 : pos+length+1]\n\t\t\t\tj := 0\n\t\t\t\tmax := len(line)\n\t\t\t\tfor j < max {\n\t\t\t\t\tcolor = append(color, line[j:j+3]...)\n\t\t\t\t\talpha = append(alpha, line[j+3])\n\t\t\t\t\tj = j + 4\n\t\t\t\t}\n\n\t\t\t\ti++\n\t\t\t}\n\t\t\tinfo.smask, err = compress(alpha)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tinfo.data, err = compress(color)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tinfo.data = data\n\t}\n\n\treturn nil\n}\n\nfunc compress(data []byte) ([]byte, error) {\n\tvar results []byte\n\tvar buff bytes.Buffer\n\tzwr, err := zlib.NewWriterLevel(&buff, zlib.BestSpeed)\n\n\tif err != nil {\n\t\treturn results, err\n\t}\n\t_, err = zwr.Write(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tzwr.Close()\n\treturn buff.Bytes(), nil\n}\n\nfunc readUInt(f *bytes.Reader) (uint, error) {\n\tbuff, err := readBytes(f, 4)\n\t//fmt.Printf(\"%#v\\n\\n\", buff)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tn := binary.BigEndian.Uint32(buff)\n\treturn uint(n), nil\n}\n\nfunc readInt(f *bytes.Reader) (int, error) {\n\n\tu, err := readUInt(f)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tvar v int\n\tif u >= 0x8000 {\n\t\tv = int(u) - 65536\n\t} else {\n\t\tv = int(u)\n\t}\n\treturn v, nil\n}\n\nfunc readBytes(f *bytes.Reader, len int) ([]byte, error) {\n\tb := make([]byte, len)\n\t_, err := f.Read(b)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\nfunc isDeviceRGB(formatname string, img *image.Image) bool {\n\tif _, ok := (*img).(*image.YCbCr); ok {\n\t\treturn true\n\t} else if _, ok := (*img).(*image.NRGBA); ok {\n\t\treturn true\n\t}\n\treturn false\n}\n\n//ImgReactagleToWH  Rectangle to W and H\nfunc ImgReactagleToWH(imageRect image.Rectangle) (float64, float64) {\n\tk := 1\n\tw := -128 //init\n\th := -128 //init\n\tif w < 0 {\n\t\tw = -imageRect.Dx() * 72 / w / k\n\t}\n\tif h < 0 {\n\t\th = -imageRect.Dy() * 72 / h / k\n\t}\n\tif w == 0 {\n\t\tw = h * imageRect.Dx() / imageRect.Dy()\n\t}\n\tif h == 0 {\n\t\th = w * imageRect.Dy() / imageRect.Dx()\n\t}\n\treturn float64(w), float64(h)\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/img_info.go",
    "content": "package gopdf\n\ntype imgInfo struct {\n\tw, h int\n\t//src              string\n\tformatName       string\n\tcolspace         string\n\tbitsPerComponent string\n\tfilter           string\n\tdecodeParms      string\n\ttrns             []byte\n\tsmask            []byte\n\tsmarkObjID       int\n\tpal              []byte\n\tdeviceRGBObjID   int\n\tdata             []byte\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/imported_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"io\"\n)\n\n//ImportedObj : imported object\ntype ImportedObj struct { //impl IObj\n\tData string\n}\n\nfunc (c *ImportedObj) init(funcGetRoot func() *GoPdf) {\n\n}\n\nfunc (c *ImportedObj) getType() string {\n\treturn \"Imported\"\n}\n\nfunc (c *ImportedObj) write(w io.Writer, objID int) error {\n\tif c != nil {\n\t\tio.WriteString(w, c.Data)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/iobj.go",
    "content": "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() string\n\twrite(w io.Writer, objID int) error\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/link_option.go",
    "content": "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        string\n\tanchor     string\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/list_cache_content.go",
    "content": "package gopdf\n\nimport \"io\"\n\ntype listCacheContent struct {\n\tcaches []ICacheContent\n}\n\nfunc (l *listCacheContent) last() ICacheContent {\n\tmax := len(l.caches)\n\tif max > 0 {\n\t\treturn l.caches[max-1]\n\t}\n\treturn nil\n}\n\nfunc (l *listCacheContent) append(cache ICacheContent) {\n\tl.caches = append(l.caches, cache)\n}\n\nfunc (l *listCacheContent) appendContentText(cache cacheContentText, text string) (float64, float64, error) {\n\n\tx := cache.x\n\ty := cache.y\n\n\tmustMakeNewCache := true\n\tvar cacheFont *cacheContentText\n\tvar ok bool\n\tlast := l.last()\n\tif cacheFont, ok = last.(*cacheContentText); ok {\n\t\tif cacheFont != nil {\n\t\t\tif cacheFont.isSame(cache) {\n\t\t\t\tmustMakeNewCache = false\n\t\t\t}\n\t\t}\n\t}\n\n\tif mustMakeNewCache { //make new cell\n\t\tl.caches = append(l.caches, &cache)\n\t\tcacheFont = &cache\n\t}\n\n\t//start add text\n\tcacheFont.text += text\n\n\t//re-create contnet\n\ttextWidthPdfUnit, textHeightPdfUnit, err := cacheFont.createContent()\n\tif err != nil {\n\t\treturn x, y, err\n\t}\n\n\tif cacheFont.cellOpt.Float == 0 || cacheFont.cellOpt.Float&Right == Right || cacheFont.contentType == ContentTypeText {\n\t\tx += textWidthPdfUnit\n\t}\n\tif cacheFont.cellOpt.Float&Bottom == Bottom {\n\t\ty += textHeightPdfUnit\n\t}\n\n\treturn x, y, nil\n}\n\nfunc (l *listCacheContent) write(w io.Writer, protection *PDFProtection) error {\n\tfor _, cache := range l.caches {\n\t\tif err := cache.write(w, protection); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/map_of_character_To_glyph_index.go",
    "content": "package gopdf\n\n//MapOfCharacterToGlyphIndex map of CharacterToGlyphIndex\ntype MapOfCharacterToGlyphIndex struct {\n\tkeyIndexs map[rune]int //for search index in keys\n\tKeys      []rune\n\tVals      []uint\n}\n\n//NewMapOfCharacterToGlyphIndex new CharacterToGlyphIndex\nfunc NewMapOfCharacterToGlyphIndex() *MapOfCharacterToGlyphIndex {\n\tvar m MapOfCharacterToGlyphIndex\n\tm.keyIndexs = make(map[rune]int)\n\treturn &m\n}\n\n//KeyExists key is exists?\nfunc (m *MapOfCharacterToGlyphIndex) KeyExists(k rune) bool {\n\t/*for _, key := range m.Keys {\n\t\tif k == key {\n\t\t\treturn true\n\t\t}\n\t}*/\n\tif _, ok := m.keyIndexs[k]; ok {\n\t\treturn true\n\t}\n\treturn false\n}\n\n//Set set key and value to map\nfunc (m *MapOfCharacterToGlyphIndex) Set(k rune, v uint) {\n\tm.keyIndexs[k] = len(m.Keys)\n\tm.Keys = append(m.Keys, k)\n\tm.Vals = append(m.Vals, v)\n}\n\n//Index get index by key\nfunc (m *MapOfCharacterToGlyphIndex) Index(k rune) (int, bool) {\n\t/*for i, key := range m.Keys {\n\t\tif k == key {\n\t\t\treturn i, true\n\t\t}\n\t}*/\n\tif index, ok := m.keyIndexs[k]; ok {\n\t\treturn index, true\n\t}\n\treturn -1, false\n}\n\n//Val get value by Key\nfunc (m *MapOfCharacterToGlyphIndex) Val(k rune) (uint, bool) {\n\ti, ok := m.Index(k)\n\tif !ok {\n\t\treturn 0, false\n\t}\n\treturn m.Vals[i], true\n}\n\n//AllKeys get keys\nfunc (m *MapOfCharacterToGlyphIndex) AllKeys() []rune {\n\treturn m.Keys\n}\n\n//AllVals get all values\nfunc (m *MapOfCharacterToGlyphIndex) AllVals() []uint {\n\treturn m.Vals\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/margin.go",
    "content": "package gopdf\n\n// Margins type.\ntype Margins struct {\n\tLeft, Top, Right, Bottom float64\n}\n\n// SetLeftMargin sets left margin.\nfunc (gp *GoPdf) SetLeftMargin(margin float64) {\n\tgp.UnitsToPointsVar(&margin)\n\tgp.margins.Left = margin\n}\n\n// SetTopMargin sets top margin.\nfunc (gp *GoPdf) SetTopMargin(margin float64) {\n\tgp.UnitsToPointsVar(&margin)\n\tgp.margins.Top = margin\n}\n\n// SetMargins defines the left, top, right and bottom margins. By default, they equal 1 cm. Call this method to change them.\nfunc (gp *GoPdf) SetMargins(left, top, right, bottom float64) {\n\tgp.UnitsToPointsVar(&left, &top, &right, &bottom)\n\tgp.margins = Margins{left, top, right, bottom}\n}\n\n// SetMarginLeft sets the left margin\nfunc (gp *GoPdf) SetMarginLeft(margin float64) {\n\tgp.margins.Left = gp.UnitsToPoints(margin)\n}\n\n// SetMarginTop sets the top margin\nfunc (gp *GoPdf) SetMarginTop(margin float64) {\n\tgp.margins.Top = gp.UnitsToPoints(margin)\n}\n\n// SetMarginRight sets the right margin\nfunc (gp *GoPdf) SetMarginRight(margin float64) {\n\tgp.margins.Right = gp.UnitsToPoints(margin)\n}\n\n// SetMarginBottom set the bottom margin\nfunc (gp *GoPdf) SetMarginBottom(margin float64) {\n\tgp.margins.Bottom = gp.UnitsToPoints(margin)\n}\n\n// Margins gets the current margins, The margins will be converted back to the documents units. Returned values will be in the following order Left, Top, Right, Bottom\nfunc (gp *GoPdf) Margins() (float64, float64, float64, float64) {\n\treturn gp.PointsToUnits(gp.margins.Left),\n\t\tgp.PointsToUnits(gp.margins.Top),\n\t\tgp.PointsToUnits(gp.margins.Right),\n\t\tgp.PointsToUnits(gp.margins.Bottom)\n}\n\n// MarginLeft returns the left margin.\nfunc (gp *GoPdf) MarginLeft() float64 {\n\treturn gp.PointsToUnits(gp.margins.Left)\n}\n\n// MarginTop returns the top margin.\nfunc (gp *GoPdf) MarginTop() float64 {\n\treturn gp.PointsToUnits(gp.margins.Top)\n}\n\n// MarginRight returns the right margin.\nfunc (gp *GoPdf) MarginRight() float64 {\n\treturn gp.PointsToUnits(gp.margins.Right)\n}\n\n// MarginBottom returns the bottom margin.\nfunc (gp *GoPdf) MarginBottom() float64 {\n\treturn gp.PointsToUnits(gp.margins.Bottom)\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/outlines_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//OutlinesObj : outlines dictionary\ntype OutlinesObj struct { //impl IObj\n\tgetRoot func() *GoPdf\n\n\tindex   int\n\tfirst   int\n\tlast    int\n\tcount   int\n\tlastObj *OutlineObj\n}\n\nfunc (o *OutlinesObj) init(funcGetRoot func() *GoPdf) {\n\to.getRoot = funcGetRoot\n\to.first = -1\n\to.last = -1\n}\n\nfunc (o *OutlinesObj) getType() string {\n\treturn \"Outlines\"\n}\n\nfunc (o *OutlinesObj) write(w io.Writer, objID int) error {\n\tcontent := \"<<\\n\"\n\tcontent += fmt.Sprintf(\"\\t/Type /%s\\n\", o.getType())\n\tcontent += fmt.Sprintf(\"\\t/Count %d\\n\", o.count)\n\n\tif o.first >= 0 {\n\t\tcontent += fmt.Sprintf(\"\\t/First %d 0 R\\n\", o.first)\n\t}\n\n\tif o.last >= 0 {\n\t\tcontent += fmt.Sprintf(\"\\t/Last %d 0 R\\n\", o.last)\n\t}\n\n\tcontent += \">>\\n\"\n\n\tif _, err := io.WriteString(w, content); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (o *OutlinesObj) SetIndexObjOutlines(index int) {\n\to.index = index\n}\n\nfunc (o *OutlinesObj) AddOutline(dest int, title string) {\n\too := &OutlineObj{title: title, dest: dest, parent: o.index, prev: o.last, next: -1}\n\to.last = o.getRoot().addObj(oo) + 1\n\tif o.first <= 0 {\n\t\to.first = o.last\n\t}\n\tif o.lastObj != nil {\n\t\to.lastObj.next = o.last\n\t}\n\to.lastObj = oo\n\to.count++\n}\n\nfunc (o *OutlinesObj) Count() int {\n\treturn o.count\n}\n\ntype OutlineObj struct { //impl IObj\n\ttitle string\n\n\tdest   int\n\tparent int\n\tprev   int\n\tnext   int\n}\n\nfunc (o *OutlineObj) init(funcGetRoot func() *GoPdf) {\n}\n\nfunc (o *OutlineObj) getType() string {\n\treturn \"Outline\"\n}\n\nfunc (o *OutlineObj) write(w io.Writer, objID int) error {\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"  /Parent %d 0 R\\n\", o.parent+1)\n\tif o.prev >= 0 {\n\t\tfmt.Fprintf(w, \"  /Prev %d 0 R\\n\", o.prev)\n\t}\n\tif o.next >= 0 {\n\t\tfmt.Fprintf(w, \"  /Next %d 0 R\\n\", o.next)\n\t}\n\tfmt.Fprintf(w, \"  /Dest [ %d 0 R /XYZ null null null ]\\n\", o.dest)\n\tfmt.Fprintf(w, \"  /Title <FEFF%s>\\n\", encodeUtf8(o.title))\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/page_obj.go",
    "content": "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        string\n\tResourcesRelate string\n\tpageOption      PageOption\n\tLinks           []linkOption\n\tgetRoot         func() *GoPdf\n}\n\nfunc (p *PageObj) init(funcGetRoot func() *GoPdf) {\n\tp.getRoot = funcGetRoot\n\tp.Links = make([]linkOption, 0)\n}\n\nfunc (p *PageObj) setOption(opt PageOption) {\n\tp.pageOption = opt\n}\n\nfunc (p *PageObj) write(w io.Writer, objID int) error {\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"  /Type /%s\\n\", p.getType())\n\tio.WriteString(w, \"  /Parent 2 0 R\\n\")\n\tfmt.Fprintf(w, \"  /Resources %s\\n\", p.ResourcesRelate)\n\n\tvar err error\n\tgp := p.getRoot()\n\tif len(p.Links) > 0 {\n\t\tio.WriteString(w, \"  /Annots [\")\n\t\tfor _, l := range p.Links {\n\t\t\tif l.url != \"\" {\n\t\t\t\terr = p.writeExternalLink(w, l, objID)\n\t\t\t} else {\n\t\t\t\terr = p.writeInternalLink(w, l, gp.anchors)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tio.WriteString(w, \"]\\n\")\n\t}\n\n\t/*me.buffer.WriteString(\"    /Font <<\\n\")\n\ti := 0\n\tmax := len(me.Realtes)\n\tfor i < max {\n\t\trealte := me.Realtes[i]\n\t\tme.buffer.WriteString(fmt.Sprintf(\"      /F%d %d 0 R\\n\",realte.CountOfFont + 1, realte.IndexOfObj + 1))\n\t\ti++\n\t}\n\tme.buffer.WriteString(\"    >>\\n\")*/\n\t//me.buffer.WriteString(\"  >>\\n\")\n\tfmt.Fprintf(w, \"  /Contents %s\\n\", p.Contents) //sample  Contents 8 0 R\n\tif !p.pageOption.isEmpty() {\n\t\tfmt.Fprintf(w, \" /MediaBox [ 0 0 %0.2f %0.2f ]\\n\", p.pageOption.PageSize.W, p.pageOption.PageSize.H)\n\t}\n\tif p.pageOption.isTrimBoxSet() {\n\t\ttrimBox := p.pageOption.TrimBox\n\t\tfmt.Fprintf(w, \" /TrimBox [ %0.2f %0.2f %0.2f %0.2f ]\\n\", trimBox.Left, trimBox.Top, trimBox.Right, trimBox.Bottom)\n\t}\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\nfunc (p *PageObj) writeExternalLink(w io.Writer, l linkOption, objID int) error {\n\tprotection := p.getRoot().protection()\n\turl := l.url\n\tif protection != nil {\n\t\ttmp, err := rc4Cip(protection.objectkey(objID), []byte(url))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\turl = string(tmp)\n\t}\n\turl = strings.Replace(url, \"\\\\\", \"\\\\\\\\\", -1)\n\turl = strings.Replace(url, \"(\", \"\\\\(\", -1)\n\turl = strings.Replace(url, \")\", \"\\\\)\", -1)\n\turl = strings.Replace(url, \"\\r\", \"\\\\r\", -1)\n\n\t_, err := fmt.Fprintf(w, \"<</Type /Annot /Subtype /Link /Rect [%.2f %.2f %.2f %.2f] /Border [0 0 0] /A <</S /URI /URI (%s)>>>>\",\n\t\tl.x, l.y, l.x+l.w, l.y-l.h, url)\n\treturn err\n}\n\nfunc (p *PageObj) writeInternalLink(w io.Writer, l linkOption, anchors map[string]anchorOption) error {\n\ta, ok := anchors[l.anchor]\n\tif !ok {\n\t\treturn nil\n\t}\n\t_, err := fmt.Fprintf(w, \"<</Type /Annot /Subtype /Link /Rect [%.2f %.2f %.2f %.2f] /Border [0 0 0] /Dest [%d 0 R /XYZ 0 %.2f null]>>\",\n\t\tl.x, l.y, l.x+l.w, l.y-l.h, a.page+1, a.y)\n\treturn err\n}\n\nfunc (p *PageObj) getType() string {\n\treturn \"Page\"\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/page_option.go",
    "content": "package gopdf\n\n//PageOption option of page\ntype PageOption struct {\n\tTrimBox  *Box\n\tPageSize *Rect\n}\n\nfunc (p PageOption) isEmpty() bool {\n\tif p.PageSize == nil {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (p PageOption) isTrimBoxSet() bool {\n\tif p.TrimBox == nil {\n\t\treturn false\n\t}\n\tif p.TrimBox.Top == 0 && p.TrimBox.Left == 0 && p.TrimBox.Bottom == 0 && p.TrimBox.Right == 0 {\n\t\treturn false\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/page_sizes.go",
    "content": "package gopdf\n\n// PageSizeLetter page format\nvar PageSizeLetter = &Rect{W: 612, H: 792, unitOverride: UnitPT}\n\n// PageSizeLetterSmall page format\nvar PageSizeLetterSmall = &Rect{W: 612, H: 792, unitOverride: UnitPT}\n\n// PageSizeTabloid page format\nvar PageSizeTabloid = &Rect{W: 792, H: 1224, unitOverride: UnitPT}\n\n// PageSizeLedger page format\nvar PageSizeLedger = &Rect{W: 1224, H: 792, unitOverride: UnitPT}\n\n// PageSizeLegal page format\nvar PageSizeLegal = &Rect{W: 612, H: 1008, unitOverride: UnitPT}\n\n// PageSizeStatement page format\nvar PageSizeStatement = &Rect{W: 396, H: 612, unitOverride: UnitPT}\n\n// PageSizeExecutive page format\nvar PageSizeExecutive = &Rect{W: 540, H: 720, unitOverride: UnitPT}\n\n// PageSizeA0 page format\nvar PageSizeA0 = &Rect{W: 2384, H: 3371, unitOverride: UnitPT}\n\n// PageSizeA1 page format\nvar PageSizeA1 = &Rect{W: 1685, H: 2384, unitOverride: UnitPT}\n\n// PageSizeA2 page format\nvar PageSizeA2 = &Rect{W: 1190, H: 1684, unitOverride: UnitPT}\n\n// PageSizeA3 page format\nvar PageSizeA3 = &Rect{W: 842, H: 1190, unitOverride: UnitPT}\n\n// PageSizeA4 page format\nvar PageSizeA4 = &Rect{W: 595, H: 842, unitOverride: UnitPT}\n\n// PageSizeA4Small page format\nvar PageSizeA4Small = &Rect{W: 595, H: 842, unitOverride: UnitPT}\n\n// PageSizeA5 page format\nvar PageSizeA5 = &Rect{W: 420, H: 595, unitOverride: UnitPT}\n\n// PageSizeB4 page format\nvar PageSizeB4 = &Rect{W: 729, H: 1032, unitOverride: UnitPT}\n\n// PageSizeB5 page format\nvar PageSizeB5 = &Rect{W: 516, H: 729, unitOverride: UnitPT}\n\n// PageSizeFolio page format\nvar PageSizeFolio = &Rect{W: 612, H: 936, unitOverride: UnitPT}\n\n// PageSizeQuarto page format\nvar PageSizeQuarto = &Rect{W: 610, H: 780, unitOverride: UnitPT}\n\n// PageSize10x14 page format\nvar PageSize10x14 = &Rect{W: 720, H: 1008, unitOverride: UnitPT}\n\n// // PageSizeEnvelope page format\n// var PageSizeEnvelope\t= Rect{W:???,H:???}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pages_obj.go",
    "content": "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\tKids      string\n\tgetRoot   func() *GoPdf\n}\n\nfunc (p *PagesObj) init(funcGetRoot func() *GoPdf) {\n\tp.PageCount = 0\n\tp.getRoot = funcGetRoot\n}\n\nfunc (p *PagesObj) write(w io.Writer, objID int) error {\n\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"  /Type /%s\\n\", p.getType())\n\n\trootConfig := p.getRoot().config\n\tfmt.Fprintf(w, \"  /MediaBox [ 0 0 %0.2f %0.2f ]\\n\", rootConfig.PageSize.W, rootConfig.PageSize.H)\n\tfmt.Fprintf(w, \"  /Count %d\\n\", p.PageCount)\n\tfmt.Fprintf(w, \"  /Kids [ %s ]\\n\", p.Kids) //sample Kids [ 3 0 R ]\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\nfunc (p *PagesObj) getType() string {\n\treturn \"Pages\"\n}\n\nfunc (p *PagesObj) test() {\n\tfmt.Print(p.getType() + \"\\n\")\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pdf_dictionary_obj.go",
    "content": "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)\n\n//EntrySelectors entry selectors\nvar EntrySelectors = []int{\n\t0, 0, 1, 1, 2, 2,\n\t2, 2, 3, 3, 3, 3,\n\t3, 3, 3, 3, 4, 4,\n\t4, 4, 4, 4, 4, 4,\n\t4, 4, 4, 4, 4, 4, 4,\n}\n\n//ErrNotSupportShortIndexYet not suport none short index yet\nvar ErrNotSupportShortIndexYet = errors.New(\"not suport none short index yet\")\n\n//PdfDictionaryObj pdf dictionary object\ntype PdfDictionaryObj struct {\n\tPtrToSubsetFontObj *SubsetFontObj\n\t//getRoot            func() *GoPdf\n\tpdfProtection *PDFProtection\n}\n\nfunc (p *PdfDictionaryObj) init(funcGetRoot func() *GoPdf) {\n\t//p.getRoot = funcGetRoot\n}\n\nfunc (p *PdfDictionaryObj) setProtection(pr *PDFProtection) {\n\tp.pdfProtection = pr\n}\n\nfunc (p *PdfDictionaryObj) protection() *PDFProtection {\n\treturn p.pdfProtection\n}\n\nfunc (p *PdfDictionaryObj) write(w io.Writer, objID int) error {\n\tb, err := p.makeFont()\n\tif err != nil {\n\t\t//log.Panicf(\"%s\", err.Error())\n\t\treturn err\n\t}\n\n\t//zipvar buff bytes.Buffer\n\tzbuff := GetBuffer()\n\tdefer PutBuffer(zbuff)\n\n\tgzipwriter := zlib.NewWriter(zbuff)\n\t_, err = gzipwriter.Write(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tgzipwriter.Close()\n\n\tfmt.Fprintf(w, \"<</Length %d\\n\", zbuff.Len())\n\tio.WriteString(w, \"/Filter /FlateDecode\\n\")\n\tfmt.Fprintf(w, \"/Length1 %d\\n\", len(b))\n\tio.WriteString(w, \">>\\n\")\n\tio.WriteString(w, \"stream\\n\")\n\tif p.protection() != nil {\n\t\ttmp, err := rc4Cip(p.protection().objectkey(objID), zbuff.Bytes())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tw.Write(tmp)\n\t\t//p.buffer.WriteString(\"\\n\")\n\t} else {\n\t\tw.Write(zbuff.Bytes())\n\t}\n\tio.WriteString(w, \"\\nendstream\\n\")\n\n\treturn nil\n}\n\nfunc (p *PdfDictionaryObj) getType() string {\n\treturn \"PdfDictionary\"\n}\n\n//SetPtrToSubsetFontObj set subsetFontObj pointer\nfunc (p *PdfDictionaryObj) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {\n\tp.PtrToSubsetFontObj = ptr\n}\n\nfunc (p *PdfDictionaryObj) makeGlyfAndLocaTable() ([]byte, []int, error) {\n\tttfp := p.PtrToSubsetFontObj.GetTTFParser()\n\tvar glyf core.TableDirectoryEntry\n\n\tnumGlyphs := int(ttfp.NumGlyphs())\n\n\tglyphArray := p.completeGlyphClosure(p.PtrToSubsetFontObj.CharacterToGlyphIndex)\n\tsort.Ints(glyphArray)\n\tglyphCount := len(glyphArray)\n\n\tsize := 0\n\tfor idx := 0; idx < glyphCount; idx++ {\n\t\tsize += p.getGlyphSize(glyphArray[idx])\n\t}\n\tglyf.Length = uint(size)\n\n\tglyphTable := make([]byte, glyf.PaddedLength())\n\tlocaTable := make([]int, numGlyphs+1)\n\n\tglyphOffset := 0\n\tglyphIndex := 0\n\toldglyph := -1\n\tfor idx := 0; idx < numGlyphs; idx++ {\n\t\tlocaTable[idx] = glyphOffset\n\n\t\tif glyphIndex < glyphCount {\n\t\t\tif glyphArray[glyphIndex] == idx {\n\t\t\t\toldglyph = glyphArray[glyphIndex]\n\t\t\t\tglyphIndex++\n\t\t\t\tbytes := p.getGlyphData(idx)\n\t\t\t\tlength := len(bytes)\n\t\t\t\tif length > 0 {\n\t\t\t\t\tfor i := 0; i < length; i++ {\n\t\t\t\t\t\tglyphTable[glyphOffset+i] = bytes[i]\n\t\t\t\t\t}\n\t\t\t\t\tglyphOffset += length\n\t\t\t\t}\n\t\t\t} else if oldglyph == glyphArray[glyphIndex] {\n\t\t\t\tglyphIndex++\n\t\t\t\tbytes := p.getGlyphData(idx)\n\t\t\t\tlength := len(bytes)\n\t\t\t\tif length > 0 {\n\t\t\t\t\tfor i := 0; i < length; i++ {\n\t\t\t\t\t\tglyphTable[glyphOffset+i] = bytes[i]\n\t\t\t\t\t}\n\t\t\t\t\tglyphOffset += length\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} //end for\n\tlocaTable[numGlyphs] = glyphOffset\n\treturn glyphTable, locaTable, nil\n}\n\nfunc (p *PdfDictionaryObj) getGlyphSize(glyph int) int {\n\n\tttfp := p.PtrToSubsetFontObj.GetTTFParser()\n\tglyf := ttfp.GetTables()[\"glyf\"]\n\tstart := int(glyf.Offset + ttfp.LocaTable[glyph])\n\tnext := int(glyf.Offset + ttfp.LocaTable[glyph+1])\n\treturn next - start\n}\n\nfunc (p *PdfDictionaryObj) getGlyphData(glyph int) []byte {\n\tttfp := p.PtrToSubsetFontObj.GetTTFParser()\n\tglyf := ttfp.GetTables()[\"glyf\"]\n\tstart := int(glyf.Offset + ttfp.LocaTable[glyph])\n\tnext := int(glyf.Offset + ttfp.LocaTable[glyph+1])\n\tcount := next - start\n\tvar data []byte\n\ti := 0\n\tfor i < count {\n\t\tdata = append(data, ttfp.FontData()[start+i])\n\t\ti++\n\t}\n\treturn data\n}\n\nfunc (p *PdfDictionaryObj) makeFont() ([]byte, error) {\n\tvar buff Buff\n\tttfp := p.PtrToSubsetFontObj.GetTTFParser()\n\ttables := make(map[string]core.TableDirectoryEntry)\n\ttables[\"cvt \"] = ttfp.GetTables()[\"cvt \"] //มีช่องว่างด้วยนะ\n\ttables[\"fpgm\"] = ttfp.GetTables()[\"fpgm\"]\n\ttables[\"glyf\"] = ttfp.GetTables()[\"glyf\"]\n\ttables[\"head\"] = ttfp.GetTables()[\"head\"]\n\ttables[\"hhea\"] = ttfp.GetTables()[\"hhea\"]\n\ttables[\"hmtx\"] = ttfp.GetTables()[\"hmtx\"]\n\ttables[\"loca\"] = ttfp.GetTables()[\"loca\"]\n\ttables[\"maxp\"] = ttfp.GetTables()[\"maxp\"]\n\ttables[\"prep\"] = ttfp.GetTables()[\"prep\"]\n\ttableCount := len(tables)\n\tselector := EntrySelectors[tableCount]\n\n\tglyphTable, locaTable, err := p.makeGlyfAndLocaTable()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tWriteUInt32(&buff, 0x00010000)\n\tWriteUInt16(&buff, uint(tableCount))\n\tWriteUInt16(&buff, ((1 << uint(selector)) * 16))\n\tWriteUInt16(&buff, uint(selector))\n\tWriteUInt16(&buff, (uint(tableCount)-(1<<uint(selector)))*16)\n\n\tvar tags []string\n\tfor tag := range tables {\n\t\ttags = append(tags, tag) //copy all tag\n\t}\n\tsort.Strings(tags) //order\n\tidx := 0\n\ttablePosition := int(12 + 16*tableCount)\n\tfor idx < tableCount {\n\t\tentry := tables[tags[idx]]\n\t\t//write data\n\t\toffset := uint64(tablePosition)\n\t\tbuff.SetPosition(tablePosition)\n\t\tif tags[idx] == \"glyf\" {\n\t\t\tentry.Length = uint(len(glyphTable))\n\t\t\tentry.CheckSum = CheckSum(glyphTable)\n\t\t\tWriteBytes(&buff, glyphTable, 0, entry.PaddedLength())\n\t\t} else if tags[idx] == \"loca\" {\n\t\t\tif ttfp.IsShortIndex {\n\t\t\t\tentry.Length = uint(len(locaTable) * 2)\n\t\t\t} else {\n\t\t\t\tentry.Length = uint(len(locaTable) * 4)\n\t\t\t}\n\n\t\t\tdata := make([]byte, entry.PaddedLength())\n\t\t\tlength := len(locaTable)\n\t\t\tbyteIdx := 0\n\t\t\tif ttfp.IsShortIndex {\n\t\t\t\tfor idx := 0; idx < length; idx++ {\n\t\t\t\t\tval := locaTable[idx] / 2\n\t\t\t\t\tdata[byteIdx] = byte(val >> 8)\n\t\t\t\t\tbyteIdx++\n\t\t\t\t\tdata[byteIdx] = byte(val)\n\t\t\t\t\tbyteIdx++\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor idx := 0; idx < length; idx++ {\n\t\t\t\t\tval := locaTable[idx]\n\t\t\t\t\tdata[byteIdx] = byte(val >> 24)\n\t\t\t\t\tbyteIdx++\n\t\t\t\t\tdata[byteIdx] = byte(val >> 16)\n\t\t\t\t\tbyteIdx++\n\t\t\t\t\tdata[byteIdx] = byte(val >> 8)\n\t\t\t\t\tbyteIdx++\n\t\t\t\t\tdata[byteIdx] = byte(val)\n\t\t\t\t\tbyteIdx++\n\t\t\t\t}\n\t\t\t}\n\t\t\tentry.CheckSum = CheckSum(data)\n\t\t\tWriteBytes(&buff, data, 0, len(data))\n\t\t} else {\n\t\t\tWriteBytes(&buff, ttfp.FontData(), int(entry.Offset), entry.PaddedLength())\n\t\t}\n\t\tendPosition := buff.Position()\n\t\ttablePosition = endPosition\n\n\t\t//write table\n\t\tbuff.SetPosition(idx*16 + 12)\n\t\tWriteTag(&buff, tags[idx])\n\t\tWriteUInt32(&buff, uint(entry.CheckSum))\n\t\tWriteUInt32(&buff, uint(offset)) //offset\n\t\tWriteUInt32(&buff, uint(entry.Length))\n\n\t\ttablePosition = endPosition\n\t\tidx++\n\t}\n\t//DebugSubType(buff.Bytes())\n\t//me.buffer.Write(buff.Bytes())\n\treturn buff.Bytes(), nil\n}\n\nfunc (p *PdfDictionaryObj) completeGlyphClosure(mapOfglyphs *MapOfCharacterToGlyphIndex) []int {\n\tvar glyphArray []int\n\t//copy\n\tisContainZero := false\n\tglyphs := mapOfglyphs.AllVals()\n\tfor _, v := range glyphs {\n\t\tglyphArray = append(glyphArray, int(v))\n\t\tif v == 0 {\n\t\t\tisContainZero = true\n\t\t}\n\t}\n\tif !isContainZero {\n\t\tglyphArray = append(glyphArray, 0)\n\t}\n\n\ti := 0\n\tcount := len(glyphs)\n\tfor i < count {\n\t\tp.AddCompositeGlyphs(&glyphArray, glyphArray[i])\n\t\ti++\n\t}\n\treturn glyphArray\n}\n\n//AddCompositeGlyphs add composite glyph\n//composite glyph is a Unicode entity that can be defined as a sequence of one or more other characters.\nfunc (p *PdfDictionaryObj) AddCompositeGlyphs(glyphArray *[]int, glyph int) {\n\tstart := p.GetOffset(int(glyph))\n\tif start == p.GetOffset(int(glyph)+1) {\n\t\treturn\n\t}\n\n\toffset := start\n\tttfp := p.PtrToSubsetFontObj.GetTTFParser()\n\tfontData := ttfp.FontData()\n\tnumContours, step := ReadShortFromByte(fontData, offset)\n\toffset += step\n\tif numContours >= 0 {\n\t\treturn\n\t}\n\n\toffset += 8\n\tfor {\n\t\tflags, step1 := ReadUShortFromByte(fontData, offset)\n\t\toffset += step1\n\t\tcGlyph, step2 := ReadUShortFromByte(fontData, offset)\n\t\toffset += step2\n\t\t//check cGlyph is contain in glyphArray?\n\t\tglyphContainsKey := false\n\t\tfor _, g := range *glyphArray {\n\t\t\tif g == int(cGlyph) {\n\t\t\t\tglyphContainsKey = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !glyphContainsKey {\n\t\t\t*glyphArray = append(*glyphArray, int(cGlyph))\n\t\t}\n\n\t\tif (flags & moreComponents) == 0 {\n\t\t\treturn\n\t\t}\n\t\toffsetAppend := 4\n\t\tif (flags & arg1and2areWords) == 0 {\n\t\t\toffsetAppend = 2\n\t\t}\n\t\tif (flags & hasScale) != 0 {\n\t\t\toffsetAppend += 2\n\t\t} else if (flags & xAndYScale) != 0 {\n\t\t\toffsetAppend += 4\n\t\t}\n\t\tif (flags & twoByTwo) != 0 {\n\t\t\toffsetAppend += 8\n\t\t}\n\t\toffset += offsetAppend\n\t}\n}\n\nconst hasScale = 8\nconst moreComponents = 32\nconst arg1and2areWords = 1\nconst xAndYScale = 64\nconst twoByTwo = 128\n\n//GetOffset get offset from glyf table\nfunc (p *PdfDictionaryObj) GetOffset(glyph int) int {\n\tttfp := p.PtrToSubsetFontObj.GetTTFParser()\n\tglyf := ttfp.GetTables()[\"glyf\"]\n\toffset := int(glyf.Offset + ttfp.LocaTable[glyph])\n\treturn offset\n}\n\n//CheckSum check sum\nfunc CheckSum(data []byte) uint {\n\n\tvar byte3, byte2, byte1, byte0 uint64\n\tbyte3 = 0\n\tbyte2 = 0\n\tbyte1 = 0\n\tbyte0 = 0\n\tlength := len(data)\n\ti := 0\n\tfor i < length {\n\t\tbyte3 += uint64(data[i])\n\t\ti++\n\t\tbyte2 += uint64(data[i])\n\t\ti++\n\t\tbyte1 += uint64(data[i])\n\t\ti++\n\t\tbyte0 += uint64(data[i])\n\t\ti++\n\t}\n\t//var result uint32\n\tresult := uint32(byte3<<24) + uint32(byte2<<16) + uint32(byte1<<8) + uint32(byte0)\n\treturn uint(result)\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pdf_info_obj.go",
    "content": "package gopdf\n\nimport \"time\"\n\n//PdfInfo Document Information Dictionary\ntype PdfInfo struct {\n\tTitle        string    //The document’s title\n\tAuthor       string    //The name of the person who created the document.\n\tSubject      string    //The subject of the document.\n\tCreator      string    // If the document was converted to PDF from another format, the name of the application original document from which it was converted.\n\tProducer     string    //If the document was converted to PDF from another format, the name of the application (for example, Acrobat Distiller) that converted it to PDF.\n\tCreationDate time.Time //The date and time the document was created, in human-readable form\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/pdf_protection.go",
    "content": "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//PermissionsPrint setProtection print\n\tPermissionsPrint = 4\n\t//PermissionsModify setProtection modify\n\tPermissionsModify = 8\n\t//PermissionsCopy setProtection copy\n\tPermissionsCopy = 16\n\t//PermissionsAnnotForms setProtection  annot-forms\n\tPermissionsAnnotForms = 32\n)\n\nvar protectionPadding = []byte{\n\t0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,\n\t0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,\n}\n\n//PDFProtection protection in pdf\ntype PDFProtection struct {\n\tencrypted bool   //whether document is protected\n\tuValue    []byte //U entry in pdf document\n\toValue    []byte //O entry in pdf document\n\tpValue    int    //P entry in pdf document\n\t//var $enc_obj_id;         //encryption object id\n\tencryptionKey []byte\n}\n\n//SetProtection set protection infomation\nfunc (p *PDFProtection) SetProtection(permissions int, userPass []byte, ownerPass []byte) error {\n\treturn p.setProtection(permissions, userPass, ownerPass)\n}\n\nfunc (p *PDFProtection) setProtection(permissions int, userPass []byte, ownerPass []byte) error {\n\tprotection := 192 | permissions\n\tif ownerPass == nil || len(ownerPass) == 0 {\n\t\townerPass = p.randomPass(24)\n\t}\n\treturn p.generateEncryptionKey(userPass, ownerPass, protection)\n}\n\nfunc (p *PDFProtection) generateEncryptionKey(userPass []byte, ownerPass []byte, protection int) error {\n\n\tuserPass = append(userPass, protectionPadding...)\n\tuserPassWithPadding := userPass[0:32]\n\townerPass = append(ownerPass, protectionPadding...)\n\townerPassWithPadding := ownerPass[0:32]\n\n\t//oValue\n\toValue, err := p.createOValue(userPassWithPadding, ownerPassWithPadding)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.oValue = oValue\n\n\tuValue, err := p.createUValue(userPassWithPadding, oValue, protection)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.uValue = uValue\n\tp.pValue = -((protection ^ 255) + 1)\n\n\treturn nil\n}\n\n//EncryptionObj get Encryption Object\nfunc (p *PDFProtection) EncryptionObj() *EncryptionObj {\n\treturn p.encryptionObj()\n}\n\nfunc (p *PDFProtection) encryptionObj() *EncryptionObj {\n\tvar en EncryptionObj\n\ten.oValue = p.oValue\n\ten.pValue = p.pValue\n\ten.uValue = p.uValue\n\treturn &en\n}\n\nfunc (p *PDFProtection) createOValue(userPassWithPadding []byte, ownerPassWithPadding []byte) ([]byte, error) {\n\ttmp := md5.Sum(ownerPassWithPadding)\n\townerRC4key := tmp[0:5]\n\tcip, err := rc4.NewCipher(ownerRC4key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdest := make([]byte, len(userPassWithPadding))\n\tcip.XORKeyStream(dest, userPassWithPadding)\n\treturn dest, nil\n}\n\nfunc (p *PDFProtection) createUValue(userPassWithPadding []byte, oValue []byte, protection int) ([]byte, error) {\n\tm := md5.New()\n\tm.Write(userPassWithPadding)\n\tm.Write(oValue)\n\tm.Write([]byte{byte(protection), byte(0xff), byte(0xff), byte(0xff)})\n\n\ttmp2 := m.Sum(nil)\n\tp.encryptionKey = tmp2[0:5]\n\tcip, err := rc4.NewCipher(p.encryptionKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdest := make([]byte, len(protectionPadding))\n\tcip.XORKeyStream(dest, protectionPadding)\n\treturn dest, nil\n}\n\nfunc (p *PDFProtection) randomPass(strlen int) []byte {\n\trand.Seed(time.Now().UTC().UnixNano())\n\tconst chars = \"abcdef0123456789\"\n\tresult := make([]byte, strlen)\n\tfor i := 0; i < strlen; i++ {\n\t\tresult[i] = chars[rand.Intn(len(chars))]\n\t}\n\treturn result\n}\n\n//Objectkey create object key from ObjID\nfunc (p *PDFProtection) Objectkey(objID int) []byte {\n\treturn p.objectkey(objID)\n}\n\nfunc (p *PDFProtection) objectkey(n int) []byte {\n\ttmp := make([]byte, 8, 8)\n\tbinary.LittleEndian.PutUint32(tmp, uint32(n))\n\ttmp2 := append(p.encryptionKey, tmp[0], tmp[1], tmp[2], 0, 0)\n\ttmp3 := md5.Sum(tmp2)\n\treturn tmp3[0:10]\n}\n\nfunc rc4Cip(key []byte, src []byte) ([]byte, error) {\n\tcip, err := rc4.NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdest := make([]byte, len(src))\n\tcip.XORKeyStream(dest, src)\n\treturn dest, nil\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/point.go",
    "content": "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",
    "content": "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             RelateFonts\n\tRelateXobjs         RelateXobjects\n\tExtGStates          []ExtGS\n\tImportedTemplateIds map[string]int\n\tgetRoot             func() *GoPdf\n}\n\nfunc (pr *ProcSetObj) init(funcGetRoot func() *GoPdf) {\n\tpr.getRoot = funcGetRoot\n\tpr.ImportedTemplateIds = make(map[string]int, 0)\n\tpr.ExtGStates = make([]ExtGS, 0)\n}\n\nfunc (pr *ProcSetObj) write(w io.Writer, objID int) error {\n\tcontent := \"<<\\n\"\n\tcontent += \"\\t/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\\n\"\n\n\tfonts := \"\\t/Font <<\\n\"\n\tfor _, relate := range pr.Relates {\n\t\tfonts += fmt.Sprintf(\"\\t\\t/F%d %d 0 R\\n\", relate.CountOfFont+1, relate.IndexOfObj+1)\n\t}\n\tfonts += \"\\t>>\\n\"\n\n\tcontent += fonts\n\n\txobjects := \"\\t/XObject <<\\n\"\n\tfor _, XObject := range pr.RelateXobjs {\n\t\txobjects += fmt.Sprintf(\"\\t\\t/I%d %d 0 R\\n\", XObject.IndexOfObj+1, XObject.IndexOfObj+1)\n\t}\n\t// Write imported template name and their ids\n\tfor tplName, objID := range pr.ImportedTemplateIds {\n\t\txobjects += fmt.Sprintf(\"\\t\\t%s %d 0 R\\n\", tplName, objID)\n\t}\n\txobjects += \"\\t>>\\n\"\n\n\tcontent += xobjects\n\n\textGStates := \"\\t/ExtGState <<\\n\"\n\tfor _, extGState := range pr.ExtGStates {\n\t\textGStates += fmt.Sprintf(\"\\t\\t/GS%d %d 0 R\\n\", extGState.Index+1, extGState.Index+1)\n\t}\n\textGStates += \"\\t>>\\n\"\n\n\tcontent += extGStates\n\n\tcontent += \">>\\n\"\n\n\tif _, err := io.WriteString(w, content); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (pr *ProcSetObj) getType() string {\n\treturn \"ProcSet\"\n}\n\n// RelateFonts is a slice of RelateFont.\ntype RelateFonts []RelateFont\n\n// IsContainsFamily checks if font family exists.\nfunc (re *RelateFonts) IsContainsFamily(family string) bool {\n\tfor _, rf := range *re {\n\t\tif rf.Family == family {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// IsContainsFamilyAndStyle checks if font with same name and style already exists .\nfunc (re *RelateFonts) IsContainsFamilyAndStyle(family string, style int) bool {\n\tfor _, rf := range *re {\n\t\tif rf.Family == family && rf.Style == style {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// RelateFont is a metadata index for fonts?\ntype RelateFont struct {\n\tFamily string\n\t//etc /F1\n\tCountOfFont int\n\t//etc  5 0 R\n\tIndexOfObj int\n\tStyle      int // Regular|Bold|Italic\n}\n\n// RelateXobjects is a slice of RelateXobject.\ntype RelateXobjects []RelateXobject\n\n// RelateXobject is an index for ???\ntype RelateXobject struct {\n\tIndexOfObj int\n}\n\n// ExtGS is ???\ntype ExtGS struct {\n\tIndex int\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/rect.go",
    "content": "package gopdf\n\n// Rect defines a rectangle.\ntype Rect struct {\n\tW            float64\n\tH            float64\n\tunitOverride int\n}\n\n// PointsToUnits converts the rectangles width and height to Units. When this is called it is assumed the values of the rectangle are in Points\nfunc (rect *Rect) PointsToUnits(t int) (r *Rect) {\n\tif rect == nil {\n\t\treturn\n\t}\n\n\tif rect.unitOverride != UnitUnset {\n\t\tt = rect.unitOverride\n\t}\n\n\tr = &Rect{W: rect.W, H: rect.H}\n\tPointsToUnitsVar(t, &r.W, &r.H)\n\treturn\n}\n\n// UnitsToPoints converts the rectanlges width and height to Points. When this is called it is assumed the values of the rectangle are in Units\nfunc (rect *Rect) UnitsToPoints(t int) (r *Rect) {\n\tif rect == nil {\n\t\treturn\n\t}\n\n\tif rect.unitOverride != UnitUnset {\n\t\tt = rect.unitOverride\n\t}\n\n\tr = &Rect{W: rect.W, H: rect.H}\n\tUnitsToPointsVar(t, &r.W, &r.H)\n\treturn\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/smask_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"sync\"\n)\n\ntype SMaskSubtypes string\n\nconst (\n\tSMaskAlphaSubtype      = \"/Alpha\"\n\tSMaskLuminositySubtype = \"/Luminosity\"\n)\n\n//SMask smask\ntype SMask struct {\n\timgInfo\n\tdata []byte\n\t//getRoot func() *GoPdf\n\tpdfProtection                 *PDFProtection\n\tIndex                         int\n\tTransparencyXObjectGroupIndex int\n\tS                             string\n}\n\ntype SMaskOptions struct {\n\tTransparencyXObjectGroupIndex int\n\tSubtype                       SMaskSubtypes\n}\n\nfunc (smask SMaskOptions) GetId() string {\n\tid := fmt.Sprintf(\"S_%s;G_%d_0_R\", smask.Subtype, smask.TransparencyXObjectGroupIndex)\n\n\treturn id\n}\n\nfunc GetCachedMask(opts SMaskOptions, gp *GoPdf) SMask {\n\tsmask, ok := gp.curr.sMasksMap.Find(opts)\n\tif !ok {\n\t\tsmask = SMask{\n\t\t\tS:                             string(opts.Subtype),\n\t\t\tTransparencyXObjectGroupIndex: opts.TransparencyXObjectGroupIndex,\n\t\t}\n\t\tsmask.Index = gp.addObj(smask)\n\n\t\tgp.curr.sMasksMap.Save(opts.GetId(), smask)\n\t}\n\n\treturn smask\n}\n\nfunc (s SMask) init(func() *GoPdf) {}\n\nfunc (s *SMask) setProtection(p *PDFProtection) {\n\ts.pdfProtection = p\n}\n\nfunc (s SMask) protection() *PDFProtection {\n\treturn s.pdfProtection\n}\n\nfunc (s SMask) getType() string {\n\treturn \"Mask\"\n}\n\nfunc (s SMask) write(w io.Writer, objID int) error {\n\tif s.TransparencyXObjectGroupIndex != 0 {\n\t\tcontent := \"<<\\n\"\n\t\tcontent += \"\\t/Type /Mask\\n\"\n\t\tcontent += fmt.Sprintf(\"\\t/S %s\\n\", s.S)\n\t\tcontent += fmt.Sprintf(\"\\t/G %d 0 R\\n\", s.TransparencyXObjectGroupIndex+1)\n\t\tcontent += \">>\\n\"\n\n\t\tif _, err := io.WriteString(w, content); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\terr := writeImgProps(w, s.imgInfo, false)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tfmt.Fprintf(w, \"/Length %d\\n>>\\n\", len(s.data)) // /Length 62303>>\\n\n\t\tio.WriteString(w, \"stream\\n\")\n\t\tif s.protection() != nil {\n\t\t\ttmp, err := rc4Cip(s.protection().objectkey(objID), s.data)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tw.Write(tmp)\n\t\t\tio.WriteString(w, \"\\n\")\n\t\t} else {\n\t\t\tw.Write(s.data)\n\t\t}\n\t\tio.WriteString(w, \"\\nendstream\\n\")\n\t}\n\n\treturn nil\n}\n\ntype SMaskMap struct {\n\tsyncer sync.Mutex\n\ttable  map[string]SMask\n}\n\nfunc NewSMaskMap() SMaskMap {\n\treturn SMaskMap{\n\t\tsyncer: sync.Mutex{},\n\t\ttable:  make(map[string]SMask),\n\t}\n}\n\nfunc (smask *SMaskMap) Find(sMask SMaskOptions) (SMask, bool) {\n\tkey := sMask.GetId()\n\n\tsmask.syncer.Lock()\n\tdefer smask.syncer.Unlock()\n\n\tt, ok := smask.table[key]\n\tif !ok {\n\t\treturn SMask{}, false\n\t}\n\n\treturn t, ok\n\n}\n\nfunc (smask *SMaskMap) Save(id string, sMask SMask) SMask {\n\tsmask.syncer.Lock()\n\tdefer smask.syncer.Unlock()\n\n\tsmask.table[id] = sMask\n\n\treturn sMask\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/strhelper.go",
    "content": "package gopdf\n\nimport (\n\t\"math/big\"\n\t\"strings\"\n)\n\n//StrHelperGetStringWidth get string width\nfunc StrHelperGetStringWidth(str string, fontSize int, ifont IFont) float64 {\n\tw := 0\n\tbs := []byte(str)\n\ti := 0\n\tmax := len(bs)\n\tfor i < max {\n\t\tw += ifont.GetCw()[bs[i]]\n\t\ti++\n\t}\n\treturn float64(w) * (float64(fontSize) / 1000.0)\n}\n\n//CreateEmbeddedFontSubsetName create Embedded font (subset font) name\nfunc CreateEmbeddedFontSubsetName(name string) string {\n\tname = strings.Replace(name, \" \", \"+\", -1)\n\tname = strings.Replace(name, \"/\", \"+\", -1)\n\treturn name\n}\n\n//ReadShortFromByte read short from byte array\nfunc ReadShortFromByte(data []byte, offset int) (int64, int) {\n\tbuff := data[offset : offset+2]\n\tnum := big.NewInt(0)\n\tnum.SetBytes(buff)\n\tu := num.Uint64()\n\tvar v int64\n\tif u >= 0x8000 {\n\t\tv = int64(u) - 65536\n\t} else {\n\t\tv = int64(u)\n\t}\n\treturn v, 2\n}\n\n//ReadUShortFromByte read ushort from byte array\nfunc ReadUShortFromByte(data []byte, offset int) (uint64, int) {\n\tbuff := data[offset : offset+2]\n\tnum := big.NewInt(0)\n\tnum.SetBytes(buff)\n\treturn num.Uint64(), 2\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/style.go",
    "content": "package gopdf\n\ntype PaintStyle string\n\nconst (\n\tDrawPaintStyle     PaintStyle = \"S\"\n\tFillPaintStyle     PaintStyle = \"f\"\n\tDrawFillPaintStyle PaintStyle = \"B\"\n)\n\nfunc parseStyle(style string) PaintStyle {\n\top := DrawPaintStyle\n\tif style == \"F\" {\n\t\top = FillPaintStyle\n\t} else if style == \"FD\" || style == \"DF\" {\n\t\top = DrawFillPaintStyle\n\t}\n\n\treturn op\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/subfont_descriptor_obj.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/signintech/gopdf/fontmaker/core\"\n)\n\n//SubfontDescriptorObj pdf subfont descriptorObj object\ntype SubfontDescriptorObj struct {\n\tPtrToSubsetFontObj    *SubsetFontObj\n\tindexObjPdfDictionary int\n}\n\nfunc (s *SubfontDescriptorObj) init(func() *GoPdf) {}\n\nfunc (s *SubfontDescriptorObj) getType() string {\n\treturn \"SubFontDescriptor\"\n}\n\nfunc (s *SubfontDescriptorObj) write(w io.Writer, objID int) error {\n\tttfp := s.PtrToSubsetFontObj.GetTTFParser()\n\t//fmt.Printf(\"-->%d\\n\", ttfp.UnitsPerEm())\n\tio.WriteString(w, \"<<\\n\")\n\tio.WriteString(w, \"/Type /FontDescriptor\\n\")\n\tfmt.Fprintf(w, \"/Ascent %d\\n\", DesignUnitsToPdf(ttfp.Ascender(), ttfp.UnitsPerEm()))\n\tfmt.Fprintf(w, \"/CapHeight %d\\n\", DesignUnitsToPdf(ttfp.CapHeight(), ttfp.UnitsPerEm()))\n\tfmt.Fprintf(w, \"/Descent %d\\n\", DesignUnitsToPdf(ttfp.Descender(), ttfp.UnitsPerEm()))\n\tfmt.Fprintf(w, \"/Flags %d\\n\", ttfp.Flag())\n\tfmt.Fprintf(w, \"/FontBBox [%d %d %d %d]\\n\",\n\t\tDesignUnitsToPdf(ttfp.XMin(), ttfp.UnitsPerEm()),\n\t\tDesignUnitsToPdf(ttfp.YMin(), ttfp.UnitsPerEm()),\n\t\tDesignUnitsToPdf(ttfp.XMax(), ttfp.UnitsPerEm()),\n\t\tDesignUnitsToPdf(ttfp.YMax(), ttfp.UnitsPerEm()),\n\t)\n\tfmt.Fprintf(w, \"/FontFile2 %d 0 R\\n\", s.indexObjPdfDictionary+1)\n\tfmt.Fprintf(w, \"/FontName /%s\\n\", CreateEmbeddedFontSubsetName(s.PtrToSubsetFontObj.GetFamily()))\n\tfmt.Fprintf(w, \"/ItalicAngle %d\\n\", ttfp.ItalicAngle())\n\tio.WriteString(w, \"/StemV 0\\n\")\n\tfmt.Fprintf(w, \"/XHeight %d\\n\", DesignUnitsToPdf(ttfp.XHeight(), ttfp.UnitsPerEm()))\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\n//SetIndexObjPdfDictionary set PdfDictionary pointer\nfunc (s *SubfontDescriptorObj) SetIndexObjPdfDictionary(index int) {\n\ts.indexObjPdfDictionary = index\n}\n\n//SetPtrToSubsetFontObj set SubsetFont pointer\nfunc (s *SubfontDescriptorObj) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {\n\ts.PtrToSubsetFontObj = ptr\n}\n\n//DesignUnitsToPdf convert unit\nfunc DesignUnitsToPdf(val int, unitsPerEm uint) int {\n\treturn core.Round(float64(float64(val) * 1000.00 / float64(unitsPerEm)))\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/subset_font_obj.go",
    "content": "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 not found\nvar ErrCharNotFound = errors.New(\"char not found\")\n\n//ErrGlyphNotFound font file not contain glyph\nvar ErrGlyphNotFound = errors.New(\"glyph not found\")\n\n//SubsetFontObj pdf subsetFont object\ntype SubsetFontObj struct {\n\tttfp                  core.TTFParser\n\tFamily                string\n\tCharacterToGlyphIndex *MapOfCharacterToGlyphIndex\n\tCountOfFont           int\n\tindexObjCIDFont       int\n\tindexObjUnicodeMap    int\n\tttfFontOption         TtfOption\n\tfuncKernOverride      FuncKernOverride\n}\n\nfunc (s *SubsetFontObj) init(funcGetRoot func() *GoPdf) {\n\ts.CharacterToGlyphIndex = NewMapOfCharacterToGlyphIndex() //make(map[rune]uint)\n\ts.funcKernOverride = nil\n}\n\nfunc (s *SubsetFontObj) write(w io.Writer, objID int) error {\n\t//me.AddChars(\"จ\")\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"/BaseFont /%s\\n\", CreateEmbeddedFontSubsetName(s.Family))\n\tfmt.Fprintf(w, \"/DescendantFonts [%d 0 R]\\n\", s.indexObjCIDFont+1)\n\tio.WriteString(w, \"/Encoding /Identity-H\\n\")\n\tio.WriteString(w, \"/Subtype /Type0\\n\")\n\tfmt.Fprintf(w, \"/ToUnicode %d 0 R\\n\", s.indexObjUnicodeMap+1)\n\tio.WriteString(w, \"/Type /Font\\n\")\n\tio.WriteString(w, \">>\\n\")\n\treturn nil\n}\n\n//SetIndexObjCIDFont set IndexObjCIDFont\nfunc (s *SubsetFontObj) SetIndexObjCIDFont(index int) {\n\ts.indexObjCIDFont = index\n}\n\n//SetIndexObjUnicodeMap set IndexObjUnicodeMap\nfunc (s *SubsetFontObj) SetIndexObjUnicodeMap(index int) {\n\ts.indexObjUnicodeMap = index\n}\n\n//SetFamily set font family name\nfunc (s *SubsetFontObj) SetFamily(familyname string) {\n\ts.Family = familyname\n}\n\n//GetFamily get font family name\nfunc (s *SubsetFontObj) GetFamily() string {\n\treturn s.Family\n}\n\n//SetTtfFontOption set TtfOption must set before SetTTFByPath\nfunc (s *SubsetFontObj) SetTtfFontOption(option TtfOption) {\n\ts.ttfFontOption = option\n}\n\n//GetTtfFontOption get TtfOption must set before SetTTFByPath\nfunc (s *SubsetFontObj) GetTtfFontOption() TtfOption {\n\treturn s.ttfFontOption\n}\n\n//KernValueByLeft find kern value from kern table by left\nfunc (s *SubsetFontObj) KernValueByLeft(left uint) (bool, *core.KernValue) {\n\n\tif !s.ttfFontOption.UseKerning {\n\t\treturn false, nil\n\t}\n\n\tk := s.ttfp.Kern()\n\tif k == nil {\n\t\treturn false, nil\n\t}\n\n\tif kval, ok := k.Kerning[left]; ok {\n\t\treturn true, &kval\n\t}\n\n\treturn false, nil\n}\n\n//SetTTFByPath set ttf\nfunc (s *SubsetFontObj) SetTTFByPath(ttfpath string) error {\n\tuseKerning := s.ttfFontOption.UseKerning\n\ts.ttfp.SetUseKerning(useKerning)\n\terr := s.ttfp.Parse(ttfpath)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//SetTTFByReader set ttf\nfunc (s *SubsetFontObj) SetTTFByReader(rd io.Reader) error {\n\tuseKerning := s.ttfFontOption.UseKerning\n\ts.ttfp.SetUseKerning(useKerning)\n\terr := s.ttfp.ParseByReader(rd)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//SetTTFData set ttf\nfunc (s *SubsetFontObj) SetTTFData(data []byte) error {\n\tuseKerning := s.ttfFontOption.UseKerning\n\ts.ttfp.SetUseKerning(useKerning)\n\terr := s.ttfp.ParseFontData(data)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n//AddChars add char to map CharacterToGlyphIndex\nfunc (s *SubsetFontObj) AddChars(txt string) error {\n\tfor _, runeValue := range txt {\n\t\tif s.CharacterToGlyphIndex.KeyExists(runeValue) {\n\t\t\tcontinue\n\t\t}\n\t\tglyphIndex, err := s.CharCodeToGlyphIndex(runeValue)\n\t\tif err == ErrGlyphNotFound {\n\t\t\t//never return error on this, just call function OnGlyphNotFound\n\t\t\tif s.ttfFontOption.OnGlyphNotFound != nil {\n\t\t\t\ts.ttfFontOption.OnGlyphNotFound(runeValue)\n\t\t\t}\n\t\t} else if err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts.CharacterToGlyphIndex.Set(runeValue, glyphIndex) // [runeValue] = glyphIndex\n\t}\n\treturn nil\n}\n\n//CharIndex index of char in glyph table\nfunc (s *SubsetFontObj) CharIndex(r rune) (uint, error) {\n\tglyIndex, ok := s.CharacterToGlyphIndex.Val(r)\n\tif ok {\n\t\treturn glyIndex, nil\n\t}\n\treturn 0, ErrCharNotFound\n}\n\n//CharWidth with of char\nfunc (s *SubsetFontObj) CharWidth(r rune) (uint, error) {\n\tglyIndex, ok := s.CharacterToGlyphIndex.Val(r)\n\tif ok {\n\t\treturn s.GlyphIndexToPdfWidth(glyIndex), nil\n\t}\n\treturn 0, ErrCharNotFound\n}\n\nfunc (s *SubsetFontObj) getType() string {\n\treturn \"SubsetFont\"\n}\n\nfunc (s *SubsetFontObj) charCodeToGlyphIndexFormat12(r rune) (uint, error) {\n\n\tvalue := uint(r)\n\tgTbs := s.ttfp.GroupingTables()\n\tfor _, gTb := range gTbs {\n\t\tif value >= gTb.StartCharCode && value <= gTb.EndCharCode {\n\t\t\tgIndex := (value - gTb.StartCharCode) + gTb.GlyphID\n\t\t\treturn gIndex, nil\n\t\t}\n\t}\n\n\treturn uint(0), ErrGlyphNotFound\n}\n\nfunc (s *SubsetFontObj) charCodeToGlyphIndexFormat4(r rune) (uint, error) {\n\tvalue := uint(r)\n\tseg := uint(0)\n\tsegCount := s.ttfp.SegCount\n\tfor seg < segCount {\n\t\tif value <= s.ttfp.EndCount[seg] {\n\t\t\tbreak\n\t\t}\n\t\tseg++\n\t}\n\t//fmt.Printf(\"\\ncccc--->%#v\\n\", me.ttfp.Chars())\n\tif value < s.ttfp.StartCount[seg] {\n\t\treturn 0, ErrGlyphNotFound\n\t}\n\n\tif s.ttfp.IdRangeOffset[seg] == 0 {\n\n\t\treturn (value + s.ttfp.IdDelta[seg]) & 0xFFFF, nil\n\t}\n\t//fmt.Printf(\"IdRangeOffset=%d\\n\", me.ttfp.IdRangeOffset[seg])\n\tidx := s.ttfp.IdRangeOffset[seg]/2 + (value - s.ttfp.StartCount[seg]) - (segCount - seg)\n\n\tif s.ttfp.GlyphIdArray[int(idx)] == uint(0) {\n\t\treturn 0, nil\n\t}\n\n\treturn (s.ttfp.GlyphIdArray[int(idx)] + s.ttfp.IdDelta[seg]) & 0xFFFF, nil\n}\n\n// CharCodeToGlyphIndex gets glyph index from char code.\nfunc (s *SubsetFontObj) CharCodeToGlyphIndex(r rune) (uint, error) {\n\tvalue := uint64(r)\n\tif value <= 0xFFFF {\n\t\tgIndex, err := s.charCodeToGlyphIndexFormat4(r)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\treturn gIndex, nil\n\t}\n\tgIndex, err := s.charCodeToGlyphIndexFormat12(r)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn gIndex, nil\n}\n\n// GlyphIndexToPdfWidth gets width from glyphIndex.\nfunc (s *SubsetFontObj) GlyphIndexToPdfWidth(glyphIndex uint) uint {\n\n\tnumberOfHMetrics := s.ttfp.NumberOfHMetrics()\n\tunitsPerEm := s.ttfp.UnitsPerEm()\n\tif glyphIndex >= numberOfHMetrics {\n\t\tglyphIndex = numberOfHMetrics - 1\n\t}\n\n\twidth := s.ttfp.Widths()[glyphIndex]\n\tif unitsPerEm == 1000 {\n\t\treturn width\n\t}\n\treturn width * 1000 / unitsPerEm\n}\n\n// GetTTFParser gets TTFParser.\nfunc (s *SubsetFontObj) GetTTFParser() *core.TTFParser {\n\treturn &s.ttfp\n}\n\n// GetUt underlineThickness.\nfunc (s *SubsetFontObj) GetUt() int {\n\treturn s.ttfp.UnderlineThickness()\n}\n\n// GetUp underline postion.\nfunc (s *SubsetFontObj) GetUp() int {\n\treturn s.ttfp.UnderlinePosition()\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/transparency.go",
    "content": "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             BlendModeType = \"/Hue\"\n\tColor           BlendModeType = \"/Color\"\n\tNormalBlendMode BlendModeType = \"/Normal\"\n\tDarken          BlendModeType = \"/Darken\"\n\tScreen          BlendModeType = \"/Screen\"\n\tOverlay         BlendModeType = \"/Overlay\"\n\tLighten         BlendModeType = \"/Lighten\"\n\tMultiply        BlendModeType = \"/Multiply\"\n\tExclusion       BlendModeType = \"/Exclusion\"\n\tColorBurn       BlendModeType = \"/ColorBurn\"\n\tHardLight       BlendModeType = \"/HardLight\"\n\tSoftLight       BlendModeType = \"/SoftLight\"\n\tDifference      BlendModeType = \"/Difference\"\n\tSaturation      BlendModeType = \"/Saturation\"\n\tLuminosity      BlendModeType = \"/Luminosity\"\n\tColorDodge      BlendModeType = \"/ColorDodge\"\n)\n\nconst DefaultAplhaValue = 1\n\n// Transparency defines an object alpha.\ntype Transparency struct {\n\textGStateIndex int\n\tAlpha          float64\n\tBlendModeType  BlendModeType\n}\n\nfunc NewTransparency(alpha float64, blendModeType string) (Transparency, error) {\n\tif alpha < 0.0 || alpha > 1.0 {\n\t\treturn Transparency{}, errors.Errorf(\"alpha value is out of range (0.0 - 1.0): %.3f\", alpha)\n\t}\n\n\tbmtType, err := defineBlendModeType(blendModeType)\n\tif err != nil {\n\t\treturn Transparency{}, err\n\t}\n\n\treturn Transparency{\n\t\tAlpha:         alpha,\n\t\tBlendModeType: bmtType,\n\t}, nil\n}\n\nfunc (t Transparency) GetId() string {\n\tkeyStr := fmt.Sprintf(\"%.3f_%s\", t.Alpha, t.BlendModeType)\n\n\treturn keyStr\n}\n\ntype TransparencyMap struct {\n\tsyncer sync.Mutex\n\ttable  map[string]Transparency\n}\n\nfunc NewTransparencyMap() TransparencyMap {\n\treturn TransparencyMap{\n\t\tsyncer: sync.Mutex{},\n\t\ttable:  make(map[string]Transparency),\n\t}\n}\n\nfunc (tm *TransparencyMap) Find(transparency Transparency) (Transparency, bool) {\n\tkey := transparency.GetId()\n\n\ttm.syncer.Lock()\n\tdefer tm.syncer.Unlock()\n\n\tt, ok := tm.table[key]\n\tif !ok {\n\t\treturn Transparency{}, false\n\t}\n\n\treturn t, ok\n\n}\n\nfunc (tm *TransparencyMap) Save(transparency Transparency) Transparency {\n\ttm.syncer.Lock()\n\tdefer tm.syncer.Unlock()\n\n\tkey := transparency.GetId()\n\ttm.table[key] = transparency\n\n\treturn transparency\n}\n\nfunc defineBlendModeType(bmType string) (BlendModeType, error) {\n\tswitch bmType {\n\tcase string(Hue):\n\t\treturn Hue, nil\n\tcase string(Color):\n\t\treturn Color, nil\n\tcase \"\", string(NormalBlendMode):\n\t\treturn NormalBlendMode, nil\n\tcase string(Darken):\n\t\treturn Darken, nil\n\tcase string(Screen):\n\t\treturn Screen, nil\n\tcase string(Overlay):\n\t\treturn Overlay, nil\n\tcase string(Lighten):\n\t\treturn Lighten, nil\n\tcase string(Multiply):\n\t\treturn Multiply, nil\n\tcase string(Exclusion):\n\t\treturn Exclusion, nil\n\tcase string(ColorBurn):\n\t\treturn ColorBurn, nil\n\tcase string(HardLight):\n\t\treturn HardLight, nil\n\tcase string(SoftLight):\n\t\treturn SoftLight, nil\n\tcase string(Difference):\n\t\treturn Difference, nil\n\tcase string(Saturation):\n\t\treturn Saturation, nil\n\tcase string(Luminosity):\n\t\treturn Luminosity, nil\n\tcase string(ColorDodge):\n\t\treturn ColorDodge, nil\n\tdefault:\n\t\treturn \"\", errors.New(\"blend mode is unknown\")\n\t}\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/transparency_xobject_group.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype TransparencyXObjectGroup struct {\n\tIndex            int\n\tBBox             [4]float64\n\tMatrix           [6]float64\n\tExtGStateIndexes []int\n\tXObjects         []cacheContentImage\n\n\tgetRoot func() *GoPdf\n\tpdfProtection *PDFProtection\n}\n\ntype TransparencyXObjectGroupOptions struct {\n\tProtection       *PDFProtection\n\tExtGStateIndexes []int\n\tBBox             [4]float64\n\tXObjects         []cacheContentImage\n}\n\nfunc GetCachedTransparencyXObjectGroup(opts TransparencyXObjectGroupOptions, gp *GoPdf) (TransparencyXObjectGroup, error) {\n\tgroup := TransparencyXObjectGroup{\n\t\tBBox:             opts.BBox,\n\t\tXObjects:         opts.XObjects,\n\t\tpdfProtection:    opts.Protection,\n\t\tExtGStateIndexes: opts.ExtGStateIndexes,\n\t}\n\tgroup.Index = gp.addObj(group)\n\tgroup.init(func() *GoPdf {\n\t\treturn gp\n\t})\n\n\treturn group, nil\n}\n\nfunc (s TransparencyXObjectGroup) init(funcGetRoot func() *GoPdf) {\n\ts.getRoot = funcGetRoot\n}\n\nfunc (s *TransparencyXObjectGroup) setProtection(p *PDFProtection) {\n\ts.pdfProtection = p\n}\n\nfunc (s TransparencyXObjectGroup) protection() *PDFProtection {\n\treturn s.pdfProtection\n}\n\nfunc (s TransparencyXObjectGroup) getType() string {\n\treturn \"XObject\"\n}\n\nfunc (s TransparencyXObjectGroup) write(w io.Writer, objId int) error {\n\tstreamBuff := GetBuffer()\n\tdefer PutBuffer(streamBuff)\n\n\tfor _, XObject := range s.XObjects {\n\t\tif err := XObject.write(streamBuff, nil); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tcontent := \"<<\\n\"\n\tcontent += \"\\t/FormType 1\\n\"\n\tcontent += \"\\t/Subtype /Form\\n\"\n\tcontent += fmt.Sprintf(\"\\t/Type /%s\\n\", s.getType())\n\tcontent += fmt.Sprintf(\"\\t/Matrix [1 0 0 1 0 0]\\n\")\n\tcontent += fmt.Sprintf(\"\\t/BBox [%.3F %.3F %.3F %.3F]\\n\", s.BBox[0], s.BBox[1], s.BBox[2], s.BBox[3])\n\tcontent += \"\\t/Group<</CS /DeviceGray /S /Transparency>>\\n\"\n\n\tcontent += fmt.Sprintf(\"\\t/Length %d\\n\", len(streamBuff.Bytes()))\n\tcontent += \">>\\n\"\n\tcontent += \"stream\\n\"\n\n\tif _, err := io.WriteString(w, content); err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := w.Write(streamBuff.Bytes()); err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := io.WriteString(w, \"endstream\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/ttf_option.go",
    "content": "package gopdf\n\n//TtfOption  font option\ntype TtfOption struct {\n\tUseKerning      bool\n\tStyle           int // Regular|Bold|Italic\n\tOnGlyphNotFound func(r rune)\n}\n\nfunc defaultTtfFontOption() TtfOption {\n\tvar defa TtfOption\n\tdefa.UseKerning = false\n\tdefa.Style = Regular\n\treturn defa\n}\n"
  },
  {
    "path": "vendor/github.com/signintech/gopdf/unicode_map.go",
    "content": "package gopdf\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n//UnicodeMap unicode map\ntype UnicodeMap struct {\n\tPtrToSubsetFontObj *SubsetFontObj\n\t//getRoot            func() *GoPdf\n\tpdfProtection *PDFProtection\n}\n\nfunc (u *UnicodeMap) init(funcGetRoot func() *GoPdf) {\n\t//u.getRoot = funcGetRoot\n}\n\nfunc (u *UnicodeMap) setProtection(p *PDFProtection) {\n\tu.pdfProtection = p\n}\n\nfunc (u *UnicodeMap) protection() *PDFProtection {\n\treturn u.pdfProtection\n}\n\n//SetPtrToSubsetFontObj set pointer to SubsetFontObj\nfunc (u *UnicodeMap) SetPtrToSubsetFontObj(ptr *SubsetFontObj) {\n\tu.PtrToSubsetFontObj = ptr\n}\n\nfunc (u *UnicodeMap) getType() string {\n\treturn \"Unicode\"\n}\n\nfunc (u *UnicodeMap) write(w io.Writer, objID int) error {\n\t//stream\n\t//characterToGlyphIndex := u.PtrToSubsetFontObj.CharacterToGlyphIndex\n\tprefix :=\n\t\t\"/CIDInit /ProcSet findresource begin\\n\" +\n\t\t\t\"12 dict begin\\n\" +\n\t\t\t\"begincmap\\n\" +\n\t\t\t\"/CIDSystemInfo << /Registry (Adobe)/Ordering (UCS)/Supplement 0>> def\\n\" +\n\t\t\t\"/CMapName /Adobe-Identity-UCS def /CMapType 2 def\\n\"\n\tsuffix := \"endcmap CMapName currentdict /CMap defineresource pop end end\"\n\n\tglyphIndexToCharacter := newMapGlyphIndexToCharacter() //make(map[int]rune)\n\tlowIndex := 65536\n\thiIndex := -1\n\n\tkeys := u.PtrToSubsetFontObj.CharacterToGlyphIndex.AllKeys()\n\tfor _, k := range keys {\n\t\tv, _ := u.PtrToSubsetFontObj.CharacterToGlyphIndex.Val(k)\n\t\tindex := int(v)\n\t\tif index < lowIndex {\n\t\t\tlowIndex = index\n\t\t}\n\t\tif index > hiIndex {\n\t\t\thiIndex = index\n\t\t}\n\t\t//glyphIndexToCharacter[index] = k\n\t\tglyphIndexToCharacter.set(index, k)\n\t}\n\n\tbuff := GetBuffer()\n\tdefer PutBuffer(buff)\n\n\tbuff.WriteString(prefix)\n\tbuff.WriteString(\"1 begincodespacerange\\n\")\n\tfmt.Fprintf(buff, \"<%04X><%04X>\\n\", lowIndex, hiIndex)\n\tbuff.WriteString(\"endcodespacerange\\n\")\n\tfmt.Fprintf(buff, \"%d beginbfrange\\n\", glyphIndexToCharacter.size())\n\tindexs := glyphIndexToCharacter.allIndexs()\n\tfor _, k := range indexs {\n\t\tv, _ := glyphIndexToCharacter.runeByIndex(k)\n\t\tfmt.Fprintf(buff, \"<%04X><%04X><%04X>\\n\", k, k, v)\n\t}\n\tbuff.WriteString(\"endbfrange\\n\")\n\tbuff.WriteString(suffix)\n\tbuff.WriteString(\"\\n\")\n\n\tio.WriteString(w, \"<<\\n\")\n\tfmt.Fprintf(w, \"/Length %d\\n\", buff.Len())\n\tio.WriteString(w, \">>\\n\")\n\tio.WriteString(w, \"stream\\n\")\n\tif u.protection() != nil {\n\t\ttmp, err := rc4Cip(u.protection().objectkey(objID), buff.Bytes())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tw.Write(tmp)\n\t\t//streambuff.WriteString(\"\\n\")\n\t} else {\n\t\tbuff.WriteTo(w)\n\t}\n\tio.WriteString(w, \"endstream\\n\")\n\n\treturn nil\n}\n\ntype mapGlyphIndexToCharacter struct {\n\trunes  []rune\n\tindexs []int\n}\n\nfunc newMapGlyphIndexToCharacter() *mapGlyphIndexToCharacter {\n\tvar m mapGlyphIndexToCharacter\n\treturn &m\n}\n\nfunc (m *mapGlyphIndexToCharacter) set(index int, r rune) {\n\tm.runes = append(m.runes, r)\n\tm.indexs = append(m.indexs, index)\n}\n\nfunc (m *mapGlyphIndexToCharacter) size() int {\n\treturn len(m.indexs)\n}\n\nfunc (m *mapGlyphIndexToCharacter) allIndexs() []int {\n\treturn m.indexs\n}\n\nfunc (m *mapGlyphIndexToCharacter) runeByIndex(index int) (rune, bool) {\n\tvar r rune\n\tok := false\n\tfor i, idx := range m.indexs {\n\t\tif idx == index {\n\t\t\tr = m.runes[i]\n\t\t\tok = true\n\t\t\tbreak\n\t\t}\n\t}\n\treturn r, ok\n}\n"
  },
  {
    "path": "vendor/modules.txt",
    "content": "# github.com/phpdave11/gofpdi v1.0.11\ngithub.com/phpdave11/gofpdi\n# github.com/pkg/errors v0.8.1\ngithub.com/pkg/errors\n# github.com/signintech/gopdf v0.9.20\n## explicit\ngithub.com/signintech/gopdf\ngithub.com/signintech/gopdf/fontmaker/core\n"
  }
]