From 3319c51b75785b73101c8c9cd19a3eec8f494c0a Mon Sep 17 00:00:00 2001 From: Joe Westcott Date: Mon, 29 Apr 2019 19:59:53 +0100 Subject: Add SetFontStyle method (#248) --- def.go | 1 + fpdf.go | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/def.go b/def.go index fcc9237..ee0d3a6 100644 --- a/def.go +++ b/def.go @@ -426,6 +426,7 @@ type Pdf interface { SetFontLoader(loader FontLoader) SetFontLocation(fontDirStr string) SetFontSize(size float64) + SetFontStyle(styleStr string) SetFontUnitSize(size float64) SetFooterFunc(fnc func()) SetFooterFuncLpi(fnc func(lastPage bool)) diff --git a/fpdf.go b/fpdf.go index bd4aa4e..4053802 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1799,6 +1799,11 @@ func (f *Fpdf) SetFont(familyStr, styleStr string, size float64) { return } +// SetFontStyle sets the style of the current font. See also SetFont() +func (f *Fpdf) SetFontStyle(styleStr string) { + f.SetFont(f.fontFamily, styleStr, f.fontSizePt) +} + // SetFontSize defines the size of the current font. Size is specified in // points (1/ 72 inch). See also SetFontUnitSize(). func (f *Fpdf) SetFontSize(size float64) { -- cgit v1.2.1-24-ge1ad From 04d2090aeec620cca72622aa752cf53aaf0b0fbb Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 29 Apr 2019 15:05:06 -0400 Subject: Add go version in go.mod --- go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.mod b/go.mod index c7a180d..d5c6846 100644 --- a/go.mod +++ b/go.mod @@ -1 +1,3 @@ module github.com/jung-kurt/gofpdf + +go 1.12 -- cgit v1.2.1-24-ge1ad From 88c06828a097914c971a893f0048cd911e9b1a22 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 14:32:56 -0400 Subject: Use Lua script to generate README, doc.go and index.html rather than autoreadme --- .gitignore | 5 ++ Makefile | 31 +++++++ README.md | 185 +++++++++++++++++++++++------------------- check | 3 - cov | 1 - doc.go | 144 +++++++++++++++------------------ doc/doc.lua | 100 +++++++++++++++++++++++ doc/ftr.html | 3 + doc/hdr.html | 55 +++++++++++++ document.md | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mkdoc | 23 ------ 11 files changed, 620 insertions(+), 190 deletions(-) create mode 100644 Makefile delete mode 100755 check delete mode 100755 cov create mode 100644 doc/doc.lua create mode 100644 doc/ftr.html create mode 100644 doc/hdr.html create mode 100644 document.md delete mode 100755 mkdoc diff --git a/.gitignore b/.gitignore index b28eb22..87a2697 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,8 @@ private *.swp **/*.test .idea/ +doc/body.html +doc/body.md +doc/index.html +doc/index.html.ok +coverage.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5a78d8e --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +doc : README.md doc.go doc/index.html.ok + +test : + go test -v + +cov : + go test -v -coverprofile=coverage && go tool cover -html=coverage -o=coverage.html + +check : + golint . + go vet -all . + gofmt -s -l . + +%.html.ok : %.html + tidy -quiet -output /dev/null $< + touch $@ + +README.md doc.go doc/index.html : document.md + +doc/body.md README.md doc.go : document.md + lua doc/doc.lua + gofmt -s -w doc.go + +doc/index.html : doc/hdr.html doc/body.html doc/ftr.html + cat doc/hdr.html doc/body.html doc/ftr.html > $@ + +doc/body.html : doc/body.md + markdown -f +links,+image,+smarty,+ext,+divquote -o $@ $< + +clean : + rm -f coverage.html coverage doc/*.ok doc/body.md README.md doc.go doc/index.html doc/body.html diff --git a/README.md b/README.md index 54c4d55..145d798 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# gofpdf +# GoFPDF document generator -![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") +[![MIT licensed][badge-mit]][license] +[![Report][badge-report]][report] +[![GoDoc][badge-doc]][godoc] -[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/jung-kurt/gofpdf/master/license.txt) -[![GoDoc](https://godoc.org/github.com/jung-kurt/gofpdf?status.svg)](https://godoc.org/github.com/jung-kurt/gofpdf) -[![Build Status](https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master)](https://travis-ci.org/jung-kurt/gofpdf) +![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") Package gofpdf implements a PDF document generator with high level support for text, drawing and images. @@ -35,31 +35,29 @@ on Linux, Mac and Windows platforms. Like FPDF version 1.7, from which gofpdf is derived, this package does not yet support UTF-8 fonts. In particular, languages that require more than one code page such as Chinese, Japanese, and Arabic are not currently supported. This is -explained in [issue 109](https://github.com/jung-kurt/gofpdf/issues/109). However, support is provided to automatically translate -UTF-8 runes to code page encodings for languages that have fewer than 256 -glyphs. +explained in [issue 109][issue109]. However, support is provided to +automatically translate UTF-8 runes to code page encodings for languages that +have fewer than 256 glyphs. ## Installation - To install the package on your system, run -``` +```shell go get github.com/jung-kurt/gofpdf ``` Later, to receive updates, run -``` +```shell go get -u -v github.com/jung-kurt/gofpdf/... ``` ## Quick Start - The following Go code generates a simple PDF file. -``` +```go pdf := gofpdf.New("P", "mm", "A4", "") pdf.AddPage() pdf.SetFont("Arial", "B", 16) @@ -67,12 +65,12 @@ pdf.Cell(40, 10, "Hello, world") err := pdf.OutputFileAndClose("hello.pdf") ``` -See the functions in the [fpdf_test.go](https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go) file (shown as examples in this -documentation) for more advanced PDF examples. +See the functions in the +[fpdf_test.go][fpdf-test] +file (shown as examples in this documentation) for more advanced PDF examples. ## Errors - If an error occurs in an Fpdf method, an internal error field is set. After this occurs, Fpdf method calls typically return without performing any operations and the error state is retained. This error management scheme @@ -80,17 +78,18 @@ facilitates PDF generation since individual method calls do not need to be examined for failure; it is generally sufficient to wait until after Output() is called. For the same reason, if an error occurs in the calling application during PDF generation, it may be desirable for the application to transfer the -error to the Fpdf instance by calling the SetError() method or the SetErrorf() -method. At any time during the life cycle of the Fpdf instance, the error state -can be determined with a call to Ok() or Err(). The error itself can be -retrieved with a call to Error(). +error to the Fpdf instance by calling the `SetError()` method or the +`SetErrorf()` method. At any time during the life cycle of the Fpdf instance, +the error state can be determined with a call to `Ok()` or `Err()`. The error +itself can be retrieved with a call to `Error()`. ## Conversion Notes - -This package is a relatively straightforward translation from the original [FPDF](http://www.fpdf.org/) library written in PHP (despite the caveat in the introduction to [Effective -Go](https://golang.org/doc/effective_go.html)). The API names have been retained even though the Go idiom would suggest -otherwise (for example, pdf.GetX() is used rather than simply pdf.X()). The +This package is a relatively straightforward translation from the original +[FPDF][fpdf] library written in PHP (despite the caveat in the +introduction to [Effective Go][effective-go]). The +API names have been retained even though the Go idiom would suggest otherwise +(for example, `pdf.GetX()` is used rather than simply `pdf.X()`). The similarity of the two libraries makes the original FPDF website a good source of information. It includes a forum and FAQ. @@ -105,63 +104,60 @@ rather than PHP. ## Example PDFs - -A side effect of running "go test ./..." is the production of a number of +A side effect of running `go test ./...` is the production of a number of example PDFs. These can be found in the gofpdf/pdf directory after the tests complete. Please note that these examples run in the context of a test. In order run an -example as a standalone application, you'll need to examine [fpdf_test.go](https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go) for -some helper routines, for example exampleFilename() and summary(). +example as a standalone application, you'll need to examine +[fpdf_test.go][fpdf-test] for some helper routines, for example +`exampleFilename()` and `summary()`. Example PDFs can be compared with reference copies in order to verify that they have been generated as expected. This comparison will be performed if a PDF with the same name as the example PDF is placed in the gofpdf/pdf/reference -directory and if the third argument to ComparePDFFiles() in +directory and if the third argument to `ComparePDFFiles()` in internal/example/example.go is true. (By default it is false.) The routine that summarizes an example will look for this file and, if found, will call -ComparePDFFiles() to check the example PDF for equality with its reference PDF. +`ComparePDFFiles()` to check the example PDF for equality with its reference PDF. If differences exist between the two files they will be printed to standard output and the test will fail. If the reference file is missing, the comparison is considered to succeed. In order to successfully compare two PDFs, the placement of internal resources must be consistent and the internal creation -timestamps must be the same. To do this, the methods SetCatalogSort() and -SetCreationDate() need to be called for both files. This is done automatically +timestamps must be the same. To do this, the methods `SetCatalogSort()` and +`SetCreationDate()` need to be called for both files. This is done automatically for all examples. ## Nonstandard Fonts - Nothing special is required to use the standard PDF fonts (courier, helvetica, -times, zapfdingbats) in your documents other than calling SetFont(). +times, zapfdingbats) in your documents other than calling `SetFont()`. In order to use a different TrueType or Type1 font, you will need to generate a font definition file and, if the font will be embedded into PDFs, a compressed -version of the font file. This is done by calling the MakeFont function or +version of the font file. This is done by calling the `MakeFont()` function or using the included makefont command line utility. To create the utility, cd -into the makefont subdirectory and run "go build". This will produce a +into the makefont subdirectory and run `go build`. This will produce a standalone executable named makefont. Select the appropriate encoding file from the font subdirectory and run the command as in the following example. -``` +```shell ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf ``` In your PDF generation code, call AddFont() to load the font and, as with the standard fonts, SetFont() to begin using it. Most examples, including the package example, demonstrate this method. Good sources of free, open-source -fonts include [Google Fonts](http://www.google.com/fonts/) and [DejaVu Fonts](http://dejavu-fonts.org/). +fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. ## Related Packages - -The [draw2d](https://github.com/llgcode/draw2d) package is a two dimensional -vector graphics library that can generate output in different forms. It uses -gofpdf for its document production mode. +The [draw2d][draw2d] package is a two dimensional vector graphics library that +can generate output in different forms. It uses gofpdf for its document +production mode. ## Contributing Changes - gofpdf is a global community effort and you are invited to make it even better. If you have implemented a new feature or corrected a problem, please consider contributing your change to the project. A contribution that does not directly @@ -173,56 +169,54 @@ Here are guidelines for making submissions. Your change should * be compatible with the MIT License * be properly documented * be formatted with `go fmt` -* include an example in [fpdf_test.go](https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go) if appropriate -* conform to the standards of [golint](https://github.com/golang/lint) and -[go vet](https://godoc.org/golang.org/x/tools/cmd/vet), that is, `golint .` and +* include an example in [fpdf_test.go][test] if appropriate +* conform to the standards of [golint][lint] and +[go vet][vet], that is, `golint .` and `go vet .` should not generate any warnings -* not diminish [test coverage](https://blog.golang.org/cover) +* not diminish [test coverage][coverage] -[Pull requests](https://help.github.com/articles/using-pull-requests/) work -nicely as a means of contributing your changes. +[Pull requests][pr] are the preferred means of accepting your changes. ## License - gofpdf is released under the MIT License. It is copyrighted by Kurt Jung and the contributors acknowledged below. ## Acknowledgments - -This package's code and documentation are closely derived from the [FPDF](http://www.fpdf.org/) library created by Olivier Plathey, and a number of font and -image resources are copied directly from it. Bruno Michel has provided valuable -assistance with the code. Drawing support is adapted from the FPDF geometric -figures script by David Hernández Sanz. Transparency support is adapted from -the FPDF transparency script by Martin Hall-May. Support for gradients and -clipping is adapted from FPDF scripts by Andreas Würmser. Support for outline -bookmarks is adapted from Olivier Plathey by Manuel Cornes. Layer support is -adapted from Olivier Plathey. Support for transformations is adapted from the -FPDF transformation script by Moritz Wagner and Andreas Würmser. PDF -protection is adapted from the work of Klemen Vodopivec for the FPDF product. -Lawrence Kesteloot provided code to allow an image's extent to be determined -prior to placement. Support for vertical alignment within a cell was provided -by Stefan Schroeder. Ivan Daniluk generalized the font and image loading code -to use the Reader interface while maintaining backward compatibility. Anthony -Starks provided code for the Polygon function. Robert Lillack provided the -Beziergon function and corrected some naming issues with the internal curve -function. Claudio Felber provided implementations for dashed line drawing and -generalized font loading. Stani Michiels provided support for multi-segment -path drawing with smooth line joins, line join styles, enhanced fill modes, and -has helped greatly with package presentation and tests. Templating is adapted -by Marcus Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. -Jelmer Snoeck contributed packages that generate a variety of barcodes and help -with registering images on the web. Jelmer Snoek and Guillermo Pascual -augmented the basic HTML functionality with aligned text. Kent Quirk -implemented backwards-compatible support for reading DPI from images that -support it, and for setting DPI manually and then having it properly taken into -account when calculating image size. Paulo Coutinho provided support for static -embedded fonts. Dan Meyers added support for embedded JavaScript. David Fish -added a generic alias-replacement function to enable, among other things, table -of contents functionality. Andy Bakun identified and corrected a problem in -which the internal catalogs were not sorted stably. Paul Montag added encoding -and decoding functionality for templates, including images that are embedded in +This package's code and documentation are closely derived from the [FPDF][fpdf] +library created by Olivier Plathey, and a number of font and image resources +are copied directly from it. Bruno Michel has provided valuable assistance with +the code. Drawing support is adapted from the FPDF geometric figures script by +David Hernández Sanz. Transparency support is adapted from the FPDF +transparency script by Martin Hall-May. Support for gradients and clipping is +adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is +adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from +Olivier Plathey. Support for transformations is adapted from the FPDF +transformation script by Moritz Wagner and Andreas Würmser. PDF protection is +adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence +Kesteloot provided code to allow an image's extent to be determined prior to +placement. Support for vertical alignment within a cell was provided by Stefan +Schroeder. Ivan Daniluk generalized the font and image loading code to use the +Reader interface while maintaining backward compatibility. Anthony Starks +provided code for the Polygon function. Robert Lillack provided the Beziergon +function and corrected some naming issues with the internal curve function. +Claudio Felber provided implementations for dashed line drawing and generalized +font loading. Stani Michiels provided support for multi-segment path drawing +with smooth line joins, line join styles, enhanced fill modes, and has helped +greatly with package presentation and tests. Templating is adapted by Marcus +Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer +Snoeck contributed packages that generate a variety of barcodes and help with +registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the +basic HTML functionality with aligned text. Kent Quirk implemented +backwards-compatible support for reading DPI from images that support it, and +for setting DPI manually and then having it properly taken into account when +calculating image size. Paulo Coutinho provided support for static embedded +fonts. Dan Meyers added support for embedded JavaScript. David Fish added a +generic alias-replacement function to enable, among other things, table of +contents functionality. Andy Bakun identified and corrected a problem in which +the internal catalogs were not sorted stably. Paul Montag added encoding and +decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. @@ -233,4 +227,27 @@ Matusiak added supported for word spacing. UTF-8 runes to code page bytes is provided. * Improve test coverage as reported by the coverage tool. - +[badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg +[badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg +[badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg +[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg +[badge-report]: https://goreportcard.com/badge/github.com/jung-kurt/gofpdf +[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master) +[coverage]: https://blog.golang.org/cover +[dfont]: http://dejavu-fonts.org/ +[draw2d]: https://github.com/llgcode/draw2d +[fpdf]: http://www.fpdf.org/ +[gfont]: http://www.google.com/fonts/ +[github]: https://github.com/jung-kurt/gofpdf +[godoc]: https://godoc.org/github.com/jung-kurt/gofpdf +[jung]: https://github.com/jung-kurt/ +[license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE +[lint]: https://github.com/golang/lint +[pr]: https://help.github.com/articles/using-pull-requests/ +[report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf +[status]: https://travis-ci.org/jung-kurt/gofpdf +[test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[vet]: https://godoc.org/golang.org/x/tools/cmd/vet +[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 +[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[effective-go]: https://golang.org/doc/effective_go.html \ No newline at end of file diff --git a/check b/check deleted file mode 100755 index dcc2519..0000000 --- a/check +++ /dev/null @@ -1,3 +0,0 @@ -golint . -go vet -all . -gofmt -s -l . diff --git a/cov b/cov deleted file mode 100755 index a07edce..0000000 --- a/cov +++ /dev/null @@ -1 +0,0 @@ -go test -coverprofile=coverage && go tool cover -html=coverage diff --git a/doc.go b/doc.go index 6492f7e..78afc23 100644 --- a/doc.go +++ b/doc.go @@ -1,19 +1,3 @@ -/* - * Copyright (c) 2013-2017 Kurt Jung (Gmail: kurt.w.jung) - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - /* Package gofpdf implements a PDF document generator with high level support for text, drawing and images. @@ -60,9 +44,9 @@ on Linux, Mac and Windows platforms. Like FPDF version 1.7, from which gofpdf is derived, this package does not yet support UTF-8 fonts. In particular, languages that require more than one code page such as Chinese, Japanese, and Arabic are not currently supported. This is -explained in issue 109. However, support is provided to automatically translate -UTF-8 runes to code page encodings for languages that have fewer than 256 -glyphs. +explained in issue 109. However, support is provided to +automatically translate UTF-8 runes to code page encodings for languages that +have fewer than 256 glyphs. Installation @@ -84,8 +68,9 @@ The following Go code generates a simple PDF file. pdf.Cell(40, 10, "Hello, world") err := pdf.OutputFileAndClose("hello.pdf") -See the functions in the fpdf_test.go file (shown as examples in this -documentation) for more advanced PDF examples. +See the functions in the +fpdf_test.go +file (shown as examples in this documentation) for more advanced PDF examples. Errors @@ -96,17 +81,18 @@ facilitates PDF generation since individual method calls do not need to be examined for failure; it is generally sufficient to wait until after Output() is called. For the same reason, if an error occurs in the calling application during PDF generation, it may be desirable for the application to transfer the -error to the Fpdf instance by calling the SetError() method or the SetErrorf() -method. At any time during the life cycle of the Fpdf instance, the error state -can be determined with a call to Ok() or Err(). The error itself can be -retrieved with a call to Error(). +error to the Fpdf instance by calling the SetError() method or the +SetErrorf() method. At any time during the life cycle of the Fpdf instance, +the error state can be determined with a call to Ok() or Err(). The error +itself can be retrieved with a call to Error(). Conversion Notes -This package is a relatively straightforward translation from the original FPDF -library written in PHP (despite the caveat in the introduction to Effective -Go). The API names have been retained even though the Go idiom would suggest -otherwise (for example, pdf.GetX() is used rather than simply pdf.X()). The +This package is a relatively straightforward translation from the original +FPDF library written in PHP (despite the caveat in the +introduction to Effective Go). The +API names have been retained even though the Go idiom would suggest otherwise +(for example, pdf.GetX() is used rather than simply pdf.X()). The similarity of the two libraries makes the original FPDF website a good source of information. It includes a forum and FAQ. @@ -121,13 +107,14 @@ rather than PHP. Example PDFs -A side effect of running "go test ./..." is the production of a number of +A side effect of running go test ./... is the production of a number of example PDFs. These can be found in the gofpdf/pdf directory after the tests complete. Please note that these examples run in the context of a test. In order run an -example as a standalone application, you'll need to examine fpdf_test.go for -some helper routines, for example exampleFilename() and summary(). +example as a standalone application, you'll need to examine +fpdf_test.go for some helper routines, for example +exampleFilename() and summary(). Example PDFs can be compared with reference copies in order to verify that they have been generated as expected. This comparison will be performed if a PDF @@ -151,9 +138,9 @@ times, zapfdingbats) in your documents other than calling SetFont(). In order to use a different TrueType or Type1 font, you will need to generate a font definition file and, if the font will be embedded into PDFs, a compressed -version of the font file. This is done by calling the MakeFont function or +version of the font file. This is done by calling the MakeFont() function or using the included makefont command line utility. To create the utility, cd -into the makefont subdirectory and run "go build". This will produce a +into the makefont subdirectory and run go build. This will produce a standalone executable named makefont. Select the appropriate encoding file from the font subdirectory and run the command as in the following example. @@ -162,13 +149,13 @@ the font subdirectory and run the command as in the following example. In your PDF generation code, call AddFont() to load the font and, as with the standard fonts, SetFont() to begin using it. Most examples, including the package example, demonstrate this method. Good sources of free, open-source -fonts include http://www.google.com/fonts/ and http://dejavu-fonts.org/. +fonts include Google Fonts and DejaVu Fonts. Related Packages -The draw2d package (https://github.com/llgcode/draw2d) is a two dimensional -vector graphics library that can generate output in different forms. It uses -gofpdf for its document production mode. +The draw2d package is a two dimensional vector graphics library that +can generate output in different forms. It uses gofpdf for its document +production mode. Contributing Changes @@ -176,7 +163,7 @@ gofpdf is a global community effort and you are invited to make it even better. If you have implemented a new feature or corrected a problem, please consider contributing your change to the project. A contribution that does not directly pertain to the core functionality of gofpdf should be placed in its own -directory directly beneath the `contrib` directory. +directory directly beneath the contrib directory. Here are guidelines for making submissions. Your change should @@ -184,18 +171,17 @@ Here are guidelines for making submissions. Your change should • be properly documented -• be formatted with `go fmt` +• be formatted with go fmt • include an example in fpdf_test.go if appropriate -• conform to the standards of golint (https://github.com/golang/lint) and -go vet (https://godoc.org/golang.org/x/tools/cmd/vet), that is, `golint .` and -`go vet .` should not generate any warnings +• conform to the standards of golint and +go vet, that is, golint . and +go vet . should not generate any warnings -• not diminish test coverage (https://blog.golang.org/cover) +• not diminish test coverage -Pull requests (https://help.github.com/articles/using-pull-requests/) work -nicely as a means of contributing your changes. +Pull requests are the preferred means of accepting your changes. License @@ -204,39 +190,39 @@ the contributors acknowledged below. Acknowledgments -This package's code and documentation are closely derived from the FPDF library -(http://www.fpdf.org/) created by Olivier Plathey, and a number of font and -image resources are copied directly from it. Bruno Michel has provided valuable -assistance with the code. Drawing support is adapted from the FPDF geometric -figures script by David Hernández Sanz. Transparency support is adapted from -the FPDF transparency script by Martin Hall-May. Support for gradients and -clipping is adapted from FPDF scripts by Andreas Würmser. Support for outline -bookmarks is adapted from Olivier Plathey by Manuel Cornes. Layer support is -adapted from Olivier Plathey. Support for transformations is adapted from the -FPDF transformation script by Moritz Wagner and Andreas Würmser. PDF -protection is adapted from the work of Klemen Vodopivec for the FPDF product. -Lawrence Kesteloot provided code to allow an image's extent to be determined -prior to placement. Support for vertical alignment within a cell was provided -by Stefan Schroeder. Ivan Daniluk generalized the font and image loading code -to use the Reader interface while maintaining backward compatibility. Anthony -Starks provided code for the Polygon function. Robert Lillack provided the -Beziergon function and corrected some naming issues with the internal curve -function. Claudio Felber provided implementations for dashed line drawing and -generalized font loading. Stani Michiels provided support for multi-segment -path drawing with smooth line joins, line join styles, enhanced fill modes, and -has helped greatly with package presentation and tests. Templating is adapted -by Marcus Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. -Jelmer Snoeck contributed packages that generate a variety of barcodes and help -with registering images on the web. Jelmer Snoek and Guillermo Pascual -augmented the basic HTML functionality with aligned text. Kent Quirk -implemented backwards-compatible support for reading DPI from images that -support it, and for setting DPI manually and then having it properly taken into -account when calculating image size. Paulo Coutinho provided support for static -embedded fonts. Dan Meyers added support for embedded JavaScript. David Fish -added a generic alias-replacement function to enable, among other things, table -of contents functionality. Andy Bakun identified and corrected a problem in -which the internal catalogs were not sorted stably. Paul Montag added encoding -and decoding functionality for templates, including images that are embedded in +This package's code and documentation are closely derived from the FPDF +library created by Olivier Plathey, and a number of font and image resources +are copied directly from it. Bruno Michel has provided valuable assistance with +the code. Drawing support is adapted from the FPDF geometric figures script by +David Hernández Sanz. Transparency support is adapted from the FPDF +transparency script by Martin Hall-May. Support for gradients and clipping is +adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is +adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from +Olivier Plathey. Support for transformations is adapted from the FPDF +transformation script by Moritz Wagner and Andreas Würmser. PDF protection is +adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence +Kesteloot provided code to allow an image's extent to be determined prior to +placement. Support for vertical alignment within a cell was provided by Stefan +Schroeder. Ivan Daniluk generalized the font and image loading code to use the +Reader interface while maintaining backward compatibility. Anthony Starks +provided code for the Polygon function. Robert Lillack provided the Beziergon +function and corrected some naming issues with the internal curve function. +Claudio Felber provided implementations for dashed line drawing and generalized +font loading. Stani Michiels provided support for multi-segment path drawing +with smooth line joins, line join styles, enhanced fill modes, and has helped +greatly with package presentation and tests. Templating is adapted by Marcus +Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer +Snoeck contributed packages that generate a variety of barcodes and help with +registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the +basic HTML functionality with aligned text. Kent Quirk implemented +backwards-compatible support for reading DPI from images that support it, and +for setting DPI manually and then having it properly taken into account when +calculating image size. Paulo Coutinho provided support for static embedded +fonts. Dan Meyers added support for embedded JavaScript. David Fish added a +generic alias-replacement function to enable, among other things, table of +contents functionality. Andy Bakun identified and corrected a problem in which +the internal catalogs were not sorted stably. Paul Montag added encoding and +decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. diff --git a/doc/doc.lua b/doc/doc.lua new file mode 100644 index 0000000..dbe87c1 --- /dev/null +++ b/doc/doc.lua @@ -0,0 +1,100 @@ +-- This script reads a single page of Markdown-like documentation and generates +-- output in three different forms: gofmt, git-flavored markdown, and +-- standard markdown. + +local gsub, match, len, find, concat, insert = +string.gsub, string.match, string.len, string.find, table.concat, table.insert + +local function write(filestr, str) + local f = io.open(filestr, 'w+') + if f then + f:write(str) + f:close() + end +end + +local function codeblock(tbl, mode) + local newtbl = {} + local incode = false + local pos1, pos2, prefix, syntax + for j, str in ipairs(tbl) do + prefix, syntax = match(str, '^(```)(%a*)') + if prefix and len(syntax) > 0 then + incode = true + if mode == 'r' then + insert(newtbl, str) + end + elseif prefix then + incode = false + if mode == 'r' then + insert(newtbl, str) + end + else + if incode and mode ~= 'r' then + str = '\t' .. str + end + insert(newtbl, str) + end + end + return newtbl +end + +local function markdownwrite(tbl, filestr) + tbl = codeblock(tbl, 'm') + local str = concat(tbl, '\n') + write(filestr, str) +end + +local function readmewrite(tbl, filestr) + tbl = codeblock(tbl, 'r') + local str = concat(tbl, '\n') + str = gsub(str, '\n%> ', '\n') + -- str = gsub(str, '%b<>', '') + write(filestr, str) +end + +local function godocwrite(tbl, filestr) + tbl = codeblock(tbl, 'g') + for j, str in ipairs(tbl) do + str = gsub(str, '^#+ *', '') + tbl[j] = gsub(str, '^* ', '\n• ') + end + local str = concat(tbl, '\n') + str = gsub(str, '\n\n\n+', '\n\n') + str = gsub(str, '\n%> ', '\n') + str = gsub(str, '`', '') + str = gsub(str, '/%*', '\x01') + str = gsub(str, '%*', '') + str = gsub(str, '\x01', '\x2f*') + -- str = gsub(str, '%b<>', '') + -- replace [foo][bar] with foo + str = gsub(str, '%[(%C-)%]%[%C-%]', '%1') + str = '/*\n' .. str .. '\n*/\npackage gofpdf\n' + write(filestr, str) +end + +local godoc, markdown, readme = {}, {}, {} +local modeg, modem, moder + +for str in io.lines('document.md') do + local mode = string.match(str, '^~(%a*)~$') + if mode then + modeg = find(mode, 'g') ~= nil + moder = find(mode, 'r') ~= nil + modem = find(mode, 'm') ~= nil + else + if modeg then + insert(godoc, str) + end + if modem then + insert(markdown, str) + end + if moder then + insert(readme, str) + end + end +end + +markdownwrite(markdown, 'doc/body.md') +godocwrite(godoc, 'doc.go') +readmewrite(readme, 'README.md') diff --git a/doc/ftr.html b/doc/ftr.html new file mode 100644 index 0000000..47fc456 --- /dev/null +++ b/doc/ftr.html @@ -0,0 +1,3 @@ + + + diff --git a/doc/hdr.html b/doc/hdr.html new file mode 100644 index 0000000..bbc2758 --- /dev/null +++ b/doc/hdr.html @@ -0,0 +1,55 @@ + + + + + + + CGI for Caddy + + + + diff --git a/document.md b/document.md new file mode 100644 index 0000000..69aaf41 --- /dev/null +++ b/document.md @@ -0,0 +1,260 @@ +~rm~ +# GoFPDF document generator + +~m~ +[![Git Hub repository][badge-github]][github] +[![Kurt Jung][badge-author]][jung] +~rm~ +[![MIT licensed][badge-mit]][license] +[![Report][badge-report]][report] +[![GoDoc][badge-doc]][godoc] + +![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") + +~rgm~ +Package gofpdf implements a PDF document generator with high level support for +text, drawing and images. + +## Features + +* Choice of measurement unit, page format and margins +* Page header and footer management +* Automatic page breaks, line breaks, and text justification +* Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images +* Colors, gradients and alpha channel transparency +* Outline bookmarks +* Internal and external links +* TrueType, Type1 and encoding support +* Page compression +* Lines, Bézier curves, arcs, and ellipses +* Rotation, scaling, skewing, translation, and mirroring +* Clipping +* Document protection +* Layers +* Templates +* Barcodes +* Charting facility + +gofpdf has no dependencies other than the Go standard library. All tests pass +on Linux, Mac and Windows platforms. + +Like FPDF version 1.7, from which gofpdf is derived, this package does not yet +support UTF-8 fonts. In particular, languages that require more than one code +page such as Chinese, Japanese, and Arabic are not currently supported. This is +explained in [issue 109][issue109]. However, support is provided to +automatically translate UTF-8 runes to code page encodings for languages that +have fewer than 256 glyphs. + +## Installation + +To install the package on your system, run + +```shell +go get github.com/jung-kurt/gofpdf +``` + +Later, to receive updates, run + +```shell +go get -u -v github.com/jung-kurt/gofpdf/... +``` + +## Quick Start + +The following Go code generates a simple PDF file. + +```go +pdf := gofpdf.New("P", "mm", "A4", "") +pdf.AddPage() +pdf.SetFont("Arial", "B", 16) +pdf.Cell(40, 10, "Hello, world") +err := pdf.OutputFileAndClose("hello.pdf") +``` + +See the functions in the +[fpdf_test.go][fpdf-test] +file (shown as examples in this documentation) for more advanced PDF examples. + +## Errors + +If an error occurs in an Fpdf method, an internal error field is set. After +this occurs, Fpdf method calls typically return without performing any +operations and the error state is retained. This error management scheme +facilitates PDF generation since individual method calls do not need to be +examined for failure; it is generally sufficient to wait until after Output() +is called. For the same reason, if an error occurs in the calling application +during PDF generation, it may be desirable for the application to transfer the +error to the Fpdf instance by calling the `SetError()` method or the +`SetErrorf()` method. At any time during the life cycle of the Fpdf instance, +the error state can be determined with a call to `Ok()` or `Err()`. The error +itself can be retrieved with a call to `Error()`. + +## Conversion Notes + +This package is a relatively straightforward translation from the original +[FPDF][fpdf] library written in PHP (despite the caveat in the +introduction to [Effective Go][effective-go]). The +API names have been retained even though the Go idiom would suggest otherwise +(for example, `pdf.GetX()` is used rather than simply `pdf.X()`). The +similarity of the two libraries makes the original FPDF website a good source +of information. It includes a forum and FAQ. + +However, some internal changes have been made. Page content is built up using +buffers (of type bytes.Buffer) rather than repeated string concatenation. +Errors are handled as explained above rather than panicking. Output is +generated through an interface of type io.Writer or io.WriteCloser. A number of +the original PHP methods behave differently based on the type of the arguments +that are passed to them; in these cases additional methods have been exported +to provide similar functionality. Font definition files are produced in JSON +rather than PHP. + +## Example PDFs + +A side effect of running `go test ./...` is the production of a number of +example PDFs. These can be found in the gofpdf/pdf directory after the tests +complete. + +Please note that these examples run in the context of a test. In order run an +example as a standalone application, you'll need to examine +[fpdf_test.go][fpdf-test] for some helper routines, for example +`exampleFilename()` and `summary()`. + +Example PDFs can be compared with reference copies in order to verify that they +have been generated as expected. This comparison will be performed if a PDF +with the same name as the example PDF is placed in the gofpdf/pdf/reference +directory and if the third argument to `ComparePDFFiles()` in +internal/example/example.go is true. (By default it is false.) The routine that +summarizes an example will look for this file and, if found, will call +`ComparePDFFiles()` to check the example PDF for equality with its reference PDF. +If differences exist between the two files they will be printed to standard +output and the test will fail. If the reference file is missing, the comparison +is considered to succeed. In order to successfully compare two PDFs, the +placement of internal resources must be consistent and the internal creation +timestamps must be the same. To do this, the methods `SetCatalogSort()` and +`SetCreationDate()` need to be called for both files. This is done automatically +for all examples. + +## Nonstandard Fonts + +Nothing special is required to use the standard PDF fonts (courier, helvetica, +times, zapfdingbats) in your documents other than calling `SetFont()`. + +In order to use a different TrueType or Type1 font, you will need to generate a +font definition file and, if the font will be embedded into PDFs, a compressed +version of the font file. This is done by calling the `MakeFont()` function or +using the included makefont command line utility. To create the utility, cd +into the makefont subdirectory and run `go build`. This will produce a +standalone executable named makefont. Select the appropriate encoding file from +the font subdirectory and run the command as in the following example. + +```shell +./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf +``` + +In your PDF generation code, call AddFont() to load the font and, as with the +standard fonts, SetFont() to begin using it. Most examples, including the +package example, demonstrate this method. Good sources of free, open-source +fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. + +## Related Packages + +The [draw2d][draw2d] package is a two dimensional vector graphics library that +can generate output in different forms. It uses gofpdf for its document +production mode. + +## Contributing Changes + +gofpdf is a global community effort and you are invited to make it even better. +If you have implemented a new feature or corrected a problem, please consider +contributing your change to the project. A contribution that does not directly +pertain to the core functionality of gofpdf should be placed in its own +directory directly beneath the `contrib` directory. + +Here are guidelines for making submissions. Your change should + +* be compatible with the MIT License +* be properly documented +* be formatted with `go fmt` +* include an example in [fpdf_test.go][test] if appropriate +* conform to the standards of [golint][lint] and +[go vet][vet], that is, `golint .` and +`go vet .` should not generate any warnings +* not diminish [test coverage][coverage] + +[Pull requests][pr] are the preferred means of accepting your changes. + +## License + +gofpdf is released under the MIT License. It is copyrighted by Kurt Jung and +the contributors acknowledged below. + +## Acknowledgments + +This package's code and documentation are closely derived from the [FPDF][fpdf] +library created by Olivier Plathey, and a number of font and image resources +are copied directly from it. Bruno Michel has provided valuable assistance with +the code. Drawing support is adapted from the FPDF geometric figures script by +David Hernández Sanz. Transparency support is adapted from the FPDF +transparency script by Martin Hall-May. Support for gradients and clipping is +adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is +adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from +Olivier Plathey. Support for transformations is adapted from the FPDF +transformation script by Moritz Wagner and Andreas Würmser. PDF protection is +adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence +Kesteloot provided code to allow an image's extent to be determined prior to +placement. Support for vertical alignment within a cell was provided by Stefan +Schroeder. Ivan Daniluk generalized the font and image loading code to use the +Reader interface while maintaining backward compatibility. Anthony Starks +provided code for the Polygon function. Robert Lillack provided the Beziergon +function and corrected some naming issues with the internal curve function. +Claudio Felber provided implementations for dashed line drawing and generalized +font loading. Stani Michiels provided support for multi-segment path drawing +with smooth line joins, line join styles, enhanced fill modes, and has helped +greatly with package presentation and tests. Templating is adapted by Marcus +Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer +Snoeck contributed packages that generate a variety of barcodes and help with +registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the +basic HTML functionality with aligned text. Kent Quirk implemented +backwards-compatible support for reading DPI from images that support it, and +for setting DPI manually and then having it properly taken into account when +calculating image size. Paulo Coutinho provided support for static embedded +fonts. Dan Meyers added support for embedded JavaScript. David Fish added a +generic alias-replacement function to enable, among other things, table of +contents functionality. Andy Bakun identified and corrected a problem in which +the internal catalogs were not sorted stably. Paul Montag added encoding and +decoding functionality for templates, including images that are embedded in +templates; this allows templates to be stored independently of gofpdf. Paul +also added support for page boxes used in printing PDF documents. Wojciech +Matusiak added supported for word spacing. + +## Roadmap + +* Handle UTF-8 source text natively. Until then, automatic translation of +UTF-8 runes to code page bytes is provided. +* Improve test coverage as reported by the coverage tool. + +~mr~ +[badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg +[badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg +[badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg +[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg +[badge-report]: https://goreportcard.com/badge/github.com/jung-kurt/gofpdf +[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master) +[coverage]: https://blog.golang.org/cover +[dfont]: http://dejavu-fonts.org/ +[draw2d]: https://github.com/llgcode/draw2d +[fpdf]: http://www.fpdf.org/ +[gfont]: http://www.google.com/fonts/ +[github]: https://github.com/jung-kurt/gofpdf +[godoc]: https://godoc.org/github.com/jung-kurt/gofpdf +[jung]: https://github.com/jung-kurt/ +[license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE +[lint]: https://github.com/golang/lint +[pr]: https://help.github.com/articles/using-pull-requests/ +[report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf +[status]: https://travis-ci.org/jung-kurt/gofpdf +[test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[vet]: https://godoc.org/golang.org/x/tools/cmd/vet +[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 +[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[effective-go]: https://golang.org/doc/effective_go.html diff --git a/mkdoc b/mkdoc deleted file mode 100755 index 8c082c3..0000000 --- a/mkdoc +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# https://github.com/jimmyfrasche/autoreadme -autoreadme -f -template README.md.template -# Improve the appearance of the markdown document with features unavailable in godoc -cat README.md | tr '\n' '\v' | sed \ - -e 's/\v##\([^\v]*\)/\v## \1\v\v/g' \ - -e 's/\v• /* /g' \ - -e 's/\(http:\/\/www\.google\.com\/fonts\/\)/[Google Fonts](\1)/g' \ - -e 's/\(http:\/\/dejavu-fonts\.org\/\)/[DejaVu Fonts](\1)/g' \ - -e 's/draw2d.package.(\(https:\/\/github\.com\/llgcode\/draw2d\))/[draw2d](\1) package/g' \ - -e 's/FPDF.library.(\(http:\/\/www\.fpdf\.org\/\))/[FPDF](\1) library/g' \ - -e 's/original.FPDF.library/original [FPDF](http:\/\/www.fpdf.org\/) library/g' \ - -e 's/\(Effective.Go\)/[\1](https:\/\/golang.org\/doc\/effective_go.html)/g' \ - -e 's/\(fpdf_test.go\)/[\1](https:\/\/github.com\/jung-kurt\/gofpdf\/blob\/master\/fpdf_test.go)/g' \ - -e 's/golint.(\(https:\/\/github\.com\/golang\/lint\))/[golint](\1)/g' \ - -e 's/go.vet.(\(https:\/\/godoc\.org\/golang\.org\/x\/tools\/cmd\/vet\))/[go vet](\1)/g' \ - -e 's/test.coverage.(\(https:\/\/blog\.golang\.org\/cover\))/[test coverage](\1)/g' \ - -e 's/Pull.requests.(\(https:\/\/help\.github\.com\/articles\/using\-pull\-requests\/\))/[Pull requests](\1)/g' \ - -e 's/Your change should\v/Your change should\v\v/g' \ - -e 's/issue 109/[issue 109](https:\/\/github.com\/jung-kurt\/gofpdf\/issues\/109)/g' \ - | tr '\v' '\n' > _0 -mv _0 README.md -- cgit v1.2.1-24-ge1ad From f5370ee922127973ea8aaf3aa6c0acc1082a8ab6 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 14:44:34 -0400 Subject: Remove badges in README --- README.md | 10 +++++----- document.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 145d798..1f1c72b 100644 --- a/README.md +++ b/README.md @@ -236,10 +236,13 @@ UTF-8 runes to code page bytes is provided. [coverage]: https://blog.golang.org/cover [dfont]: http://dejavu-fonts.org/ [draw2d]: https://github.com/llgcode/draw2d +[effective-go]: https://golang.org/doc/effective_go.html [fpdf]: http://www.fpdf.org/ -[gfont]: http://www.google.com/fonts/ +[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[gfont]: https://fonts.google.com/ [github]: https://github.com/jung-kurt/gofpdf [godoc]: https://godoc.org/github.com/jung-kurt/gofpdf +[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 [jung]: https://github.com/jung-kurt/ [license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE [lint]: https://github.com/golang/lint @@ -247,7 +250,4 @@ UTF-8 runes to code page bytes is provided. [report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf [status]: https://travis-ci.org/jung-kurt/gofpdf [test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[vet]: https://godoc.org/golang.org/x/tools/cmd/vet -[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 -[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[effective-go]: https://golang.org/doc/effective_go.html \ No newline at end of file +[vet]: https://godoc.org/golang.org/x/tools/cmd/vet \ No newline at end of file diff --git a/document.md b/document.md index 69aaf41..3de4146 100644 --- a/document.md +++ b/document.md @@ -1,7 +1,7 @@ ~rm~ # GoFPDF document generator -~m~ +~x~ [![Git Hub repository][badge-github]][github] [![Kurt Jung][badge-author]][jung] ~rm~ @@ -243,10 +243,13 @@ UTF-8 runes to code page bytes is provided. [coverage]: https://blog.golang.org/cover [dfont]: http://dejavu-fonts.org/ [draw2d]: https://github.com/llgcode/draw2d +[effective-go]: https://golang.org/doc/effective_go.html [fpdf]: http://www.fpdf.org/ -[gfont]: http://www.google.com/fonts/ +[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[gfont]: https://fonts.google.com/ [github]: https://github.com/jung-kurt/gofpdf [godoc]: https://godoc.org/github.com/jung-kurt/gofpdf +[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 [jung]: https://github.com/jung-kurt/ [license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE [lint]: https://github.com/golang/lint @@ -255,6 +258,3 @@ UTF-8 runes to code page bytes is provided. [status]: https://travis-ci.org/jung-kurt/gofpdf [test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go [vet]: https://godoc.org/golang.org/x/tools/cmd/vet -[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 -[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[effective-go]: https://golang.org/doc/effective_go.html -- cgit v1.2.1-24-ge1ad From 60d76ba19a24fffa319b95a0d31122449e2a7e7b Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 14:52:02 -0400 Subject: Try again to remove badges in README --- README.md | 6 ------ document.md | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 1f1c72b..2090d00 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,5 @@ # GoFPDF document generator -[![MIT licensed][badge-mit]][license] -[![Report][badge-report]][report] -[![GoDoc][badge-doc]][godoc] - -![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") - Package gofpdf implements a PDF document generator with high level support for text, drawing and images. diff --git a/document.md b/document.md index 3de4146..359e033 100644 --- a/document.md +++ b/document.md @@ -4,7 +4,7 @@ ~x~ [![Git Hub repository][badge-github]][github] [![Kurt Jung][badge-author]][jung] -~rm~ +~x~ [![MIT licensed][badge-mit]][license] [![Report][badge-report]][report] [![GoDoc][badge-doc]][godoc] -- cgit v1.2.1-24-ge1ad From 54f3906c54220782edebd4fef4d8052d0d1d658e Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 15:17:28 -0400 Subject: Remove README template --- Makefile | 2 -- README.md | 2 ++ README.md.template | 9 --------- document.md | 5 +++-- 4 files changed, 5 insertions(+), 13 deletions(-) delete mode 100644 README.md.template diff --git a/Makefile b/Makefile index 5a78d8e..887ffd8 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,6 @@ check : tidy -quiet -output /dev/null $< touch $@ -README.md doc.go doc/index.html : document.md - doc/body.md README.md doc.go : document.md lua doc/doc.lua gofmt -s -w doc.go diff --git a/README.md b/README.md index 2090d00..3005d76 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # GoFPDF document generator +![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") + Package gofpdf implements a PDF document generator with high level support for text, drawing and images. diff --git a/README.md.template b/README.md.template deleted file mode 100644 index 8caf572..0000000 --- a/README.md.template +++ /dev/null @@ -1,9 +0,0 @@ -# gofpdf - -![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") - -[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/jung-kurt/gofpdf/master/license.txt) -[![GoDoc](https://godoc.org/github.com/jung-kurt/gofpdf?status.svg)](https://godoc.org/github.com/jung-kurt/gofpdf) -[![Build Status](https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master)](https://travis-ci.org/jung-kurt/gofpdf) - -{{.Doc}} diff --git a/document.md b/document.md index 359e033..030c96b 100644 --- a/document.md +++ b/document.md @@ -1,14 +1,15 @@ ~rm~ # GoFPDF document generator -~x~ +~m~ [![Git Hub repository][badge-github]][github] [![Kurt Jung][badge-author]][jung] -~x~ +~m~ [![MIT licensed][badge-mit]][license] [![Report][badge-report]][report] [![GoDoc][badge-doc]][godoc] +~rm~ ![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") ~rgm~ -- cgit v1.2.1-24-ge1ad From a969d142c20fd3f68274cf03886aab285e06e751 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 15:43:31 -0400 Subject: Modify some link targets --- README.md | 10 +++++----- doc/hdr.html | 4 ++++ document.md | 10 +++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3005d76..e1f1f8e 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ itself can be retrieved with a call to `Error()`. ## Conversion Notes This package is a relatively straightforward translation from the original -[FPDF][fpdf] library written in PHP (despite the caveat in the +[FPDF][fpdf-site] library written in PHP (despite the caveat in the introduction to [Effective Go][effective-go]). The API names have been retained even though the Go idiom would suggest otherwise (for example, `pdf.GetX()` is used rather than simply `pdf.X()`). The @@ -148,7 +148,7 @@ fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. ## Related Packages -The [draw2d][draw2d] package is a two dimensional vector graphics library that +The [draw2d][draw2d-site] package is a two dimensional vector graphics library that can generate output in different forms. It uses gofpdf for its document production mode. @@ -180,7 +180,7 @@ the contributors acknowledged below. ## Acknowledgments -This package's code and documentation are closely derived from the [FPDF][fpdf] +This package's code and documentation are closely derived from the [FPDF][fpdf-site] library created by Olivier Plathey, and a number of font and image resources are copied directly from it. Bruno Michel has provided valuable assistance with the code. Drawing support is adapted from the FPDF geometric figures script by @@ -231,9 +231,9 @@ UTF-8 runes to code page bytes is provided. [badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master) [coverage]: https://blog.golang.org/cover [dfont]: http://dejavu-fonts.org/ -[draw2d]: https://github.com/llgcode/draw2d +[draw2d-site]: https://github.com/llgcode/draw2d [effective-go]: https://golang.org/doc/effective_go.html -[fpdf]: http://www.fpdf.org/ +[fpdf-site]: http://www.fpdf.org/ [fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go [gfont]: https://fonts.google.com/ [github]: https://github.com/jung-kurt/gofpdf diff --git a/doc/hdr.html b/doc/hdr.html index bbc2758..161ec47 100644 --- a/doc/hdr.html +++ b/doc/hdr.html @@ -12,6 +12,10 @@ padding: 1em; } + img { + max-width: 800px; + } + h1, h2, h3 { diff --git a/document.md b/document.md index 030c96b..7a65c60 100644 --- a/document.md +++ b/document.md @@ -93,7 +93,7 @@ itself can be retrieved with a call to `Error()`. ## Conversion Notes This package is a relatively straightforward translation from the original -[FPDF][fpdf] library written in PHP (despite the caveat in the +[FPDF][fpdf-site] library written in PHP (despite the caveat in the introduction to [Effective Go][effective-go]). The API names have been retained even though the Go idiom would suggest otherwise (for example, `pdf.GetX()` is used rather than simply `pdf.X()`). The @@ -159,7 +159,7 @@ fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. ## Related Packages -The [draw2d][draw2d] package is a two dimensional vector graphics library that +The [draw2d][draw2d-site] package is a two dimensional vector graphics library that can generate output in different forms. It uses gofpdf for its document production mode. @@ -191,7 +191,7 @@ the contributors acknowledged below. ## Acknowledgments -This package's code and documentation are closely derived from the [FPDF][fpdf] +This package's code and documentation are closely derived from the [FPDF][fpdf-site] library created by Olivier Plathey, and a number of font and image resources are copied directly from it. Bruno Michel has provided valuable assistance with the code. Drawing support is adapted from the FPDF geometric figures script by @@ -243,9 +243,9 @@ UTF-8 runes to code page bytes is provided. [badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master) [coverage]: https://blog.golang.org/cover [dfont]: http://dejavu-fonts.org/ -[draw2d]: https://github.com/llgcode/draw2d +[draw2d-site]: https://github.com/llgcode/draw2d [effective-go]: https://golang.org/doc/effective_go.html -[fpdf]: http://www.fpdf.org/ +[fpdf-site]: http://www.fpdf.org/ [fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go [gfont]: https://fonts.google.com/ [github]: https://github.com/jung-kurt/gofpdf -- cgit v1.2.1-24-ge1ad From a6cfa1a041277da3b481e1421c4f81542e2127c0 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 15:46:15 -0400 Subject: Correct link for go vet --- document.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/document.md b/document.md index 7a65c60..f3bd9e1 100644 --- a/document.md +++ b/document.md @@ -82,7 +82,7 @@ If an error occurs in an Fpdf method, an internal error field is set. After this occurs, Fpdf method calls typically return without performing any operations and the error state is retained. This error management scheme facilitates PDF generation since individual method calls do not need to be -examined for failure; it is generally sufficient to wait until after Output() +examined for failure; it is generally sufficient to wait until after `Output()` is called. For the same reason, if an error occurs in the calling application during PDF generation, it may be desirable for the application to transfer the error to the Fpdf instance by calling the `SetError()` method or the @@ -240,7 +240,7 @@ UTF-8 runes to code page bytes is provided. [badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg [badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg [badge-report]: https://goreportcard.com/badge/github.com/jung-kurt/gofpdf -[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master) +[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master [coverage]: https://blog.golang.org/cover [dfont]: http://dejavu-fonts.org/ [draw2d-site]: https://github.com/llgcode/draw2d @@ -258,4 +258,4 @@ UTF-8 runes to code page bytes is provided. [report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf [status]: https://travis-ci.org/jung-kurt/gofpdf [test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[vet]: https://godoc.org/golang.org/x/tools/cmd/vet +[vet]: https://golang.org/cmd/vet/ -- cgit v1.2.1-24-ge1ad From 35be79ea9799616538899dddd75f172a3188a44c Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 15:51:28 -0400 Subject: Correct spacing after list --- README.md | 10 +++++++--- document.md | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e1f1f8e..9fe080b 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ If an error occurs in an Fpdf method, an internal error field is set. After this occurs, Fpdf method calls typically return without performing any operations and the error state is retained. This error management scheme facilitates PDF generation since individual method calls do not need to be -examined for failure; it is generally sufficient to wait until after Output() +examined for failure; it is generally sufficient to wait until after `Output()` is called. For the same reason, if an error occurs in the calling application during PDF generation, it may be desirable for the application to transfer the error to the Fpdf instance by calling the `SetError()` method or the @@ -223,12 +223,16 @@ Matusiak added supported for word spacing. UTF-8 runes to code page bytes is provided. * Improve test coverage as reported by the coverage tool. + + + + [badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg [badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg [badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg [badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg [badge-report]: https://goreportcard.com/badge/github.com/jung-kurt/gofpdf -[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master) +[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master [coverage]: https://blog.golang.org/cover [dfont]: http://dejavu-fonts.org/ [draw2d-site]: https://github.com/llgcode/draw2d @@ -246,4 +250,4 @@ UTF-8 runes to code page bytes is provided. [report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf [status]: https://travis-ci.org/jung-kurt/gofpdf [test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[vet]: https://godoc.org/golang.org/x/tools/cmd/vet \ No newline at end of file +[vet]: https://golang.org/cmd/vet/ \ No newline at end of file diff --git a/document.md b/document.md index f3bd9e1..9332687 100644 --- a/document.md +++ b/document.md @@ -235,6 +235,10 @@ UTF-8 runes to code page bytes is provided. * Improve test coverage as reported by the coverage tool. ~mr~ + + + + [badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg [badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg [badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg -- cgit v1.2.1-24-ge1ad From 8b09ffb30d9a8716107d250631b3c580aa54ba04 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 30 Apr 2019 15:56:57 -0400 Subject: Reinstate badges --- README.md | 7 ++++--- doc.go | 1 + document.md | 7 ++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9fe080b..070da17 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # GoFPDF document generator +[![MIT licensed][badge-mit]][license] +[![Report][badge-report]][report] +[![GoDoc][badge-doc]][godoc] + ![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") Package gofpdf implements a PDF document generator with high level support for @@ -224,9 +228,6 @@ UTF-8 runes to code page bytes is provided. * Improve test coverage as reported by the coverage tool. - - - [badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg [badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg [badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg diff --git a/doc.go b/doc.go index 78afc23..bc71008 100644 --- a/doc.go +++ b/doc.go @@ -234,5 +234,6 @@ UTF-8 runes to code page bytes is provided. • Improve test coverage as reported by the coverage tool. + */ package gofpdf diff --git a/document.md b/document.md index 9332687..d0f79cb 100644 --- a/document.md +++ b/document.md @@ -4,7 +4,7 @@ ~m~ [![Git Hub repository][badge-github]][github] [![Kurt Jung][badge-author]][jung] -~m~ +~rm~ [![MIT licensed][badge-mit]][license] [![Report][badge-report]][report] [![GoDoc][badge-doc]][godoc] @@ -234,11 +234,8 @@ Matusiak added supported for word spacing. UTF-8 runes to code page bytes is provided. * Improve test coverage as reported by the coverage tool. -~mr~ - - - +~mr~ [badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg [badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg [badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg -- cgit v1.2.1-24-ge1ad From 50996f28baf0361e2171a1f0cebdcc7106fef2ac Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 4 May 2019 19:42:18 -0400 Subject: Use Pandoc to generate README and doc.go --- Makefile | 29 +++-- README.md | 366 ++++++++++++++++++++++++++++---------------------------- doc.go | 333 +++++++++++++++++++++++++++------------------------ doc/doc.lua | 100 ---------------- doc/document.md | 254 +++++++++++++++++++++++++++++++++++++++ doc/ftr.html | 3 - doc/go.awk | 19 +++ doc/hdr.html | 59 --------- doc/html.txt | 68 +++++++++++ document.md | 262 ---------------------------------------- 10 files changed, 712 insertions(+), 781 deletions(-) delete mode 100644 doc/doc.lua create mode 100644 doc/document.md delete mode 100644 doc/ftr.html create mode 100644 doc/go.awk delete mode 100644 doc/hdr.html create mode 100644 doc/html.txt delete mode 100644 document.md diff --git a/Makefile b/Makefile index 887ffd8..b0a5e06 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,8 @@ -doc : README.md doc.go doc/index.html.ok +all : documentation -test : - go test -v +documentation : doc/index.html doc.go README.md -cov : +cov : all go test -v -coverprofile=coverage && go tool cover -html=coverage -o=coverage.html check : @@ -11,19 +10,19 @@ check : go vet -all . gofmt -s -l . -%.html.ok : %.html - tidy -quiet -output /dev/null $< - touch $@ +README.md : doc/document.md + pandoc --read=markdown --write=gfm < $< > $@ -doc/body.md README.md doc.go : document.md - lua doc/doc.lua - gofmt -s -w doc.go +doc/index.html : doc/document.md doc/html.txt + pandoc --read=markdown --write=html --template=doc/html.txt \ + --metadata pagetitle="GoFPDF Document Generator" < $< > $@ -doc/index.html : doc/hdr.html doc/body.html doc/ftr.html - cat doc/hdr.html doc/body.html doc/ftr.html > $@ +doc.go : doc/document.md doc/go.awk + pandoc --read=markdown --write=plain $< | awk -f doc/go.awk > $@ + gofmt -s -w $@ -doc/body.html : doc/body.md - markdown -f +links,+image,+smarty,+ext,+divquote -o $@ $< +build : + go build -v clean : - rm -f coverage.html coverage doc/*.ok doc/body.md README.md doc.go doc/index.html doc/body.html + rm -f coverage.html coverage doc/index.html doc.go README.md diff --git a/README.md b/README.md index 070da17..82f5bd5 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,57 @@ # GoFPDF document generator -[![MIT licensed][badge-mit]][license] -[![Report][badge-report]][report] -[![GoDoc][badge-doc]][godoc] +[![MIT +licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE) +[![Report](https://goreportcard.com/badge/github.com/jung-kurt/gofpdf)](https://goreportcard.com/report/github.com/jung-kurt/gofpdf) +[![GoDoc](https://img.shields.io/badge/godoc-GoFPDF-blue.svg)](https://godoc.org/github.com/jung-kurt/gofpdf) -![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") +![](https://github.com/jung-kurt/gofpdf/raw/master/image/logo_gofpdf.jpg?raw=true) -Package gofpdf implements a PDF document generator with high level support for -text, drawing and images. +Package gofpdf implements a PDF document generator with high level +support for text, drawing and images. ## Features -* Choice of measurement unit, page format and margins -* Page header and footer management -* Automatic page breaks, line breaks, and text justification -* Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images -* Colors, gradients and alpha channel transparency -* Outline bookmarks -* Internal and external links -* TrueType, Type1 and encoding support -* Page compression -* Lines, Bézier curves, arcs, and ellipses -* Rotation, scaling, skewing, translation, and mirroring -* Clipping -* Document protection -* Layers -* Templates -* Barcodes -* Charting facility - -gofpdf has no dependencies other than the Go standard library. All tests pass -on Linux, Mac and Windows platforms. - -Like FPDF version 1.7, from which gofpdf is derived, this package does not yet -support UTF-8 fonts. In particular, languages that require more than one code -page such as Chinese, Japanese, and Arabic are not currently supported. This is -explained in [issue 109][issue109]. However, support is provided to -automatically translate UTF-8 runes to code page encodings for languages that -have fewer than 256 glyphs. + - Choice of measurement unit, page format and margins + - Page header and footer management + - Automatic page breaks, line breaks, and text justification + - Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images + - Colors, gradients and alpha channel transparency + - Outline bookmarks + - Internal and external links + - TrueType, Type1 and encoding support + - Page compression + - Lines, Bézier curves, arcs, and ellipses + - Rotation, scaling, skewing, translation, and mirroring + - Clipping + - Document protection + - Layers + - Templates + - Barcodes + - Charting facility + +gofpdf has no dependencies other than the Go standard library. All tests +pass on Linux, Mac and Windows platforms. + +Like FPDF version 1.7, from which gofpdf is derived, this package does +not yet support UTF-8 fonts. In particular, languages that require more +than one code page such as Chinese, Japanese, and Arabic are not +currently supported. This is explained in +[issue 109](https://github.com/jung-kurt/gofpdf/issues/109). However, +support is provided to automatically translate UTF-8 runes to code page +encodings for languages that have fewer than 256 glyphs. ## Installation To install the package on your system, run -```shell +``` shell go get github.com/jung-kurt/gofpdf ``` Later, to receive updates, run -```shell +``` shell go get -u -v github.com/jung-kurt/gofpdf/... ``` @@ -57,7 +59,7 @@ go get -u -v github.com/jung-kurt/gofpdf/... The following Go code generates a simple PDF file. -```go +``` go pdf := gofpdf.New("P", "mm", "A4", "") pdf.AddPage() pdf.SetFont("Arial", "B", 16) @@ -66,189 +68,181 @@ err := pdf.OutputFileAndClose("hello.pdf") ``` See the functions in the -[fpdf_test.go][fpdf-test] -file (shown as examples in this documentation) for more advanced PDF examples. +[fpdf\_test.go](https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go) +file (shown as examples in this documentation) for more advanced PDF +examples. ## Errors -If an error occurs in an Fpdf method, an internal error field is set. After -this occurs, Fpdf method calls typically return without performing any -operations and the error state is retained. This error management scheme -facilitates PDF generation since individual method calls do not need to be -examined for failure; it is generally sufficient to wait until after `Output()` -is called. For the same reason, if an error occurs in the calling application -during PDF generation, it may be desirable for the application to transfer the -error to the Fpdf instance by calling the `SetError()` method or the -`SetErrorf()` method. At any time during the life cycle of the Fpdf instance, -the error state can be determined with a call to `Ok()` or `Err()`. The error -itself can be retrieved with a call to `Error()`. +If an error occurs in an Fpdf method, an internal error field is set. +After this occurs, Fpdf method calls typically return without performing +any operations and the error state is retained. This error management +scheme facilitates PDF generation since individual method calls do not +need to be examined for failure; it is generally sufficient to wait +until after `Output()` is called. For the same reason, if an error +occurs in the calling application during PDF generation, it may be +desirable for the application to transfer the error to the Fpdf instance +by calling the `SetError()` method or the `SetErrorf()` method. At any +time during the life cycle of the Fpdf instance, the error state can be +determined with a call to `Ok()` or `Err()`. The error itself can be +retrieved with a call to `Error()`. ## Conversion Notes -This package is a relatively straightforward translation from the original -[FPDF][fpdf-site] library written in PHP (despite the caveat in the -introduction to [Effective Go][effective-go]). The -API names have been retained even though the Go idiom would suggest otherwise -(for example, `pdf.GetX()` is used rather than simply `pdf.X()`). The -similarity of the two libraries makes the original FPDF website a good source -of information. It includes a forum and FAQ. - -However, some internal changes have been made. Page content is built up using -buffers (of type bytes.Buffer) rather than repeated string concatenation. -Errors are handled as explained above rather than panicking. Output is -generated through an interface of type io.Writer or io.WriteCloser. A number of -the original PHP methods behave differently based on the type of the arguments -that are passed to them; in these cases additional methods have been exported -to provide similar functionality. Font definition files are produced in JSON -rather than PHP. +This package is a relatively straightforward translation from the +original [FPDF](http://www.fpdf.org/) library written in PHP (despite +the caveat in the introduction to [Effective +Go](https://golang.org/doc/effective_go.html)). The API names have been +retained even though the Go idiom would suggest otherwise (for example, +`pdf.GetX()` is used rather than simply `pdf.X()`). The similarity of +the two libraries makes the original FPDF website a good source of +information. It includes a forum and FAQ. + +However, some internal changes have been made. Page content is built up +using buffers (of type bytes.Buffer) rather than repeated string +concatenation. Errors are handled as explained above rather than +panicking. Output is generated through an interface of type io.Writer or +io.WriteCloser. A number of the original PHP methods behave differently +based on the type of the arguments that are passed to them; in these +cases additional methods have been exported to provide similar +functionality. Font definition files are produced in JSON rather than +PHP. ## Example PDFs -A side effect of running `go test ./...` is the production of a number of -example PDFs. These can be found in the gofpdf/pdf directory after the tests -complete. - -Please note that these examples run in the context of a test. In order run an -example as a standalone application, you'll need to examine -[fpdf_test.go][fpdf-test] for some helper routines, for example -`exampleFilename()` and `summary()`. - -Example PDFs can be compared with reference copies in order to verify that they -have been generated as expected. This comparison will be performed if a PDF -with the same name as the example PDF is placed in the gofpdf/pdf/reference -directory and if the third argument to `ComparePDFFiles()` in -internal/example/example.go is true. (By default it is false.) The routine that -summarizes an example will look for this file and, if found, will call -`ComparePDFFiles()` to check the example PDF for equality with its reference PDF. -If differences exist between the two files they will be printed to standard -output and the test will fail. If the reference file is missing, the comparison -is considered to succeed. In order to successfully compare two PDFs, the -placement of internal resources must be consistent and the internal creation -timestamps must be the same. To do this, the methods `SetCatalogSort()` and -`SetCreationDate()` need to be called for both files. This is done automatically -for all examples. +A side effect of running `go test ./...` is the production of a number +of example PDFs. These can be found in the gofpdf/pdf directory after +the tests complete. + +Please note that these examples run in the context of a test. In order +run an example as a standalone application, you’ll need to examine +[fpdf\_test.go](https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go) +for some helper routines, for example `exampleFilename()` and +`summary()`. + +Example PDFs can be compared with reference copies in order to verify +that they have been generated as expected. This comparison will be +performed if a PDF with the same name as the example PDF is placed in +the gofpdf/pdf/reference directory and if the third argument to +`ComparePDFFiles()` in internal/example/example.go is true. (By default +it is false.) The routine that summarizes an example will look for this +file and, if found, will call `ComparePDFFiles()` to check the example +PDF for equality with its reference PDF. If differences exist between +the two files they will be printed to standard output and the test will +fail. If the reference file is missing, the comparison is considered to +succeed. In order to successfully compare two PDFs, the placement of +internal resources must be consistent and the internal creation +timestamps must be the same. To do this, the methods `SetCatalogSort()` +and `SetCreationDate()` need to be called for both files. This is done +automatically for all examples. ## Nonstandard Fonts -Nothing special is required to use the standard PDF fonts (courier, helvetica, -times, zapfdingbats) in your documents other than calling `SetFont()`. +Nothing special is required to use the standard PDF fonts (courier, +helvetica, times, zapfdingbats) in your documents other than calling +`SetFont()`. -In order to use a different TrueType or Type1 font, you will need to generate a -font definition file and, if the font will be embedded into PDFs, a compressed -version of the font file. This is done by calling the `MakeFont()` function or -using the included makefont command line utility. To create the utility, cd -into the makefont subdirectory and run `go build`. This will produce a -standalone executable named makefont. Select the appropriate encoding file from -the font subdirectory and run the command as in the following example. +In order to use a different TrueType or Type1 font, you will need to +generate a font definition file and, if the font will be embedded into +PDFs, a compressed version of the font file. This is done by calling the +`MakeFont()` function or using the included makefont command line +utility. To create the utility, cd into the makefont subdirectory and +run `go build`. This will produce a standalone executable named +makefont. Select the appropriate encoding file from the font +subdirectory and run the command as in the following example. -```shell +``` shell ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf ``` -In your PDF generation code, call AddFont() to load the font and, as with the -standard fonts, SetFont() to begin using it. Most examples, including the -package example, demonstrate this method. Good sources of free, open-source -fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. +In your PDF generation code, call AddFont() to load the font and, as +with the standard fonts, SetFont() to begin using it. Most examples, +including the package example, demonstrate this method. Good sources of +free, open-source fonts include [Google +Fonts](https://fonts.google.com/) and [DejaVu +Fonts](http://dejavu-fonts.org/). ## Related Packages -The [draw2d][draw2d-site] package is a two dimensional vector graphics library that -can generate output in different forms. It uses gofpdf for its document -production mode. +The [draw2d](https://github.com/llgcode/draw2d) package is a two +dimensional vector graphics library that can generate output in +different forms. It uses gofpdf for its document production mode. ## Contributing Changes -gofpdf is a global community effort and you are invited to make it even better. -If you have implemented a new feature or corrected a problem, please consider -contributing your change to the project. A contribution that does not directly -pertain to the core functionality of gofpdf should be placed in its own -directory directly beneath the `contrib` directory. +gofpdf is a global community effort and you are invited to make it even +better. If you have implemented a new feature or corrected a problem, +please consider contributing your change to the project. A contribution +that does not directly pertain to the core functionality of gofpdf +should be placed in its own directory directly beneath the `contrib` +directory. Here are guidelines for making submissions. Your change should -* be compatible with the MIT License -* be properly documented -* be formatted with `go fmt` -* include an example in [fpdf_test.go][test] if appropriate -* conform to the standards of [golint][lint] and -[go vet][vet], that is, `golint .` and -`go vet .` should not generate any warnings -* not diminish [test coverage][coverage] + - be compatible with the MIT License + - be properly documented + - be formatted with `go fmt` + - include an example in + [fpdf\_test.go](https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go) + if appropriate + - conform to the standards of [golint](https://github.com/golang/lint) + and [go vet](https://golang.org/cmd/vet/), that is, `golint .` and + `go vet .` should not generate any warnings + - not diminish [test coverage](https://blog.golang.org/cover) -[Pull requests][pr] are the preferred means of accepting your changes. +[Pull requests](https://help.github.com/articles/using-pull-requests/) +are the preferred means of accepting your changes. ## License -gofpdf is released under the MIT License. It is copyrighted by Kurt Jung and -the contributors acknowledged below. +gofpdf is released under the MIT License. It is copyrighted by Kurt Jung +and the contributors acknowledged below. ## Acknowledgments -This package's code and documentation are closely derived from the [FPDF][fpdf-site] -library created by Olivier Plathey, and a number of font and image resources -are copied directly from it. Bruno Michel has provided valuable assistance with -the code. Drawing support is adapted from the FPDF geometric figures script by -David Hernández Sanz. Transparency support is adapted from the FPDF -transparency script by Martin Hall-May. Support for gradients and clipping is -adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is -adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from -Olivier Plathey. Support for transformations is adapted from the FPDF -transformation script by Moritz Wagner and Andreas Würmser. PDF protection is -adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence -Kesteloot provided code to allow an image's extent to be determined prior to -placement. Support for vertical alignment within a cell was provided by Stefan -Schroeder. Ivan Daniluk generalized the font and image loading code to use the -Reader interface while maintaining backward compatibility. Anthony Starks -provided code for the Polygon function. Robert Lillack provided the Beziergon -function and corrected some naming issues with the internal curve function. -Claudio Felber provided implementations for dashed line drawing and generalized -font loading. Stani Michiels provided support for multi-segment path drawing -with smooth line joins, line join styles, enhanced fill modes, and has helped -greatly with package presentation and tests. Templating is adapted by Marcus -Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer -Snoeck contributed packages that generate a variety of barcodes and help with -registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the -basic HTML functionality with aligned text. Kent Quirk implemented -backwards-compatible support for reading DPI from images that support it, and -for setting DPI manually and then having it properly taken into account when -calculating image size. Paulo Coutinho provided support for static embedded -fonts. Dan Meyers added support for embedded JavaScript. David Fish added a -generic alias-replacement function to enable, among other things, table of -contents functionality. Andy Bakun identified and corrected a problem in which -the internal catalogs were not sorted stably. Paul Montag added encoding and -decoding functionality for templates, including images that are embedded in -templates; this allows templates to be stored independently of gofpdf. Paul -also added support for page boxes used in printing PDF documents. Wojciech -Matusiak added supported for word spacing. +This package’s code and documentation are closely derived from the +[FPDF](http://www.fpdf.org/) library created by Olivier Plathey, and a +number of font and image resources are copied directly from it. Bruno +Michel has provided valuable assistance with the code. Drawing support +is adapted from the FPDF geometric figures script by David Hernández +Sanz. Transparency support is adapted from the FPDF transparency script +by Martin Hall-May. Support for gradients and clipping is adapted from +FPDF scripts by Andreas Würmser. Support for outline bookmarks is +adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted +from Olivier Plathey. Support for transformations is adapted from the +FPDF transformation script by Moritz Wagner and Andreas Würmser. PDF +protection is adapted from the work of Klemen Vodopivec for the FPDF +product. Lawrence Kesteloot provided code to allow an image’s extent to +be determined prior to placement. Support for vertical alignment within +a cell was provided by Stefan Schroeder. Ivan Daniluk generalized the +font and image loading code to use the Reader interface while +maintaining backward compatibility. Anthony Starks provided code for the +Polygon function. Robert Lillack provided the Beziergon function and +corrected some naming issues with the internal curve function. Claudio +Felber provided implementations for dashed line drawing and generalized +font loading. Stani Michiels provided support for multi-segment path +drawing with smooth line joins, line join styles, enhanced fill modes, +and has helped greatly with package presentation and tests. Templating +is adapted by Marcus Downing from the FPDF\_Tpl library created by Jan +Slabon and Setasign. Jelmer Snoeck contributed packages that generate a +variety of barcodes and help with registering images on the web. Jelmer +Snoek and Guillermo Pascual augmented the basic HTML functionality with +aligned text. Kent Quirk implemented backwards-compatible support for +reading DPI from images that support it, and for setting DPI manually +and then having it properly taken into account when calculating image +size. Paulo Coutinho provided support for static embedded fonts. Dan +Meyers added support for embedded JavaScript. David Fish added a generic +alias-replacement function to enable, among other things, table of +contents functionality. Andy Bakun identified and corrected a problem in +which the internal catalogs were not sorted stably. Paul Montag added +encoding and decoding functionality for templates, including images that +are embedded in templates; this allows templates to be stored +independently of gofpdf. Paul also added support for page boxes used in +printing PDF documents. Wojciech Matusiak added supported for word +spacing. ## Roadmap -* Handle UTF-8 source text natively. Until then, automatic translation of -UTF-8 runes to code page bytes is provided. -* Improve test coverage as reported by the coverage tool. - - -[badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg -[badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg -[badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg -[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg -[badge-report]: https://goreportcard.com/badge/github.com/jung-kurt/gofpdf -[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master -[coverage]: https://blog.golang.org/cover -[dfont]: http://dejavu-fonts.org/ -[draw2d-site]: https://github.com/llgcode/draw2d -[effective-go]: https://golang.org/doc/effective_go.html -[fpdf-site]: http://www.fpdf.org/ -[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[gfont]: https://fonts.google.com/ -[github]: https://github.com/jung-kurt/gofpdf -[godoc]: https://godoc.org/github.com/jung-kurt/gofpdf -[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 -[jung]: https://github.com/jung-kurt/ -[license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE -[lint]: https://github.com/golang/lint -[pr]: https://help.github.com/articles/using-pull-requests/ -[report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf -[status]: https://travis-ci.org/jung-kurt/gofpdf -[test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[vet]: https://golang.org/cmd/vet/ \ No newline at end of file + - Handle UTF-8 source text natively. Until then, automatic translation + of UTF-8 runes to code page bytes is provided. + - Improve test coverage as reported by the coverage tool. diff --git a/doc.go b/doc.go index bc71008..17a9bc1 100644 --- a/doc.go +++ b/doc.go @@ -1,239 +1,260 @@ /* -Package gofpdf implements a PDF document generator with high level support for -text, drawing and images. +Package gofpdf implements a PDF document generator with high level +support for text, drawing and images. + Features -• Choice of measurement unit, page format and margins -• Page header and footer management +- Choice of measurement unit, page format and margins + +- Page header and footer management -• Automatic page breaks, line breaks, and text justification +- Automatic page breaks, line breaks, and text justification -• Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images +- Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images -• Colors, gradients and alpha channel transparency +- Colors, gradients and alpha channel transparency -• Outline bookmarks +- Outline bookmarks -• Internal and external links +- Internal and external links -• TrueType, Type1 and encoding support +- TrueType, Type1 and encoding support -• Page compression +- Page compression -• Lines, Bézier curves, arcs, and ellipses +- Lines, Bézier curves, arcs, and ellipses -• Rotation, scaling, skewing, translation, and mirroring +- Rotation, scaling, skewing, translation, and mirroring -• Clipping +- Clipping -• Document protection +- Document protection -• Layers +- Layers -• Templates +- Templates -• Barcodes +- Barcodes -• Charting facility +- Charting facility -gofpdf has no dependencies other than the Go standard library. All tests pass -on Linux, Mac and Windows platforms. +gofpdf has no dependencies other than the Go standard library. All tests +pass on Linux, Mac and Windows platforms. + +Like FPDF version 1.7, from which gofpdf is derived, this package does +not yet support UTF-8 fonts. In particular, languages that require more +than one code page such as Chinese, Japanese, and Arabic are not +currently supported. This is explained in issue 109. However, support is +provided to automatically translate UTF-8 runes to code page encodings +for languages that have fewer than 256 glyphs. -Like FPDF version 1.7, from which gofpdf is derived, this package does not yet -support UTF-8 fonts. In particular, languages that require more than one code -page such as Chinese, Japanese, and Arabic are not currently supported. This is -explained in issue 109. However, support is provided to -automatically translate UTF-8 runes to code page encodings for languages that -have fewer than 256 glyphs. Installation To install the package on your system, run - go get github.com/jung-kurt/gofpdf + go get github.com/jung-kurt/gofpdf Later, to receive updates, run - go get -u -v github.com/jung-kurt/gofpdf/... + go get -u -v github.com/jung-kurt/gofpdf/... + Quick Start The following Go code generates a simple PDF file. - pdf := gofpdf.New("P", "mm", "A4", "") - pdf.AddPage() - pdf.SetFont("Arial", "B", 16) - pdf.Cell(40, 10, "Hello, world") - err := pdf.OutputFileAndClose("hello.pdf") + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "B", 16) + pdf.Cell(40, 10, "Hello, world") + err := pdf.OutputFileAndClose("hello.pdf") + +See the functions in the fpdf_test.go file (shown as examples in this +documentation) for more advanced PDF examples. -See the functions in the -fpdf_test.go -file (shown as examples in this documentation) for more advanced PDF examples. Errors -If an error occurs in an Fpdf method, an internal error field is set. After -this occurs, Fpdf method calls typically return without performing any -operations and the error state is retained. This error management scheme -facilitates PDF generation since individual method calls do not need to be -examined for failure; it is generally sufficient to wait until after Output() -is called. For the same reason, if an error occurs in the calling application -during PDF generation, it may be desirable for the application to transfer the -error to the Fpdf instance by calling the SetError() method or the -SetErrorf() method. At any time during the life cycle of the Fpdf instance, -the error state can be determined with a call to Ok() or Err(). The error -itself can be retrieved with a call to Error(). +If an error occurs in an Fpdf method, an internal error field is set. +After this occurs, Fpdf method calls typically return without performing +any operations and the error state is retained. This error management +scheme facilitates PDF generation since individual method calls do not +need to be examined for failure; it is generally sufficient to wait +until after Output() is called. For the same reason, if an error occurs +in the calling application during PDF generation, it may be desirable +for the application to transfer the error to the Fpdf instance by +calling the SetError() method or the SetErrorf() method. At any time +during the life cycle of the Fpdf instance, the error state can be +determined with a call to Ok() or Err(). The error itself can be +retrieved with a call to Error(). + Conversion Notes -This package is a relatively straightforward translation from the original -FPDF library written in PHP (despite the caveat in the -introduction to Effective Go). The -API names have been retained even though the Go idiom would suggest otherwise -(for example, pdf.GetX() is used rather than simply pdf.X()). The -similarity of the two libraries makes the original FPDF website a good source -of information. It includes a forum and FAQ. - -However, some internal changes have been made. Page content is built up using -buffers (of type bytes.Buffer) rather than repeated string concatenation. -Errors are handled as explained above rather than panicking. Output is -generated through an interface of type io.Writer or io.WriteCloser. A number of -the original PHP methods behave differently based on the type of the arguments -that are passed to them; in these cases additional methods have been exported -to provide similar functionality. Font definition files are produced in JSON -rather than PHP. +This package is a relatively straightforward translation from the +original FPDF library written in PHP (despite the caveat in the +introduction to Effective Go). The API names have been retained even +though the Go idiom would suggest otherwise (for example, pdf.GetX() is +used rather than simply pdf.X()). The similarity of the two libraries +makes the original FPDF website a good source of information. It +includes a forum and FAQ. + +However, some internal changes have been made. Page content is built up +using buffers (of type bytes.Buffer) rather than repeated string +concatenation. Errors are handled as explained above rather than +panicking. Output is generated through an interface of type io.Writer or +io.WriteCloser. A number of the original PHP methods behave differently +based on the type of the arguments that are passed to them; in these +cases additional methods have been exported to provide similar +functionality. Font definition files are produced in JSON rather than +PHP. + Example PDFs A side effect of running go test ./... is the production of a number of -example PDFs. These can be found in the gofpdf/pdf directory after the tests -complete. - -Please note that these examples run in the context of a test. In order run an -example as a standalone application, you'll need to examine -fpdf_test.go for some helper routines, for example -exampleFilename() and summary(). - -Example PDFs can be compared with reference copies in order to verify that they -have been generated as expected. This comparison will be performed if a PDF -with the same name as the example PDF is placed in the gofpdf/pdf/reference -directory and if the third argument to ComparePDFFiles() in -internal/example/example.go is true. (By default it is false.) The routine that -summarizes an example will look for this file and, if found, will call -ComparePDFFiles() to check the example PDF for equality with its reference PDF. -If differences exist between the two files they will be printed to standard -output and the test will fail. If the reference file is missing, the comparison -is considered to succeed. In order to successfully compare two PDFs, the -placement of internal resources must be consistent and the internal creation -timestamps must be the same. To do this, the methods SetCatalogSort() and -SetCreationDate() need to be called for both files. This is done automatically -for all examples. +example PDFs. These can be found in the gofpdf/pdf directory after the +tests complete. + +Please note that these examples run in the context of a test. In order +run an example as a standalone application, you’ll need to examine +fpdf_test.go for some helper routines, for example exampleFilename() and +summary(). + +Example PDFs can be compared with reference copies in order to verify +that they have been generated as expected. This comparison will be +performed if a PDF with the same name as the example PDF is placed in +the gofpdf/pdf/reference directory and if the third argument to +ComparePDFFiles() in internal/example/example.go is true. (By default it +is false.) The routine that summarizes an example will look for this +file and, if found, will call ComparePDFFiles() to check the example PDF +for equality with its reference PDF. If differences exist between the +two files they will be printed to standard output and the test will +fail. If the reference file is missing, the comparison is considered to +succeed. In order to successfully compare two PDFs, the placement of +internal resources must be consistent and the internal creation +timestamps must be the same. To do this, the methods SetCatalogSort() +and SetCreationDate() need to be called for both files. This is done +automatically for all examples. + Nonstandard Fonts -Nothing special is required to use the standard PDF fonts (courier, helvetica, -times, zapfdingbats) in your documents other than calling SetFont(). +Nothing special is required to use the standard PDF fonts (courier, +helvetica, times, zapfdingbats) in your documents other than calling +SetFont(). -In order to use a different TrueType or Type1 font, you will need to generate a -font definition file and, if the font will be embedded into PDFs, a compressed -version of the font file. This is done by calling the MakeFont() function or -using the included makefont command line utility. To create the utility, cd -into the makefont subdirectory and run go build. This will produce a -standalone executable named makefont. Select the appropriate encoding file from -the font subdirectory and run the command as in the following example. +In order to use a different TrueType or Type1 font, you will need to +generate a font definition file and, if the font will be embedded into +PDFs, a compressed version of the font file. This is done by calling the +MakeFont() function or using the included makefont command line utility. +To create the utility, cd into the makefont subdirectory and run +go build. This will produce a standalone executable named makefont. +Select the appropriate encoding file from the font subdirectory and run +the command as in the following example. - ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf + ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf + +In your PDF generation code, call AddFont() to load the font and, as +with the standard fonts, SetFont() to begin using it. Most examples, +including the package example, demonstrate this method. Good sources of +free, open-source fonts include Google Fonts and DejaVu Fonts. -In your PDF generation code, call AddFont() to load the font and, as with the -standard fonts, SetFont() to begin using it. Most examples, including the -package example, demonstrate this method. Good sources of free, open-source -fonts include Google Fonts and DejaVu Fonts. Related Packages -The draw2d package is a two dimensional vector graphics library that -can generate output in different forms. It uses gofpdf for its document +The draw2d package is a two dimensional vector graphics library that can +generate output in different forms. It uses gofpdf for its document production mode. + Contributing Changes -gofpdf is a global community effort and you are invited to make it even better. -If you have implemented a new feature or corrected a problem, please consider -contributing your change to the project. A contribution that does not directly -pertain to the core functionality of gofpdf should be placed in its own -directory directly beneath the contrib directory. +gofpdf is a global community effort and you are invited to make it even +better. If you have implemented a new feature or corrected a problem, +please consider contributing your change to the project. A contribution +that does not directly pertain to the core functionality of gofpdf +should be placed in its own directory directly beneath the contrib +directory. Here are guidelines for making submissions. Your change should -• be compatible with the MIT License -• be properly documented +- be compatible with the MIT License -• be formatted with go fmt +- be properly documented -• include an example in fpdf_test.go if appropriate +- be formatted with go fmt -• conform to the standards of golint and -go vet, that is, golint . and +- include an example in fpdf_test.go if appropriate + +- conform to the standards of golint and go vet, that is, golint . and go vet . should not generate any warnings -• not diminish test coverage +- not diminish test coverage Pull requests are the preferred means of accepting your changes. + License -gofpdf is released under the MIT License. It is copyrighted by Kurt Jung and -the contributors acknowledged below. +gofpdf is released under the MIT License. It is copyrighted by Kurt Jung +and the contributors acknowledged below. + Acknowledgments -This package's code and documentation are closely derived from the FPDF -library created by Olivier Plathey, and a number of font and image resources -are copied directly from it. Bruno Michel has provided valuable assistance with -the code. Drawing support is adapted from the FPDF geometric figures script by -David Hernández Sanz. Transparency support is adapted from the FPDF -transparency script by Martin Hall-May. Support for gradients and clipping is -adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is -adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from -Olivier Plathey. Support for transformations is adapted from the FPDF -transformation script by Moritz Wagner and Andreas Würmser. PDF protection is -adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence -Kesteloot provided code to allow an image's extent to be determined prior to -placement. Support for vertical alignment within a cell was provided by Stefan -Schroeder. Ivan Daniluk generalized the font and image loading code to use the -Reader interface while maintaining backward compatibility. Anthony Starks -provided code for the Polygon function. Robert Lillack provided the Beziergon -function and corrected some naming issues with the internal curve function. -Claudio Felber provided implementations for dashed line drawing and generalized -font loading. Stani Michiels provided support for multi-segment path drawing -with smooth line joins, line join styles, enhanced fill modes, and has helped -greatly with package presentation and tests. Templating is adapted by Marcus -Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer -Snoeck contributed packages that generate a variety of barcodes and help with -registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the -basic HTML functionality with aligned text. Kent Quirk implemented -backwards-compatible support for reading DPI from images that support it, and -for setting DPI manually and then having it properly taken into account when -calculating image size. Paulo Coutinho provided support for static embedded -fonts. Dan Meyers added support for embedded JavaScript. David Fish added a -generic alias-replacement function to enable, among other things, table of -contents functionality. Andy Bakun identified and corrected a problem in which -the internal catalogs were not sorted stably. Paul Montag added encoding and -decoding functionality for templates, including images that are embedded in -templates; this allows templates to be stored independently of gofpdf. Paul -also added support for page boxes used in printing PDF documents. Wojciech -Matusiak added supported for word spacing. +This package’s code and documentation are closely derived from the FPDF +library created by Olivier Plathey, and a number of font and image +resources are copied directly from it. Bruno Michel has provided +valuable assistance with the code. Drawing support is adapted from the +FPDF geometric figures script by David Hernández Sanz. Transparency +support is adapted from the FPDF transparency script by Martin Hall-May. +Support for gradients and clipping is adapted from FPDF scripts by +Andreas Würmser. Support for outline bookmarks is adapted from Olivier +Plathey by Manuel Cornes. Layer support is adapted from Olivier Plathey. +Support for transformations is adapted from the FPDF transformation +script by Moritz Wagner and Andreas Würmser. PDF protection is adapted +from the work of Klemen Vodopivec for the FPDF product. Lawrence +Kesteloot provided code to allow an image’s extent to be determined +prior to placement. Support for vertical alignment within a cell was +provided by Stefan Schroeder. Ivan Daniluk generalized the font and +image loading code to use the Reader interface while maintaining +backward compatibility. Anthony Starks provided code for the Polygon +function. Robert Lillack provided the Beziergon function and corrected +some naming issues with the internal curve function. Claudio Felber +provided implementations for dashed line drawing and generalized font +loading. Stani Michiels provided support for multi-segment path drawing +with smooth line joins, line join styles, enhanced fill modes, and has +helped greatly with package presentation and tests. Templating is +adapted by Marcus Downing from the FPDF_Tpl library created by Jan +Slabon and Setasign. Jelmer Snoeck contributed packages that generate a +variety of barcodes and help with registering images on the web. Jelmer +Snoek and Guillermo Pascual augmented the basic HTML functionality with +aligned text. Kent Quirk implemented backwards-compatible support for +reading DPI from images that support it, and for setting DPI manually +and then having it properly taken into account when calculating image +size. Paulo Coutinho provided support for static embedded fonts. Dan +Meyers added support for embedded JavaScript. David Fish added a generic +alias-replacement function to enable, among other things, table of +contents functionality. Andy Bakun identified and corrected a problem in +which the internal catalogs were not sorted stably. Paul Montag added +encoding and decoding functionality for templates, including images that +are embedded in templates; this allows templates to be stored +independently of gofpdf. Paul also added support for page boxes used in +printing PDF documents. Wojciech Matusiak added supported for word +spacing. -Roadmap -• Handle UTF-8 source text natively. Until then, automatic translation of -UTF-8 runes to code page bytes is provided. +Roadmap -• Improve test coverage as reported by the coverage tool. +- Handle UTF-8 source text natively. Until then, automatic translation +of UTF-8 runes to code page bytes is provided. +- Improve test coverage as reported by the coverage tool. */ package gofpdf diff --git a/doc/doc.lua b/doc/doc.lua deleted file mode 100644 index dbe87c1..0000000 --- a/doc/doc.lua +++ /dev/null @@ -1,100 +0,0 @@ --- This script reads a single page of Markdown-like documentation and generates --- output in three different forms: gofmt, git-flavored markdown, and --- standard markdown. - -local gsub, match, len, find, concat, insert = -string.gsub, string.match, string.len, string.find, table.concat, table.insert - -local function write(filestr, str) - local f = io.open(filestr, 'w+') - if f then - f:write(str) - f:close() - end -end - -local function codeblock(tbl, mode) - local newtbl = {} - local incode = false - local pos1, pos2, prefix, syntax - for j, str in ipairs(tbl) do - prefix, syntax = match(str, '^(```)(%a*)') - if prefix and len(syntax) > 0 then - incode = true - if mode == 'r' then - insert(newtbl, str) - end - elseif prefix then - incode = false - if mode == 'r' then - insert(newtbl, str) - end - else - if incode and mode ~= 'r' then - str = '\t' .. str - end - insert(newtbl, str) - end - end - return newtbl -end - -local function markdownwrite(tbl, filestr) - tbl = codeblock(tbl, 'm') - local str = concat(tbl, '\n') - write(filestr, str) -end - -local function readmewrite(tbl, filestr) - tbl = codeblock(tbl, 'r') - local str = concat(tbl, '\n') - str = gsub(str, '\n%> ', '\n') - -- str = gsub(str, '%b<>', '') - write(filestr, str) -end - -local function godocwrite(tbl, filestr) - tbl = codeblock(tbl, 'g') - for j, str in ipairs(tbl) do - str = gsub(str, '^#+ *', '') - tbl[j] = gsub(str, '^* ', '\n• ') - end - local str = concat(tbl, '\n') - str = gsub(str, '\n\n\n+', '\n\n') - str = gsub(str, '\n%> ', '\n') - str = gsub(str, '`', '') - str = gsub(str, '/%*', '\x01') - str = gsub(str, '%*', '') - str = gsub(str, '\x01', '\x2f*') - -- str = gsub(str, '%b<>', '') - -- replace [foo][bar] with foo - str = gsub(str, '%[(%C-)%]%[%C-%]', '%1') - str = '/*\n' .. str .. '\n*/\npackage gofpdf\n' - write(filestr, str) -end - -local godoc, markdown, readme = {}, {}, {} -local modeg, modem, moder - -for str in io.lines('document.md') do - local mode = string.match(str, '^~(%a*)~$') - if mode then - modeg = find(mode, 'g') ~= nil - moder = find(mode, 'r') ~= nil - modem = find(mode, 'm') ~= nil - else - if modeg then - insert(godoc, str) - end - if modem then - insert(markdown, str) - end - if moder then - insert(readme, str) - end - end -end - -markdownwrite(markdown, 'doc/body.md') -godocwrite(godoc, 'doc.go') -readmewrite(readme, 'README.md') diff --git a/doc/document.md b/doc/document.md new file mode 100644 index 0000000..16ca686 --- /dev/null +++ b/doc/document.md @@ -0,0 +1,254 @@ +# GoFPDF document generator + +[![MIT licensed][badge-mit]][license] +[![Report][badge-report]][report] +[![GoDoc][badge-doc]][godoc] + +![][logo] + +Package gofpdf implements a PDF document generator with high level support for +text, drawing and images. + +## Features + +* Choice of measurement unit, page format and margins +* Page header and footer management +* Automatic page breaks, line breaks, and text justification +* Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images +* Colors, gradients and alpha channel transparency +* Outline bookmarks +* Internal and external links +* TrueType, Type1 and encoding support +* Page compression +* Lines, Bézier curves, arcs, and ellipses +* Rotation, scaling, skewing, translation, and mirroring +* Clipping +* Document protection +* Layers +* Templates +* Barcodes +* Charting facility + +gofpdf has no dependencies other than the Go standard library. All tests pass +on Linux, Mac and Windows platforms. + +Like FPDF version 1.7, from which gofpdf is derived, this package does not yet +support UTF-8 fonts. In particular, languages that require more than one code +page such as Chinese, Japanese, and Arabic are not currently supported. This is +explained in [issue 109][issue109]. However, support is provided to +automatically translate UTF-8 runes to code page encodings for languages that +have fewer than 256 glyphs. + +## Installation + +To install the package on your system, run + +```shell +go get github.com/jung-kurt/gofpdf +``` + +Later, to receive updates, run + +```shell +go get -u -v github.com/jung-kurt/gofpdf/... +``` + +## Quick Start + +The following Go code generates a simple PDF file. + +```go +pdf := gofpdf.New("P", "mm", "A4", "") +pdf.AddPage() +pdf.SetFont("Arial", "B", 16) +pdf.Cell(40, 10, "Hello, world") +err := pdf.OutputFileAndClose("hello.pdf") +``` + +See the functions in the [fpdf_test.go][fpdf-test] file (shown as examples in +this documentation) for more advanced PDF examples. + +## Errors + +If an error occurs in an Fpdf method, an internal error field is set. After +this occurs, Fpdf method calls typically return without performing any +operations and the error state is retained. This error management scheme +facilitates PDF generation since individual method calls do not need to be +examined for failure; it is generally sufficient to wait until after `Output()` +is called. For the same reason, if an error occurs in the calling application +during PDF generation, it may be desirable for the application to transfer the +error to the Fpdf instance by calling the `SetError()` method or the +`SetErrorf()` method. At any time during the life cycle of the Fpdf instance, +the error state can be determined with a call to `Ok()` or `Err()`. The error +itself can be retrieved with a call to `Error()`. + +## Conversion Notes + +This package is a relatively straightforward translation from the original +[FPDF][fpdf-site] library written in PHP (despite the caveat in the +introduction to [Effective Go][effective-go]). The +API names have been retained even though the Go idiom would suggest otherwise +(for example, `pdf.GetX()` is used rather than simply `pdf.X()`). The +similarity of the two libraries makes the original FPDF website a good source +of information. It includes a forum and FAQ. + +However, some internal changes have been made. Page content is built up using +buffers (of type bytes.Buffer) rather than repeated string concatenation. +Errors are handled as explained above rather than panicking. Output is +generated through an interface of type io.Writer or io.WriteCloser. A number of +the original PHP methods behave differently based on the type of the arguments +that are passed to them; in these cases additional methods have been exported +to provide similar functionality. Font definition files are produced in JSON +rather than PHP. + +## Example PDFs + +A side effect of running `go test ./...` is the production of a number of +example PDFs. These can be found in the gofpdf/pdf directory after the tests +complete. + +Please note that these examples run in the context of a test. In order run an +example as a standalone application, you'll need to examine +[fpdf_test.go][fpdf-test] for some helper routines, for example +`exampleFilename()` and `summary()`. + +Example PDFs can be compared with reference copies in order to verify that they +have been generated as expected. This comparison will be performed if a PDF +with the same name as the example PDF is placed in the gofpdf/pdf/reference +directory and if the third argument to `ComparePDFFiles()` in +internal/example/example.go is true. (By default it is false.) The routine that +summarizes an example will look for this file and, if found, will call +`ComparePDFFiles()` to check the example PDF for equality with its reference PDF. +If differences exist between the two files they will be printed to standard +output and the test will fail. If the reference file is missing, the comparison +is considered to succeed. In order to successfully compare two PDFs, the +placement of internal resources must be consistent and the internal creation +timestamps must be the same. To do this, the methods `SetCatalogSort()` and +`SetCreationDate()` need to be called for both files. This is done automatically +for all examples. + +## Nonstandard Fonts + +Nothing special is required to use the standard PDF fonts (courier, helvetica, +times, zapfdingbats) in your documents other than calling `SetFont()`. + +In order to use a different TrueType or Type1 font, you will need to generate a +font definition file and, if the font will be embedded into PDFs, a compressed +version of the font file. This is done by calling the `MakeFont()` function or +using the included makefont command line utility. To create the utility, cd +into the makefont subdirectory and run `go build`. This will produce a +standalone executable named makefont. Select the appropriate encoding file from +the font subdirectory and run the command as in the following example. + +```shell +./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf +``` + +In your PDF generation code, call AddFont() to load the font and, as with the +standard fonts, SetFont() to begin using it. Most examples, including the +package example, demonstrate this method. Good sources of free, open-source +fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. + +## Related Packages + +The [draw2d][draw2d-site] package is a two dimensional vector graphics library that +can generate output in different forms. It uses gofpdf for its document +production mode. + +## Contributing Changes + +gofpdf is a global community effort and you are invited to make it even better. +If you have implemented a new feature or corrected a problem, please consider +contributing your change to the project. A contribution that does not directly +pertain to the core functionality of gofpdf should be placed in its own +directory directly beneath the `contrib` directory. + +Here are guidelines for making submissions. Your change should + +* be compatible with the MIT License +* be properly documented +* be formatted with `go fmt` +* include an example in [fpdf_test.go][test] if appropriate +* conform to the standards of [golint][lint] and +[go vet][vet], that is, `golint .` and +`go vet .` should not generate any warnings +* not diminish [test coverage][coverage] + +[Pull requests][pr] are the preferred means of accepting your changes. + +## License + +gofpdf is released under the MIT License. It is copyrighted by Kurt Jung and +the contributors acknowledged below. + +## Acknowledgments + +This package's code and documentation are closely derived from the [FPDF][fpdf-site] +library created by Olivier Plathey, and a number of font and image resources +are copied directly from it. Bruno Michel has provided valuable assistance with +the code. Drawing support is adapted from the FPDF geometric figures script by +David Hernández Sanz. Transparency support is adapted from the FPDF +transparency script by Martin Hall-May. Support for gradients and clipping is +adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is +adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from +Olivier Plathey. Support for transformations is adapted from the FPDF +transformation script by Moritz Wagner and Andreas Würmser. PDF protection is +adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence +Kesteloot provided code to allow an image's extent to be determined prior to +placement. Support for vertical alignment within a cell was provided by Stefan +Schroeder. Ivan Daniluk generalized the font and image loading code to use the +Reader interface while maintaining backward compatibility. Anthony Starks +provided code for the Polygon function. Robert Lillack provided the Beziergon +function and corrected some naming issues with the internal curve function. +Claudio Felber provided implementations for dashed line drawing and generalized +font loading. Stani Michiels provided support for multi-segment path drawing +with smooth line joins, line join styles, enhanced fill modes, and has helped +greatly with package presentation and tests. Templating is adapted by Marcus +Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer +Snoeck contributed packages that generate a variety of barcodes and help with +registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the +basic HTML functionality with aligned text. Kent Quirk implemented +backwards-compatible support for reading DPI from images that support it, and +for setting DPI manually and then having it properly taken into account when +calculating image size. Paulo Coutinho provided support for static embedded +fonts. Dan Meyers added support for embedded JavaScript. David Fish added a +generic alias-replacement function to enable, among other things, table of +contents functionality. Andy Bakun identified and corrected a problem in which +the internal catalogs were not sorted stably. Paul Montag added encoding and +decoding functionality for templates, including images that are embedded in +templates; this allows templates to be stored independently of gofpdf. Paul +also added support for page boxes used in printing PDF documents. Wojciech +Matusiak added supported for word spacing. + +## Roadmap + +* Handle UTF-8 source text natively. Until then, automatic translation of +UTF-8 runes to code page bytes is provided. +* Improve test coverage as reported by the coverage tool. + + +[badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg +[badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg +[badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg +[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg +[badge-report]: https://goreportcard.com/badge/github.com/jung-kurt/gofpdf +[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master +[coverage]: https://blog.golang.org/cover +[dfont]: http://dejavu-fonts.org/ +[draw2d-site]: https://github.com/llgcode/draw2d +[effective-go]: https://golang.org/doc/effective_go.html +[fpdf-site]: http://www.fpdf.org/ +[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[gfont]: https://fonts.google.com/ +[github]: https://github.com/jung-kurt/gofpdf +[godoc]: https://godoc.org/github.com/jung-kurt/gofpdf +[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 +[jung]: https://github.com/jung-kurt/ +[license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE +[lint]: https://github.com/golang/lint +[logo]: https://github.com/jung-kurt/gofpdf/raw/master/image/logo_gofpdf.jpg?raw=true +[pr]: https://help.github.com/articles/using-pull-requests/ +[report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf +[status]: https://travis-ci.org/jung-kurt/gofpdf +[test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[vet]: https://golang.org/cmd/vet/ diff --git a/doc/ftr.html b/doc/ftr.html deleted file mode 100644 index 47fc456..0000000 --- a/doc/ftr.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/doc/go.awk b/doc/go.awk new file mode 100644 index 0000000..a325362 --- /dev/null +++ b/doc/go.awk @@ -0,0 +1,19 @@ +BEGIN { + show = 0 + print "/*" +} + +/^\-/ { + trim = 1 + print "" +} + +/^Package/ { show = 1 } + +!NF { trim = 0 } + +trim { sub("^ +", "", $0) } + +show { print $0 } + +END { print "*/\npackage gofpdf" } diff --git a/doc/hdr.html b/doc/hdr.html deleted file mode 100644 index 161ec47..0000000 --- a/doc/hdr.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - CGI for Caddy - - - - diff --git a/doc/html.txt b/doc/html.txt new file mode 100644 index 0000000..7a89bb1 --- /dev/null +++ b/doc/html.txt @@ -0,0 +1,68 @@ + + + + + + + + GoFPDF Document Generator + + + + +$body$ + + + diff --git a/document.md b/document.md deleted file mode 100644 index d0f79cb..0000000 --- a/document.md +++ /dev/null @@ -1,262 +0,0 @@ -~rm~ -# GoFPDF document generator - -~m~ -[![Git Hub repository][badge-github]][github] -[![Kurt Jung][badge-author]][jung] -~rm~ -[![MIT licensed][badge-mit]][license] -[![Report][badge-report]][report] -[![GoDoc][badge-doc]][godoc] - -~rm~ -![gofpdf](image/logo_gofpdf.jpg?raw=true "gofpdf") - -~rgm~ -Package gofpdf implements a PDF document generator with high level support for -text, drawing and images. - -## Features - -* Choice of measurement unit, page format and margins -* Page header and footer management -* Automatic page breaks, line breaks, and text justification -* Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images -* Colors, gradients and alpha channel transparency -* Outline bookmarks -* Internal and external links -* TrueType, Type1 and encoding support -* Page compression -* Lines, Bézier curves, arcs, and ellipses -* Rotation, scaling, skewing, translation, and mirroring -* Clipping -* Document protection -* Layers -* Templates -* Barcodes -* Charting facility - -gofpdf has no dependencies other than the Go standard library. All tests pass -on Linux, Mac and Windows platforms. - -Like FPDF version 1.7, from which gofpdf is derived, this package does not yet -support UTF-8 fonts. In particular, languages that require more than one code -page such as Chinese, Japanese, and Arabic are not currently supported. This is -explained in [issue 109][issue109]. However, support is provided to -automatically translate UTF-8 runes to code page encodings for languages that -have fewer than 256 glyphs. - -## Installation - -To install the package on your system, run - -```shell -go get github.com/jung-kurt/gofpdf -``` - -Later, to receive updates, run - -```shell -go get -u -v github.com/jung-kurt/gofpdf/... -``` - -## Quick Start - -The following Go code generates a simple PDF file. - -```go -pdf := gofpdf.New("P", "mm", "A4", "") -pdf.AddPage() -pdf.SetFont("Arial", "B", 16) -pdf.Cell(40, 10, "Hello, world") -err := pdf.OutputFileAndClose("hello.pdf") -``` - -See the functions in the -[fpdf_test.go][fpdf-test] -file (shown as examples in this documentation) for more advanced PDF examples. - -## Errors - -If an error occurs in an Fpdf method, an internal error field is set. After -this occurs, Fpdf method calls typically return without performing any -operations and the error state is retained. This error management scheme -facilitates PDF generation since individual method calls do not need to be -examined for failure; it is generally sufficient to wait until after `Output()` -is called. For the same reason, if an error occurs in the calling application -during PDF generation, it may be desirable for the application to transfer the -error to the Fpdf instance by calling the `SetError()` method or the -`SetErrorf()` method. At any time during the life cycle of the Fpdf instance, -the error state can be determined with a call to `Ok()` or `Err()`. The error -itself can be retrieved with a call to `Error()`. - -## Conversion Notes - -This package is a relatively straightforward translation from the original -[FPDF][fpdf-site] library written in PHP (despite the caveat in the -introduction to [Effective Go][effective-go]). The -API names have been retained even though the Go idiom would suggest otherwise -(for example, `pdf.GetX()` is used rather than simply `pdf.X()`). The -similarity of the two libraries makes the original FPDF website a good source -of information. It includes a forum and FAQ. - -However, some internal changes have been made. Page content is built up using -buffers (of type bytes.Buffer) rather than repeated string concatenation. -Errors are handled as explained above rather than panicking. Output is -generated through an interface of type io.Writer or io.WriteCloser. A number of -the original PHP methods behave differently based on the type of the arguments -that are passed to them; in these cases additional methods have been exported -to provide similar functionality. Font definition files are produced in JSON -rather than PHP. - -## Example PDFs - -A side effect of running `go test ./...` is the production of a number of -example PDFs. These can be found in the gofpdf/pdf directory after the tests -complete. - -Please note that these examples run in the context of a test. In order run an -example as a standalone application, you'll need to examine -[fpdf_test.go][fpdf-test] for some helper routines, for example -`exampleFilename()` and `summary()`. - -Example PDFs can be compared with reference copies in order to verify that they -have been generated as expected. This comparison will be performed if a PDF -with the same name as the example PDF is placed in the gofpdf/pdf/reference -directory and if the third argument to `ComparePDFFiles()` in -internal/example/example.go is true. (By default it is false.) The routine that -summarizes an example will look for this file and, if found, will call -`ComparePDFFiles()` to check the example PDF for equality with its reference PDF. -If differences exist between the two files they will be printed to standard -output and the test will fail. If the reference file is missing, the comparison -is considered to succeed. In order to successfully compare two PDFs, the -placement of internal resources must be consistent and the internal creation -timestamps must be the same. To do this, the methods `SetCatalogSort()` and -`SetCreationDate()` need to be called for both files. This is done automatically -for all examples. - -## Nonstandard Fonts - -Nothing special is required to use the standard PDF fonts (courier, helvetica, -times, zapfdingbats) in your documents other than calling `SetFont()`. - -In order to use a different TrueType or Type1 font, you will need to generate a -font definition file and, if the font will be embedded into PDFs, a compressed -version of the font file. This is done by calling the `MakeFont()` function or -using the included makefont command line utility. To create the utility, cd -into the makefont subdirectory and run `go build`. This will produce a -standalone executable named makefont. Select the appropriate encoding file from -the font subdirectory and run the command as in the following example. - -```shell -./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf -``` - -In your PDF generation code, call AddFont() to load the font and, as with the -standard fonts, SetFont() to begin using it. Most examples, including the -package example, demonstrate this method. Good sources of free, open-source -fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. - -## Related Packages - -The [draw2d][draw2d-site] package is a two dimensional vector graphics library that -can generate output in different forms. It uses gofpdf for its document -production mode. - -## Contributing Changes - -gofpdf is a global community effort and you are invited to make it even better. -If you have implemented a new feature or corrected a problem, please consider -contributing your change to the project. A contribution that does not directly -pertain to the core functionality of gofpdf should be placed in its own -directory directly beneath the `contrib` directory. - -Here are guidelines for making submissions. Your change should - -* be compatible with the MIT License -* be properly documented -* be formatted with `go fmt` -* include an example in [fpdf_test.go][test] if appropriate -* conform to the standards of [golint][lint] and -[go vet][vet], that is, `golint .` and -`go vet .` should not generate any warnings -* not diminish [test coverage][coverage] - -[Pull requests][pr] are the preferred means of accepting your changes. - -## License - -gofpdf is released under the MIT License. It is copyrighted by Kurt Jung and -the contributors acknowledged below. - -## Acknowledgments - -This package's code and documentation are closely derived from the [FPDF][fpdf-site] -library created by Olivier Plathey, and a number of font and image resources -are copied directly from it. Bruno Michel has provided valuable assistance with -the code. Drawing support is adapted from the FPDF geometric figures script by -David Hernández Sanz. Transparency support is adapted from the FPDF -transparency script by Martin Hall-May. Support for gradients and clipping is -adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is -adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from -Olivier Plathey. Support for transformations is adapted from the FPDF -transformation script by Moritz Wagner and Andreas Würmser. PDF protection is -adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence -Kesteloot provided code to allow an image's extent to be determined prior to -placement. Support for vertical alignment within a cell was provided by Stefan -Schroeder. Ivan Daniluk generalized the font and image loading code to use the -Reader interface while maintaining backward compatibility. Anthony Starks -provided code for the Polygon function. Robert Lillack provided the Beziergon -function and corrected some naming issues with the internal curve function. -Claudio Felber provided implementations for dashed line drawing and generalized -font loading. Stani Michiels provided support for multi-segment path drawing -with smooth line joins, line join styles, enhanced fill modes, and has helped -greatly with package presentation and tests. Templating is adapted by Marcus -Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer -Snoeck contributed packages that generate a variety of barcodes and help with -registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the -basic HTML functionality with aligned text. Kent Quirk implemented -backwards-compatible support for reading DPI from images that support it, and -for setting DPI manually and then having it properly taken into account when -calculating image size. Paulo Coutinho provided support for static embedded -fonts. Dan Meyers added support for embedded JavaScript. David Fish added a -generic alias-replacement function to enable, among other things, table of -contents functionality. Andy Bakun identified and corrected a problem in which -the internal catalogs were not sorted stably. Paul Montag added encoding and -decoding functionality for templates, including images that are embedded in -templates; this allows templates to be stored independently of gofpdf. Paul -also added support for page boxes used in printing PDF documents. Wojciech -Matusiak added supported for word spacing. - -## Roadmap - -* Handle UTF-8 source text natively. Until then, automatic translation of -UTF-8 runes to code page bytes is provided. -* Improve test coverage as reported by the coverage tool. - - -~mr~ -[badge-author]: https://img.shields.io/badge/author-Kurt_Jung-blue.svg -[badge-doc]: https://img.shields.io/badge/godoc-GoFPDF-blue.svg -[badge-github]: https://img.shields.io/badge/project-Git_Hub-blue.svg -[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg -[badge-report]: https://goreportcard.com/badge/github.com/jung-kurt/gofpdf -[badge-status]: https://travis-ci.org/jung-kurt/gofpdf.svg?branch=master -[coverage]: https://blog.golang.org/cover -[dfont]: http://dejavu-fonts.org/ -[draw2d-site]: https://github.com/llgcode/draw2d -[effective-go]: https://golang.org/doc/effective_go.html -[fpdf-site]: http://www.fpdf.org/ -[fpdf-test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[gfont]: https://fonts.google.com/ -[github]: https://github.com/jung-kurt/gofpdf -[godoc]: https://godoc.org/github.com/jung-kurt/gofpdf -[issue109]: https://github.com/jung-kurt/gofpdf/issues/109 -[jung]: https://github.com/jung-kurt/ -[license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE -[lint]: https://github.com/golang/lint -[pr]: https://help.github.com/articles/using-pull-requests/ -[report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf -[status]: https://travis-ci.org/jung-kurt/gofpdf -[test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go -[vet]: https://golang.org/cmd/vet/ -- cgit v1.2.1-24-ge1ad From 30a37b5fca264d688cf7a87cf1f9d0b627d45202 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 6 May 2019 07:43:54 -0400 Subject: Adjust method comments to coform with Go documentation standards --- fpdf.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fpdf.go b/fpdf.go index 47a95e2..ceb6beb 100644 --- a/fpdf.go +++ b/fpdf.go @@ -618,12 +618,12 @@ func (f *Fpdf) AliasNbPages(aliasStr string) { f.aliasNbPagesStr = aliasStr } -// enable right to left mode +// RTL enables right-to-left mode func (f *Fpdf) RTL() { f.isRTL = true } -// disable right to left mode +// LTR disables right-to-left mode func (f *Fpdf) LTR() { f.isRTL = false } -- cgit v1.2.1-24-ge1ad From ce58337af2deb2d3f26d0d2f9f1a18f4da64f638 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 6 May 2019 07:55:23 -0400 Subject: Convey changes made in README to doc/document.txt so pandoc can generate README and doc.go --- README.md | 141 +++++++++++++++++++++++++++----------------------------- doc.go | 37 +++++++-------- doc/document.md | 37 ++++++++------- 3 files changed, 107 insertions(+), 108 deletions(-) diff --git a/README.md b/README.md index 1135f0c..2e163b9 100644 --- a/README.md +++ b/README.md @@ -12,33 +12,32 @@ support for text, drawing and images. ## Features -* Choice of measurement unit, page format and margins -* Page header and footer management -* Automatic page breaks, line breaks, and text justification -* Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images -* Colors, gradients and alpha channel transparency -* Outline bookmarks -* Internal and external links -* TrueType, Type1 and encoding support -* Page compression -* Lines, Bézier curves, arcs, and ellipses -* Rotation, scaling, skewing, translation, and mirroring -* Clipping -* Document protection -* Layers -* Templates -* Barcodes -* Charting facility -* UTF-8 support - -gofpdf has no dependencies other than the Go standard library. All tests pass -on Linux, Mac and Windows platforms. - -gofpdf supports UTF-8 fonts and "right to left" languages. - -Also, support is provided to automatically translate -UTF-8 runes to code page encodings for languages that have fewer than 256 -glyphs. + - Choice of measurement unit, page format and margins + - Page header and footer management + - Automatic page breaks, line breaks, and text justification + - Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images + - Colors, gradients and alpha channel transparency + - Outline bookmarks + - Internal and external links + - TrueType, Type1 and encoding support + - Page compression + - Lines, Bézier curves, arcs, and ellipses + - Rotation, scaling, skewing, translation, and mirroring + - Clipping + - Document protection + - Layers + - Templates + - Barcodes + - Charting facility + - UTF-8 support + +gofpdf has no dependencies other than the Go standard library. All tests +pass on Linux, Mac and Windows platforms. + +gofpdf supports UTF-8 fonts and “right-to-left” languages. + +Also, support is provided to automatically translate UTF-8 runes to code +page encodings for languages that have fewer than 256 glyphs. ## Installation @@ -141,31 +140,24 @@ Nothing special is required to use the standard PDF fonts (courier, helvetica, times, zapfdingbats) in your documents other than calling `SetFont()`. -In order to use a different TrueType or Type1 font, you will need to -generate a font definition file and, if the font will be embedded into -PDFs, a compressed version of the font file. This is done by calling the -`MakeFont()` function or using the included makefont command line -utility. To create the utility, cd into the makefont subdirectory and -run `go build`. This will produce a standalone executable named +You should use AddUTF8Font or AddUTF8FontFromBytes to add UTF-8 TTF +font. `RTL()` and `LTR()` methods switch between “right-to-left” and +“left-to-right” mode. + +In order to use a different non-UTF-8 TrueType or Type1 font, you will +need to generate a font definition file and, if the font will be +embedded into PDFs, a compressed version of the font file. This is done +by calling the MakeFont function or using the included makefont command +line utility. To create the utility, cd into the makefont subdirectory +and run “go build”. This will produce a standalone executable named makefont. Select the appropriate encoding file from the font subdirectory and run the command as in the following example. -You should use AddUTF8Font or AddUTF8FontFromBytes to add UTF-8 TTF font. -RTL() and LTR() methods switch between "right to left" and "left to right" mode. - -In order to use a different non-UTF-8 TrueType or Type1 font, you will need to generate a -font definition file and, if the font will be embedded into PDFs, a compressed -version of the font file. This is done by calling the MakeFont function or -using the included makefont command line utility. To create the utility, cd -into the makefont subdirectory and run "go build". This will produce a -standalone executable named makefont. Select the appropriate encoding file from -the font subdirectory and run the command as in the following example. - -``` +``` shell ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf ``` -In your PDF generation code, call AddFont() to load the font and, as +In your PDF generation code, call `AddFont()` to load the font and, as with the standard fonts, SetFont() to begin using it. Most examples, including the package example, demonstrate this method. Good sources of free, open-source fonts include [Google @@ -221,33 +213,36 @@ FPDF scripts by Andreas Würmser. Support for outline bookmarks is adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from Olivier Plathey. Support for transformations is adapted from the FPDF transformation script by Moritz Wagner and Andreas Würmser. PDF -protection is adapted from the work of Klemen Vodopivec for the FPDF product. -Lawrence Kesteloot provided code to allow an image's extent to be determined -prior to placement. Support for vertical alignment within a cell was provided -by Stefan Schroeder. Ivan Daniluk generalized the font and image loading code -to use the Reader interface while maintaining backward compatibility. Anthony -Starks provided code for the Polygon function. Robert Lillack provided the -Beziergon function and corrected some naming issues with the internal curve -function. Claudio Felber provided implementations for dashed line drawing and -generalized font loading. Stani Michiels provided support for multi-segment -path drawing with smooth line joins, line join styles, enhanced fill modes, and -has helped greatly with package presentation and tests. Templating is adapted -by Marcus Downing from the FPDF\_Tpl library created by Jan Slabon and Setasign. -Jelmer Snoeck contributed packages that generate a variety of barcodes and help -with registering images on the web. Jelmer Snoek and Guillermo Pascual -augmented the basic HTML functionality with aligned text. Kent Quirk -implemented backwards-compatible support for reading DPI from images that -support it, and for setting DPI manually and then having it properly taken into -account when calculating image size. Paulo Coutinho provided support for static -embedded fonts. Dan Meyers added support for embedded JavaScript. David Fish -added a generic alias-replacement function to enable, among other things, table -of contents functionality. Andy Bakun identified and corrected a problem in -which the internal catalogs were not sorted stably. Paul Montag added encoding -and decoding functionality for templates, including images that are embedded in -templates; this allows templates to be stored independently of gofpdf. Paul -also added support for page boxes used in printing PDF documents. Wojciech -Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. +protection is adapted from the work of Klemen Vodopivec for the FPDF +product. Lawrence Kesteloot provided code to allow an image’s extent to +be determined prior to placement. Support for vertical alignment within +a cell was provided by Stefan Schroeder. Ivan Daniluk generalized the +font and image loading code to use the Reader interface while +maintaining backward compatibility. Anthony Starks provided code for the +Polygon function. Robert Lillack provided the Beziergon function and +corrected some naming issues with the internal curve function. Claudio +Felber provided implementations for dashed line drawing and generalized +font loading. Stani Michiels provided support for multi-segment path +drawing with smooth line joins, line join styles, enhanced fill modes, +and has helped greatly with package presentation and tests. Templating +is adapted by Marcus Downing from the FPDF\_Tpl library created by Jan +Slabon and Setasign. Jelmer Snoeck contributed packages that generate a +variety of barcodes and help with registering images on the web. Jelmer +Snoek and Guillermo Pascual augmented the basic HTML functionality with +aligned text. Kent Quirk implemented backwards-compatible support for +reading DPI from images that support it, and for setting DPI manually +and then having it properly taken into account when calculating image +size. Paulo Coutinho provided support for static embedded fonts. Dan +Meyers added support for embedded JavaScript. David Fish added a generic +alias-replacement function to enable, among other things, table of +contents functionality. Andy Bakun identified and corrected a problem in +which the internal catalogs were not sorted stably. Paul Montag added +encoding and decoding functionality for templates, including images that +are embedded in templates; this allows templates to be stored +independently of gofpdf. Paul also added support for page boxes used in +printing PDF documents. Wojciech Matusiak added supported for word +spacing. Artem Korotkiy added support of UTF-8 fonts. ## Roadmap -* Improve test coverage as reported by the coverage tool. + - Improve test coverage as reported by the coverage tool. diff --git a/doc.go b/doc.go index 17a9bc1..1042302 100644 --- a/doc.go +++ b/doc.go @@ -40,15 +40,15 @@ Features - Charting facility +- UTF-8 support + gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. -Like FPDF version 1.7, from which gofpdf is derived, this package does -not yet support UTF-8 fonts. In particular, languages that require more -than one code page such as Chinese, Japanese, and Arabic are not -currently supported. This is explained in issue 109. However, support is -provided to automatically translate UTF-8 runes to code page encodings -for languages that have fewer than 256 glyphs. +gofpdf supports UTF-8 fonts and “right-to-left” languages. + +Also, support is provided to automatically translate UTF-8 runes to code +page encodings for languages that have fewer than 256 glyphs. Installation @@ -147,14 +147,18 @@ Nothing special is required to use the standard PDF fonts (courier, helvetica, times, zapfdingbats) in your documents other than calling SetFont(). -In order to use a different TrueType or Type1 font, you will need to -generate a font definition file and, if the font will be embedded into -PDFs, a compressed version of the font file. This is done by calling the -MakeFont() function or using the included makefont command line utility. -To create the utility, cd into the makefont subdirectory and run -go build. This will produce a standalone executable named makefont. -Select the appropriate encoding file from the font subdirectory and run -the command as in the following example. +You should use AddUTF8Font or AddUTF8FontFromBytes to add UTF-8 TTF +font. RTL() and LTR() methods switch between “right-to-left” and +“left-to-right” mode. + +In order to use a different non-UTF-8 TrueType or Type1 font, you will +need to generate a font definition file and, if the font will be +embedded into PDFs, a compressed version of the font file. This is done +by calling the MakeFont function or using the included makefont command +line utility. To create the utility, cd into the makefont subdirectory +and run “go build”. This will produce a standalone executable named +makefont. Select the appropriate encoding file from the font +subdirectory and run the command as in the following example. ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf @@ -246,15 +250,12 @@ encoding and decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word -spacing. +spacing. Artem Korotkiy added support of UTF-8 fonts. Roadmap -- Handle UTF-8 source text natively. Until then, automatic translation -of UTF-8 runes to code page bytes is provided. - - Improve test coverage as reported by the coverage tool. */ package gofpdf diff --git a/doc/document.md b/doc/document.md index 16ca686..eafb015 100644 --- a/doc/document.md +++ b/doc/document.md @@ -28,16 +28,15 @@ text, drawing and images. * Templates * Barcodes * Charting facility +* UTF-8 support gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. -Like FPDF version 1.7, from which gofpdf is derived, this package does not yet -support UTF-8 fonts. In particular, languages that require more than one code -page such as Chinese, Japanese, and Arabic are not currently supported. This is -explained in [issue 109][issue109]. However, support is provided to -automatically translate UTF-8 runes to code page encodings for languages that -have fewer than 256 glyphs. +gofpdf supports UTF-8 fonts and "right-to-left" languages. + +Also, support is provided to automatically translate UTF-8 runes to code page +encodings for languages that have fewer than 256 glyphs. ## Installation @@ -132,19 +131,24 @@ for all examples. Nothing special is required to use the standard PDF fonts (courier, helvetica, times, zapfdingbats) in your documents other than calling `SetFont()`. -In order to use a different TrueType or Type1 font, you will need to generate a -font definition file and, if the font will be embedded into PDFs, a compressed -version of the font file. This is done by calling the `MakeFont()` function or -using the included makefont command line utility. To create the utility, cd -into the makefont subdirectory and run `go build`. This will produce a -standalone executable named makefont. Select the appropriate encoding file from -the font subdirectory and run the command as in the following example. +You should use AddUTF8Font or AddUTF8FontFromBytes to add UTF-8 TTF font. +`RTL()` and `LTR()` methods switch between "right-to-left" and "left-to-right" +mode. + +In order to use a different non-UTF-8 TrueType or Type1 font, you will need to +generate a font definition file and, if the font will be embedded into PDFs, a +compressed version of the font file. This is done by calling the MakeFont +function or using the included makefont command line utility. To create the +utility, cd into the makefont subdirectory and run "go build". This will +produce a standalone executable named makefont. Select the appropriate encoding +file from the font subdirectory and run the command as in the following +example. ```shell ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf ``` -In your PDF generation code, call AddFont() to load the font and, as with the +In your PDF generation code, call `AddFont()` to load the font and, as with the standard fonts, SetFont() to begin using it. Most examples, including the package example, demonstrate this method. Good sources of free, open-source fonts include [Google Fonts][gfont] and [DejaVu Fonts][dfont]. @@ -218,12 +222,11 @@ the internal catalogs were not sorted stably. Paul Montag added encoding and decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech -Matusiak added supported for word spacing. +Matusiak added supported for word spacing. Artem Korotkiy added support of +UTF-8 fonts. ## Roadmap -* Handle UTF-8 source text natively. Until then, automatic translation of -UTF-8 runes to code page bytes is provided. * Improve test coverage as reported by the coverage tool. -- cgit v1.2.1-24-ge1ad From 19544237e961fe8e9ee7ca55fdafe724de35f889 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 6 May 2019 08:02:02 -0400 Subject: Reorganize documentation slightly. Place utf-8 feature more prominently. --- README.md | 8 ++++---- doc.go | 10 +++++----- doc/document.md | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2e163b9..84e7a1b 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ support for text, drawing and images. ## Features + - UTF-8 support - Choice of measurement unit, page format and margins - Page header and footer management - Automatic page breaks, line breaks, and text justification @@ -29,7 +30,6 @@ support for text, drawing and images. - Templates - Barcodes - Charting facility - - UTF-8 support gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. @@ -140,9 +140,9 @@ Nothing special is required to use the standard PDF fonts (courier, helvetica, times, zapfdingbats) in your documents other than calling `SetFont()`. -You should use AddUTF8Font or AddUTF8FontFromBytes to add UTF-8 TTF -font. `RTL()` and `LTR()` methods switch between “right-to-left” and -“left-to-right” mode. +You should use `AddUTF8Font()` or `AddUTF8FontFromBytes()` to add a +TrueType UTF-8 encoded font. Use `RTL()` and `LTR()` methods switch +between “right-to-left” and “left-to-right” mode. In order to use a different non-UTF-8 TrueType or Type1 font, you will need to generate a font definition file and, if the font will be diff --git a/doc.go b/doc.go index 1042302..11c7ef3 100644 --- a/doc.go +++ b/doc.go @@ -6,6 +6,8 @@ support for text, drawing and images. Features +- UTF-8 support + - Choice of measurement unit, page format and margins - Page header and footer management @@ -40,8 +42,6 @@ Features - Charting facility -- UTF-8 support - gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. @@ -147,9 +147,9 @@ Nothing special is required to use the standard PDF fonts (courier, helvetica, times, zapfdingbats) in your documents other than calling SetFont(). -You should use AddUTF8Font or AddUTF8FontFromBytes to add UTF-8 TTF -font. RTL() and LTR() methods switch between “right-to-left” and -“left-to-right” mode. +You should use AddUTF8Font() or AddUTF8FontFromBytes() to add a TrueType +UTF-8 encoded font. Use RTL() and LTR() methods switch between +“right-to-left” and “left-to-right” mode. In order to use a different non-UTF-8 TrueType or Type1 font, you will need to generate a font definition file and, if the font will be diff --git a/doc/document.md b/doc/document.md index eafb015..f650372 100644 --- a/doc/document.md +++ b/doc/document.md @@ -11,6 +11,7 @@ text, drawing and images. ## Features +* UTF-8 support * Choice of measurement unit, page format and margins * Page header and footer management * Automatic page breaks, line breaks, and text justification @@ -28,7 +29,6 @@ text, drawing and images. * Templates * Barcodes * Charting facility -* UTF-8 support gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. @@ -131,9 +131,9 @@ for all examples. Nothing special is required to use the standard PDF fonts (courier, helvetica, times, zapfdingbats) in your documents other than calling `SetFont()`. -You should use AddUTF8Font or AddUTF8FontFromBytes to add UTF-8 TTF font. -`RTL()` and `LTR()` methods switch between "right-to-left" and "left-to-right" -mode. +You should use `AddUTF8Font()` or `AddUTF8FontFromBytes()` to add a TrueType +UTF-8 encoded font. Use `RTL()` and `LTR()` methods switch between +"right-to-left" and "left-to-right" mode. In order to use a different non-UTF-8 TrueType or Type1 font, you will need to generate a font definition file and, if the font will be embedded into PDFs, a -- cgit v1.2.1-24-ge1ad From bd6c576bfedb4b1a02d8232f9332244a4497df55 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 6 May 2019 08:49:56 -0400 Subject: Correct some misspellings --- fpdf.go | 12 ++++++------ fpdf_test.go | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fpdf.go b/fpdf.go index ceb6beb..7859467 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2107,7 +2107,7 @@ func (f *Fpdf) Text(x, y float64, txtStr string) { var txt2 string if f.isCurrentUTF8 { if f.isRTL { - txtStr = revertText(txtStr) + txtStr = reverseText(txtStr) x -= f.GetStringWidth(txtStr) } txt2 = f.escape(utf8toutf16(txtStr, false)) @@ -2299,7 +2299,7 @@ func (f *Fpdf) CellFormat(w, h float64, txtStr, borderStr string, ln int, //If multibyte, Tw has no effect - do word spacing using an adjustment before each space if (f.ws != 0 || alignStr == "J") && f.isCurrentUTF8 { // && f.ws != 0 if f.isRTL { - txtStr = revertText(txtStr) + txtStr = reverseText(txtStr) } wmax := int(math.Ceil((w - 2*f.cMargin) * 1000 / f.fontSize)) for _, uni := range []rune(txtStr) { @@ -2324,7 +2324,7 @@ func (f *Fpdf) CellFormat(w, h float64, txtStr, borderStr string, ln int, var txt2 string if f.isCurrentUTF8 { if f.isRTL { - txtStr = revertText(txtStr) + txtStr = reverseText(txtStr) } txt2 = f.escape(utf8toutf16(txtStr, false)) for _, uni := range []rune(txtStr) { @@ -2370,12 +2370,12 @@ func (f *Fpdf) CellFormat(w, h float64, txtStr, borderStr string, ln int, } // Revert string to use in RTL languages -func revertText(text string) string { +func reverseText(text string) string { oldText := []rune(text) newText := make([]rune, len(oldText)) - lenght := len(oldText) - 1 + length := len(oldText) - 1 for i, r := range oldText { - newText[lenght-i] = r + newText[length-i] = r } return string(newText) } diff --git a/fpdf_test.go b/fpdf_test.go index 6042fab..4c1fc05 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2389,7 +2389,7 @@ func ExampleFpdf_SubWrite() { // ExampleFpdf_SetPage demomstrates the SetPage() method, allowing content // generation to be deferred until all pages have been added. func ExampleFpdf_SetPage() { - rnd := rand.New(rand.NewSource(0)) // Make reproducable documents + rnd := rand.New(rand.NewSource(0)) // Make reproducible documents pdf := gofpdf.New("L", "cm", "A4", "") pdf.SetFont("Times", "", 12) -- cgit v1.2.1-24-ge1ad From 7e2fd5e62062f910ad6fe58dcca97a7e69b85bb3 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 6 May 2019 08:59:02 -0400 Subject: Remove some ineffectual assignments as reported by goreportcard.com --- fpdf.go | 10 +++++----- utf8fontfile.go | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fpdf.go b/fpdf.go index 7859467..cd87ad9 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1736,9 +1736,9 @@ func (f *Fpdf) addFontFromBytes(familyStr, styleStr string, jsonFileBytes, zFile if utf8Bytes != nil { - if styleStr == "IB" { - styleStr = "BI" - } + // if styleStr == "IB" { + // styleStr = "BI" + // } Type := "UTF8" reader := fileReader{readerPosition: 0, array: utf8Bytes} @@ -3995,8 +3995,8 @@ func (f *Fpdf) generateCIDFontMap(font *fontDefType, LastRune int) { previousKey = key } nextKey = key + cws - ui := ws.getIndex("interval") - ui = ui + 1 + // ui := ws.getIndex("interval") + // ui = ui + 1 if ws.getIndex("interval") >= 0 { if cws > 3 { isInterval = true diff --git a/utf8fontfile.go b/utf8fontfile.go index 964e919..0894701 100644 --- a/utf8fontfile.go +++ b/utf8fontfile.go @@ -863,8 +863,8 @@ func (utf *utf8FontFile) parseHMTXTable(numberOfHMetrics, numSymbols int, symbol } } } - data := utf.getRange(start+numberOfHMetrics*4, numSymbols*2) - arr = unpackUint16Array(data) + // data := utf.getRange(start+numberOfHMetrics*4, numSymbols*2) + // arr = unpackUint16Array(data) diff := numSymbols - numberOfHMetrics for pos := 0; pos < diff; pos++ { symbol := pos + numberOfHMetrics -- cgit v1.2.1-24-ge1ad From 641cda87ac3cf98cf58400cb3ce7513b6cc74295 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 6 May 2019 21:22:13 -0400 Subject: Check for errors when loading UTF-8 font --- fpdf.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/fpdf.go b/fpdf.go index cd87ad9..0195cd3 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1599,17 +1599,26 @@ func (f *Fpdf) addFont(familyStr, styleStr, fileStr string, isUTF8 bool) { if ok { return } - ttfStat, _ := os.Stat(fileStr) + var ttfStat os.FileInfo + var err error + ttfStat, err = os.Stat(fileStr) + if err != nil { + f.SetError(err) + return + } originalSize := ttfStat.Size() Type := "UTF8" - - utf8Bytes, _ := ioutil.ReadFile(fileStr) + var utf8Bytes []byte + utf8Bytes, err = ioutil.ReadFile(fileStr) + if err != nil { + f.SetError(err) + return + } reader := fileReader{readerPosition: 0, array: utf8Bytes} utf8File := newUTF8Font(&reader) - - err := utf8File.parseFile() + err = utf8File.parseFile() if err != nil { - fmt.Printf("get metrics Error: %e\n", err) + f.SetError(err) return } -- cgit v1.2.1-24-ge1ad From 71267fb332989953c8b27ec9a31832767886c926 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 7 May 2019 10:06:44 -0400 Subject: Add note about CJK fonts --- README.md | 7 ++++++- doc.go | 5 ++++- doc/document.md | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 84e7a1b..2d5d14e 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,12 @@ support for text, drawing and images. gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. -gofpdf supports UTF-8 fonts and “right-to-left” languages. +gofpdf supports UTF-8 TrueType fonts and “right-to-left” languages. Note +that Chinese, Japanese, and Korean characters may not be included in +many general purpose fonts. For these languages, a specialized font (for +example, +[NotoSansSC](https://github.com/jsntn/webfonts/blob/master/NotoSansSC-Regular.ttf) +for simplified Chinese) can be used. Also, support is provided to automatically translate UTF-8 runes to code page encodings for languages that have fewer than 256 glyphs. diff --git a/doc.go b/doc.go index 11c7ef3..2d6f49b 100644 --- a/doc.go +++ b/doc.go @@ -45,7 +45,10 @@ Features gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. -gofpdf supports UTF-8 fonts and “right-to-left” languages. +gofpdf supports UTF-8 TrueType fonts and “right-to-left” languages. Note +that Chinese, Japanese, and Korean characters may not be included in +many general purpose fonts. For these languages, a specialized font (for +example, NotoSansSC for simplified Chinese) can be used. Also, support is provided to automatically translate UTF-8 runes to code page encodings for languages that have fewer than 256 glyphs. diff --git a/doc/document.md b/doc/document.md index f650372..33f5dac 100644 --- a/doc/document.md +++ b/doc/document.md @@ -33,7 +33,10 @@ text, drawing and images. gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. -gofpdf supports UTF-8 fonts and "right-to-left" languages. +gofpdf supports UTF-8 TrueType fonts and "right-to-left" languages. Note that +Chinese, Japanese, and Korean characters may not be included in many general +purpose fonts. For these languages, a specialized font (for example, +[NotoSansSC][noto] for simplified Chinese) can be used. Also, support is provided to automatically translate UTF-8 runes to code page encodings for languages that have fewer than 256 glyphs. @@ -250,6 +253,7 @@ UTF-8 fonts. [license]: https://raw.githubusercontent.com/jung-kurt/gofpdf/master/LICENSE [lint]: https://github.com/golang/lint [logo]: https://github.com/jung-kurt/gofpdf/raw/master/image/logo_gofpdf.jpg?raw=true +[noto]: https://github.com/jsntn/webfonts/blob/master/NotoSansSC-Regular.ttf [pr]: https://help.github.com/articles/using-pull-requests/ [report]: https://goreportcard.com/report/github.com/jung-kurt/gofpdf [status]: https://travis-ci.org/jung-kurt/gofpdf -- cgit v1.2.1-24-ge1ad From 514e371ce761f71cf004bf0da3246824310b2e4f Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 7 May 2019 15:20:57 -0400 Subject: Add command line goreportcard check; address ineffectual assignments called out by this tool --- Makefile | 1 + fpdf.go | 2 -- utf8fontfile.go | 8 +++----- util.go | 8 +------- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index b0a5e06..410c89e 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ check : golint . go vet -all . gofmt -s -l . + goreportcard-cli -v README.md : doc/document.md pandoc --read=markdown --write=gfm < $< > $@ diff --git a/fpdf.go b/fpdf.go index 0195cd3..7bee6e5 100644 --- a/fpdf.go +++ b/fpdf.go @@ -3953,8 +3953,6 @@ func (f *Fpdf) generateCIDFontMap(font *fontDefType, LastRune int) { } interval = true cidArray[rangeID].put("interval", 1) - ui := 0 - ui = ui + 1 } else { if interval { // new range diff --git a/utf8fontfile.go b/utf8fontfile.go index 0894701..794bae2 100644 --- a/utf8fontfile.go +++ b/utf8fontfile.go @@ -377,7 +377,7 @@ func (utf *utf8FontFile) parseHHEATable() int { } func (utf *utf8FontFile) parseOS2Table() int { - weightType := 0 + var weightType int scale := 1000.0 / float64(utf.fontElementSize) if _, OK := utf.tableDescriptions["OS/2"]; OK { utf.SeekTable("OS/2") @@ -831,9 +831,9 @@ func (utf *utf8FontFile) getSymbols(originalSymbolIdx int, start *int, symbolSet } func (utf *utf8FontFile) parseHMTXTable(numberOfHMetrics, numSymbols int, symbolToChar map[int][]int, scale float64) { + var widths int start := utf.SeekTable("hmtx") arrayWidths := 0 - widths := 0 var arr []int utf.CharWidths = make([]int, 256*256) charCount := 0 @@ -863,8 +863,6 @@ func (utf *utf8FontFile) parseHMTXTable(numberOfHMetrics, numSymbols int, symbol } } } - // data := utf.getRange(start+numberOfHMetrics*4, numSymbols*2) - // arr = unpackUint16Array(data) diff := numSymbols - numberOfHMetrics for pos := 0; pos < diff; pos++ { symbol := pos + numberOfHMetrics @@ -949,7 +947,7 @@ func (utf *utf8FontFile) generateSCCSDictionaries(runeCmapPosition int, symbolCh for i := 0; i < segmentSize; i++ { positions = append(positions, utf.readUint16()) } - symbol := 0 + var symbol int for n := 0; n < segmentSize; n++ { completePosition := completers[n] + 1 for char := beginners[n]; char < completePosition; char++ { diff --git a/util.go b/util.go index e96cdd8..3902500 100644 --- a/util.go +++ b/util.go @@ -344,7 +344,7 @@ func (pa *untypedKeyMap) getIndex(key interface{}) int { //Put key=>value in PHP Array func (pa *untypedKeyMap) put(key interface{}, value int) { if key == nil { - i := 0 + var i int for n := 0; ; n++ { i = pa.getIndex(n) if i < 0 { @@ -419,14 +419,8 @@ func arrayMerge(arr1, arr2 *untypedKeyMap) *untypedKeyMap { answer.valueSet = arr1.valueSet[:] for i := 0; i < len(arr2.keySet); i++ { if arr2.keySet[i] == "interval" { - u := 0 - u = u + 1 if arr1.getIndex("interval") < 0 { answer.put("interval", arr2.valueSet[i]) - } else { - - u := 0 - u = u + 1 } } else { answer.put(nil, arr2.valueSet[i]) -- cgit v1.2.1-24-ge1ad From 65c03ae855f64ff46c37f9d58ed572a302bd355d Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 9 May 2019 10:21:35 -0400 Subject: Handle errors in UTF-8 example --- Makefile | 2 +- fpdf_test.go | 35 ++++++++++++++++++++++------------- go.mod | 6 ++++++ go.sum | 11 +++++++++++ 4 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 go.sum diff --git a/Makefile b/Makefile index 410c89e..f2590bd 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ check : golint . go vet -all . gofmt -s -l . - goreportcard-cli -v + goreportcard-cli -v | grep -v cyclomatic README.md : doc/document.md pandoc --read=markdown --write=gfm < $< > $@ diff --git a/fpdf_test.go b/fpdf_test.go index 4c1fc05..6b43af0 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2523,6 +2523,10 @@ func ExampleFpdf_TransformRotate() { // ExampleFpdf_AddUTF8Font demonstrates how use the font // with utf-8 mode func ExampleFpdf_AddUTF8Font() { + var fileStr string + var txtStr []byte + var err error + pdf := gofpdf.New("P", "mm", "A4", "") pdf.AddPage() @@ -2532,22 +2536,27 @@ func ExampleFpdf_AddUTF8Font() { pdf.AddUTF8Font("dejavu", "I", example.FontFile("DejaVuSansCondensed-Oblique.ttf")) pdf.AddUTF8Font("dejavu", "BI", example.FontFile("DejaVuSansCondensed-BoldOblique.ttf")) - txtStr, _ := ioutil.ReadFile(example.TextFile("utf-8test.txt")) + fileStr = example.Filename("Fpdf_AddUTF8Font") + txtStr, err = ioutil.ReadFile(example.TextFile("utf-8test.txt")) + if err == nil { + + pdf.SetFont("dejavu", "B", 17) + pdf.MultiCell(100, 8, "Text in different languages :", "", "C", false) + pdf.SetFont("dejavu", "", 14) + pdf.MultiCell(100, 5, string(txtStr), "", "C", false) + pdf.Ln(15) - pdf.SetFont("dejavu", "B", 17) - pdf.MultiCell(100, 8, "Text in different languages :", "", "C", false) - pdf.SetFont("dejavu", "", 14) - pdf.MultiCell(100, 5, string(txtStr), "", "C", false) - pdf.Ln(15) + txtStr, err = ioutil.ReadFile(example.TextFile("utf-8test2.txt")) + if err == nil { - txtStr, _ = ioutil.ReadFile(example.TextFile("utf-8test2.txt")) - pdf.SetFont("dejavu", "BI", 17) - pdf.MultiCell(100, 8, "Greek text with alignStr = \"J\":", "", "C", false) - pdf.SetFont("dejavu", "I", 14) - pdf.MultiCell(100, 5, string(txtStr), "", "J", false) + pdf.SetFont("dejavu", "BI", 17) + pdf.MultiCell(100, 8, "Greek text with alignStr = \"J\":", "", "C", false) + pdf.SetFont("dejavu", "I", 14) + pdf.MultiCell(100, 5, string(txtStr), "", "J", false) + err = pdf.OutputFileAndClose(fileStr) - fileStr := example.Filename("Fpdf_AddUTF8Font") - err := pdf.OutputFileAndClose(fileStr) + } + } example.Summary(err, fileStr) // Output: // Successfully generated pdf/Fpdf_AddUTF8Font.pdf diff --git a/go.mod b/go.mod index d5c6846..663e024 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,9 @@ module github.com/jung-kurt/gofpdf go 1.12 + +require ( + github.com/boombuler/barcode v1.0.0 + github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 + golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..8848810 --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 h1:nlG4Wa5+minh3S9LVFtNoY+GVRiudA2e3EVfcCi3RCA= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec h1:arXJwtMuk5vqI1NHX0UTnNw977rYk5Sl4jQqHj+hun4= +golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -- cgit v1.2.1-24-ge1ad From 8f080922446313698730071fd92ca15900e6a941 Mon Sep 17 00:00:00 2001 From: Kurt Date: Fri, 10 May 2019 17:47:17 -0400 Subject: Add SplitText() method for splitting utf-8 strings constrained by rendered width --- fpdf.go | 3 +++ splittext.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 splittext.go diff --git a/fpdf.go b/fpdf.go index 7bee6e5..d3366ce 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2407,6 +2407,9 @@ func (f *Fpdf) Cellf(w, h float64, fmtStr string, args ...interface{}) { // used to determine the total height of wrapped text for vertical placement // purposes. // +// This method is useful for codepage-based fonts only. For UTF-8 encoded text, +// use SplitText(). +// // You can use MultiCell if you want to print a text on several lines in a // simple way. func (f *Fpdf) SplitLines(txt []byte, w float64) [][]byte { diff --git a/splittext.go b/splittext.go new file mode 100644 index 0000000..3902199 --- /dev/null +++ b/splittext.go @@ -0,0 +1,54 @@ +package gofpdf + +import ( + "math" + // "strings" + "unicode" +) + +// SplitText splits UTF-8 encoded text into several lines using the current +// font. Each line has its length limited to a maximum width given by w. This +// function can be used to determine the total height of wrapped text for +// vertical placement purposes. +func (f *Fpdf) SplitText(txt string, w float64) (lines []string) { + cw := f.currentFont.Cw + wmax := int(math.Ceil((w - 2*f.cMargin) * 1000 / f.fontSize)) + s := []rune(txt) // Return slice of UTF-8 runes + nb := len(s) + for nb > 0 && s[nb-1] == '\n' { + nb-- + } + s = s[0:nb] + sep := -1 + i := 0 + j := 0 + l := 0 + for i < nb { + c := s[i] + l += cw[c] + if unicode.IsSpace(c) { + // if c == ' ' || c == '\t' || c == '\n' { + sep = i + } + if c == '\n' || l > wmax { + if sep == -1 { + if i == j { + i++ + } + sep = i + } else { + i = sep + 1 + } + lines = append(lines, string(s[j:sep])) + sep = -1 + j = i + l = 0 + } else { + i++ + } + } + if i != j { + lines = append(lines, string(s[j:i])) + } + return lines +} -- cgit v1.2.1-24-ge1ad From 1af5a0c18cae5799fbfc73dc8440abb7d7622837 Mon Sep 17 00:00:00 2001 From: Antonio Bosak Date: Wed, 15 May 2019 17:27:33 +0200 Subject: fix for not concating already defined filepath --- fpdf.go | 1 + 1 file changed, 1 insertion(+) diff --git a/fpdf.go b/fpdf.go index d3366ce..e2ff7d7 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1601,6 +1601,7 @@ func (f *Fpdf) addFont(familyStr, styleStr, fileStr string, isUTF8 bool) { } var ttfStat os.FileInfo var err error + fileStr = path.Join(f.fontpath, fileStr) ttfStat, err = os.Stat(fileStr) if err != nil { f.SetError(err) -- cgit v1.2.1-24-ge1ad From 0fb5126fefeb1a7be7ed1c4dac02539af931a237 Mon Sep 17 00:00:00 2001 From: Dave Barnes Date: Wed, 15 May 2019 10:45:22 -0500 Subject: Add support for imported objects and templates to version 1 of gofpdf. --- README.md | 3 +- contrib/gofpdi/gofpdi.go | 62 +++++++++++++++++++++++++++++++++ def.go | 4 +++ doc.go | 3 +- doc/document.md | 2 +- fpdf.go | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 contrib/gofpdi/gofpdi.go diff --git a/README.md b/README.md index 2d5d14e..fdd8980 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,8 @@ encoding and decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word -spacing. Artem Korotkiy added support of UTF-8 fonts. +spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added +support for imported objects and templates. ## Roadmap diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go new file mode 100644 index 0000000..c1f3df8 --- /dev/null +++ b/contrib/gofpdi/gofpdi.go @@ -0,0 +1,62 @@ +package gofpdi + +import ( + realgofpdi "github.com/phpdave11/gofpdi" +) + +// Create new gofpdi instance +var fpdi = realgofpdi.NewImporter() + +// gofpdiPdf is a partial interface that only implements the functions we need +// from the PDF generator to put the imported PDF templates on the PDF. +type gofpdiPdf interface { + ImportObjects(objs map[string][]byte) + ImportObjPos(objs map[string]map[int]string) + ImportTemplates(tpls map[string]string) + UseImportedTemplate(tplName string, x float64, y float64, w float64, h float64) + SetError(err error) +} + +// Imports a page of a PDF file with the specified box (/MediaBox, /TrimBox, /ArtBox, /CropBox, or /BleedBox). +// Returns a template id that can be used with UseImportedTemplate to draw the template onto the page. +func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { + // Set source file for fpdi + fpdi.SetSourceFile(sourceFile) + + // Import page + tpl := fpdi.ImportPage(pageno, box) + + // Import objects into current pdf document + // Unordered means that the objects will be returned with a sha1 hash instead of an integer + // The objects themselves may have references to other hashes which will be replaced in ImportObjects() + tplObjIds := fpdi.PutFormXobjectsUnordered() + + // Set template names and ids (hashes) in gofpdf + f.ImportTemplates(tplObjIds) + + // Get a map[string]string of the imported objects. + // The map keys will be the ID of each object. + imported := fpdi.GetImportedObjectsUnordered() + + // Import gofpdi objects into gofpdf + f.ImportObjects(imported) + + // Get a map[string]map[int]string of the object hashes and their positions within each object, + // to be replaced with object ids (integers). + importedObjPos := fpdi.GetImportedObjHashPos() + + // Import gofpdi object hashes and their positions into gopdf + f.ImportObjPos(importedObjPos) + + return tpl +} + +// Draw the template onto the page at x,y +// If w is 0, the template will be scaled to fit based on h +// If h is 0, the template will be scaled to fit based on w +func UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) { + // Get values from fpdi + tplName, scaleX, scaleY, tX, tY := fpdi.UseTemplate(tplid, x, y, w, h) + + f.UseImportedTemplate(tplName, scaleX, scaleY, tX, tY) +} diff --git a/def.go b/def.go index ab4e81d..f725f01 100644 --- a/def.go +++ b/def.go @@ -504,6 +504,10 @@ type Fpdf struct { offsets []int // array of object offsets templates map[string]Template // templates used in this document templateObjects map[string]int // template object IDs within this document + importedObjs map[string][]byte // imported template objects (gofpdi) + importedObjPos map[string]map[int]string // imported template objects hashes and their positions (gofpdi) + importedTplObjs map[string]string // imported template names and IDs (hashed) (gofpdi) + importedTplIds map[string]int // imported template ids hash to object id int (gofpdi) buffer fmtBuffer // buffer holding in-memory PDF pages []*bytes.Buffer // slice[page] of page content; 1-based state int // current document state diff --git a/doc.go b/doc.go index 2d6f49b..3295200 100644 --- a/doc.go +++ b/doc.go @@ -253,7 +253,8 @@ encoding and decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word -spacing. Artem Korotkiy added support of UTF-8 fonts. +spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added +support for imported objects and templates. Roadmap diff --git a/doc/document.md b/doc/document.md index 33f5dac..de39656 100644 --- a/doc/document.md +++ b/doc/document.md @@ -226,7 +226,7 @@ decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of -UTF-8 fonts. +UTF-8 fonts. Dave Barnes added support for imported objects and templates. ## Roadmap diff --git a/fpdf.go b/fpdf.go index d3366ce..e381459 100644 --- a/fpdf.go +++ b/fpdf.go @@ -85,6 +85,10 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) f.diffs = make([]string, 0, 8) f.templates = make(map[string]Template) f.templateObjects = make(map[string]int) + f.importedObjs = make(map[string][]byte, 0) + f.importedObjPos = make(map[string]map[int]string, 0) + f.importedTplObjs = make(map[string]string) + f.importedTplIds = make(map[string]int, 0) f.images = make(map[string]*ImageInfoType) f.pageLinks = make([][]linkType, 0, 8) f.pageLinks = append(f.pageLinks, make([]linkType, 0, 0)) // pageLinks[0] is unused (1-based) @@ -3101,6 +3105,86 @@ func (f *Fpdf) GetImageInfo(imageStr string) (info *ImageInfoType) { return f.images[imageStr] } +// Import objects from gofpdi into current document +func (f *Fpdf) ImportObjects(objs map[string][]byte) { + for k, v := range objs { + f.importedObjs[k] = v + } +} + +// Import object hash positions from gofpdi +func (f *Fpdf) ImportObjPos(objPos map[string]map[int]string) { + for k, v := range objPos { + f.importedObjPos[k] = v + } +} + +// putImportedTemplates writes the imported template objects to the PDF +func (f *Fpdf) putImportedTemplates() { + nOffset := f.n + 1 + + // keep track of list of sha1 hashes (to be replaced with integers) + objsIdHash := make([]string, len(f.importedObjs)) + + // actual object data with new id + objsIdData := make([][]byte, len(f.importedObjs)) + + // Populate hash slice and data slice + i := 0 + for k, v := range f.importedObjs { + objsIdHash[i] = k + objsIdData[i] = v + + i++ + } + + // Populate a lookup table to get an object id from a hash + hashToObjId := make(map[string]int, len(f.importedObjs)) + for i = 0; i < len(objsIdHash); i++ { + hashToObjId[objsIdHash[i]] = i + nOffset + } + + // Now, replace hashes inside data with %040d object id + for i = 0; i < len(objsIdData); i++ { + // get hash + hash := objsIdHash[i] + + for pos, h := range f.importedObjPos[hash] { + // Convert object id into a 40 character string padded with spaces + objIdPadded := fmt.Sprintf("%40s", fmt.Sprintf("%d", hashToObjId[h])) + + // Convert objIdPadded into []byte + objIdBytes := []byte(objIdPadded) + + // Replace sha1 hash with object id padded + for j := pos; j < pos+40; j++ { + objsIdData[i][j] = objIdBytes[j-pos] + } + } + + // Save objsIdHash so that procset dictionary has the correct object ids + f.importedTplIds[hash] = i + nOffset + } + + // Now, put objects + for i = 0; i < len(objsIdData); i++ { + f.newobj() + f.out(string(objsIdData[i])) + } +} + +// Use imported template from gofpdi - draws imported PDF page onto page +func (f *Fpdf) UseImportedTemplate(tplName string, scaleX float64, scaleY float64, tX float64, tY float64) { + f.outf("q 0 J 1 w 0 j 0 G 0 g q %.4F 0 0 %.4F %.4F %.4F cm %s Do Q Q\n", scaleX*f.k, scaleY*f.k, tX*f.k, (tY+f.h)*f.k, tplName) +} + +// Import gofpdi template names into importedTplObjs - to be included in the procset dictionary +func (f *Fpdf) ImportTemplates(tpls map[string]string) { + for tplName, tplId := range tpls { + f.importedTplObjs[tplName] = tplId + } +} + // GetConversionRatio returns the conversion ratio based on the unit given when // creating the PDF. func (f *Fpdf) GetConversionRatio() float64 { @@ -4173,6 +4257,12 @@ func (f *Fpdf) putxobjectdict() { } } } + { + for tplName, objID := range f.importedTplObjs { + // here replace obj id hash with n + f.outf("%s %d 0 R", tplName, f.importedTplIds[objID]) + } + } } func (f *Fpdf) putresourcedict() { @@ -4288,6 +4378,7 @@ func (f *Fpdf) putresources() { } f.putimages() f.putTemplates() + f.putImportedTemplates() // gofpdi // Resource dictionary f.offsets[2] = f.buffer.Len() f.out("2 0 obj") -- cgit v1.2.1-24-ge1ad From ce8a12ff5655c57989b925abc0b8a3a1e6535d59 Mon Sep 17 00:00:00 2001 From: Dave Barnes Date: Wed, 15 May 2019 11:25:39 -0500 Subject: Clean up code based on jung-kurt's feedback. --- contrib/gofpdi/gofpdi.go | 6 +++--- def.go | 2 +- fpdf.go | 50 ++++++++++++++++++++++++------------------------ 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go index c1f3df8..d1b98e9 100644 --- a/contrib/gofpdi/gofpdi.go +++ b/contrib/gofpdi/gofpdi.go @@ -29,10 +29,10 @@ func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { // Import objects into current pdf document // Unordered means that the objects will be returned with a sha1 hash instead of an integer // The objects themselves may have references to other hashes which will be replaced in ImportObjects() - tplObjIds := fpdi.PutFormXobjectsUnordered() + tplObjIDs := fpdi.PutFormXobjectsUnordered() // Set template names and ids (hashes) in gofpdf - f.ImportTemplates(tplObjIds) + f.ImportTemplates(tplObjIDs) // Get a map[string]string of the imported objects. // The map keys will be the ID of each object. @@ -41,7 +41,7 @@ func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { // Import gofpdi objects into gofpdf f.ImportObjects(imported) - // Get a map[string]map[int]string of the object hashes and their positions within each object, + // Get a map[string]map[int]string of the object hashes and their positions within each object, // to be replaced with object ids (integers). importedObjPos := fpdi.GetImportedObjHashPos() diff --git a/def.go b/def.go index f725f01..efa573e 100644 --- a/def.go +++ b/def.go @@ -507,7 +507,7 @@ type Fpdf struct { importedObjs map[string][]byte // imported template objects (gofpdi) importedObjPos map[string]map[int]string // imported template objects hashes and their positions (gofpdi) importedTplObjs map[string]string // imported template names and IDs (hashed) (gofpdi) - importedTplIds map[string]int // imported template ids hash to object id int (gofpdi) + importedTplIDs map[string]int // imported template ids hash to object id int (gofpdi) buffer fmtBuffer // buffer holding in-memory PDF pages []*bytes.Buffer // slice[page] of page content; 1-based state int // current document state diff --git a/fpdf.go b/fpdf.go index e381459..666f97f 100644 --- a/fpdf.go +++ b/fpdf.go @@ -88,7 +88,7 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) f.importedObjs = make(map[string][]byte, 0) f.importedObjPos = make(map[string]map[int]string, 0) f.importedTplObjs = make(map[string]string) - f.importedTplIds = make(map[string]int, 0) + f.importedTplIDs = make(map[string]int, 0) f.images = make(map[string]*ImageInfoType) f.pageLinks = make([][]linkType, 0, 8) f.pageLinks = append(f.pageLinks, make([]linkType, 0, 0)) // pageLinks[0] is unused (1-based) @@ -3105,14 +3105,14 @@ func (f *Fpdf) GetImageInfo(imageStr string) (info *ImageInfoType) { return f.images[imageStr] } -// Import objects from gofpdi into current document +// ImportObjects imports objects from gofpdi into current document func (f *Fpdf) ImportObjects(objs map[string][]byte) { for k, v := range objs { f.importedObjs[k] = v } } -// Import object hash positions from gofpdi +// ImportObjPos imports object hash positions from gofpdi func (f *Fpdf) ImportObjPos(objPos map[string]map[int]string) { for k, v := range objPos { f.importedObjPos[k] = v @@ -3124,64 +3124,64 @@ func (f *Fpdf) putImportedTemplates() { nOffset := f.n + 1 // keep track of list of sha1 hashes (to be replaced with integers) - objsIdHash := make([]string, len(f.importedObjs)) + objsIDHash := make([]string, len(f.importedObjs)) // actual object data with new id - objsIdData := make([][]byte, len(f.importedObjs)) + objsIDData := make([][]byte, len(f.importedObjs)) // Populate hash slice and data slice i := 0 for k, v := range f.importedObjs { - objsIdHash[i] = k - objsIdData[i] = v + objsIDHash[i] = k + objsIDData[i] = v i++ } // Populate a lookup table to get an object id from a hash - hashToObjId := make(map[string]int, len(f.importedObjs)) - for i = 0; i < len(objsIdHash); i++ { - hashToObjId[objsIdHash[i]] = i + nOffset + hashToObjID := make(map[string]int, len(f.importedObjs)) + for i = 0; i < len(objsIDHash); i++ { + hashToObjID[objsIDHash[i]] = i + nOffset } // Now, replace hashes inside data with %040d object id - for i = 0; i < len(objsIdData); i++ { + for i = 0; i < len(objsIDData); i++ { // get hash - hash := objsIdHash[i] + hash := objsIDHash[i] for pos, h := range f.importedObjPos[hash] { // Convert object id into a 40 character string padded with spaces - objIdPadded := fmt.Sprintf("%40s", fmt.Sprintf("%d", hashToObjId[h])) + objIDPadded := fmt.Sprintf("%40s", fmt.Sprintf("%d", hashToObjID[h])) - // Convert objIdPadded into []byte - objIdBytes := []byte(objIdPadded) + // Convert objIDPadded into []byte + objIDBytes := []byte(objIDPadded) // Replace sha1 hash with object id padded for j := pos; j < pos+40; j++ { - objsIdData[i][j] = objIdBytes[j-pos] + objsIDData[i][j] = objIDBytes[j-pos] } } - // Save objsIdHash so that procset dictionary has the correct object ids - f.importedTplIds[hash] = i + nOffset + // Save objsIDHash so that procset dictionary has the correct object ids + f.importedTplIDs[hash] = i + nOffset } // Now, put objects - for i = 0; i < len(objsIdData); i++ { + for i = 0; i < len(objsIDData); i++ { f.newobj() - f.out(string(objsIdData[i])) + f.out(string(objsIDData[i])) } } -// Use imported template from gofpdi - draws imported PDF page onto page +// UseImportedTemplate uses imported template from gofpdi - draws imported PDF page onto page func (f *Fpdf) UseImportedTemplate(tplName string, scaleX float64, scaleY float64, tX float64, tY float64) { f.outf("q 0 J 1 w 0 j 0 G 0 g q %.4F 0 0 %.4F %.4F %.4F cm %s Do Q Q\n", scaleX*f.k, scaleY*f.k, tX*f.k, (tY+f.h)*f.k, tplName) } -// Import gofpdi template names into importedTplObjs - to be included in the procset dictionary +// ImportTemplates imports gofpdi template names into importedTplObjs - to be included in the procset dictionary func (f *Fpdf) ImportTemplates(tpls map[string]string) { - for tplName, tplId := range tpls { - f.importedTplObjs[tplName] = tplId + for tplName, tplID := range tpls { + f.importedTplObjs[tplName] = tplID } } @@ -4260,7 +4260,7 @@ func (f *Fpdf) putxobjectdict() { { for tplName, objID := range f.importedTplObjs { // here replace obj id hash with n - f.outf("%s %d 0 R", tplName, f.importedTplIds[objID]) + f.outf("%s %d 0 R", tplName, f.importedTplIDs[objID]) } } } -- cgit v1.2.1-24-ge1ad From eca8e8f3216d7e07f60db6cea8fd5067d99e3c27 Mon Sep 17 00:00:00 2001 From: Kurt Date: Wed, 15 May 2019 12:43:04 -0400 Subject: Add PDF import as feature in documentation --- README.md | 1 + doc.go | 2 ++ doc/document.md | 1 + 3 files changed, 4 insertions(+) diff --git a/README.md b/README.md index fdd8980..811bbc3 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ support for text, drawing and images. - Templates - Barcodes - Charting facility + - Import PDFs as templates gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. diff --git a/doc.go b/doc.go index 3295200..6ad0461 100644 --- a/doc.go +++ b/doc.go @@ -42,6 +42,8 @@ Features - Charting facility +- Import PDFs as templates + gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. diff --git a/doc/document.md b/doc/document.md index de39656..fa544af 100644 --- a/doc/document.md +++ b/doc/document.md @@ -29,6 +29,7 @@ text, drawing and images. * Templates * Barcodes * Charting facility +* Import PDFs as templates gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms. -- cgit v1.2.1-24-ge1ad From e4895cb2e4a6b49e241d7668740c1a557ef4b8c5 Mon Sep 17 00:00:00 2001 From: Kurt Date: Wed, 15 May 2019 13:21:03 -0400 Subject: Add split line table PDF to reference directory --- pdf/reference/Fpdf_SplitLines_tables.pdf | 159 +++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 pdf/reference/Fpdf_SplitLines_tables.pdf diff --git a/pdf/reference/Fpdf_SplitLines_tables.pdf b/pdf/reference/Fpdf_SplitLines_tables.pdf new file mode 100644 index 0000000..f0d3635 --- /dev/null +++ b/pdf/reference/Fpdf_SplitLines_tables.pdf @@ -0,0 +1,159 @@ +%PDF-1.3 +3 0 obj +<> +endobj +4 0 obj +<> +stream +0 J +0 j +0.57 w +BT /F0a76705d18e0494dd24cb573e53aa0a8c710ec99 14.00 Tf ET +0.000 G +0.000 g +BT /F0a76705d18e0494dd24cb573e53aa0a8c710ec99 14.00 Tf ET +0.251 g +42.52 799.37 170.08 -28.35 re B q 0.878 g BT 96.83 781.00 Td (Column A)Tj ET Q +212.60 799.37 170.08 -28.35 re B q 0.878 g BT 266.91 781.00 Td (Column B)Tj ET Q +382.68 799.37 170.08 -28.35 re B q 0.878 g BT 436.60 781.00 Td (Column C)Tj ET Q +1.000 g +42.52 771.02 170.08 -260.79 re S +q 0.094 g BT 51.02 675.41 Td (Lorem ipsum dolor sit)Tj ET Q +q 0.094 g BT 51.02 659.82 Td (amet, consectetur)Tj ET Q +q 0.094 g BT 51.02 644.23 Td (adipisicing elit, sed do)Tj ET Q +q 0.094 g BT 51.02 628.63 Td (eiusmod tempor)Tj ET Q +q 0.094 g BT 51.02 613.04 Td (incididunt ut labore et)Tj ET Q +q 0.094 g BT 51.02 597.45 Td (dolore magna aliqua.)Tj ET Q +212.60 771.02 170.08 -260.79 re S +q 0.094 g BT 230.73 714.38 Td (Lorem ipsum dolor sit)Tj ET Q +q 0.094 g BT 242.00 698.79 Td (amet, consectetur)Tj ET Q +q 0.094 g BT 229.16 683.20 Td (adipisicing elit, sed do)Tj ET Q +q 0.094 g BT 247.45 667.61 Td (eiusmod tempor)Tj ET Q +q 0.094 g BT 231.10 652.02 Td (incididunt ut labore et)Tj ET Q +q 0.094 g BT 223.33 636.43 Td (dolore magna aliqua. Ut)Tj ET Q +q 0.094 g BT 225.68 620.84 Td (enim ad minim veniam,)Tj ET Q +q 0.094 g BT 221.77 605.25 Td (quis nostrud exercitation)Tj ET Q +q 0.094 g BT 230.73 589.66 Td (ullamco laboris nisi ut)Tj ET Q +q 0.094 g BT 225.66 574.07 Td (aliquip ex ea commodo)Tj ET Q +q 0.094 g BT 263.39 558.48 Td (consequat.)Tj ET Q +382.68 771.02 170.08 -260.79 re S +q 0.094 g BT 410.44 753.36 Td (Lorem ipsum dolor sit)Tj ET Q +q 0.094 g BT 432.98 737.77 Td (amet, consectetur)Tj ET Q +q 0.094 g BT 407.30 722.18 Td (adipisicing elit, sed do)Tj ET Q +q 0.094 g BT 443.89 706.59 Td (eiusmod tempor)Tj ET Q +q 0.094 g BT 411.18 691.00 Td (incididunt ut labore et)Tj ET Q +q 0.094 g BT 395.63 675.41 Td (dolore magna aliqua. Ut)Tj ET Q +q 0.094 g BT 400.33 659.82 Td (enim ad minim veniam,)Tj ET Q +q 0.094 g BT 392.52 644.23 Td (quis nostrud exercitation)Tj ET Q +q 0.094 g BT 410.44 628.63 Td (ullamco laboris nisi ut)Tj ET Q +q 0.094 g BT 400.30 613.04 Td (aliquip ex ea commodo)Tj ET Q +q 0.094 g BT 412.74 597.45 Td (consequat. Duis aute)Tj ET Q +q 0.094 g BT 466.45 581.86 Td (irure dolor in)Tj ET Q +q 0.094 g BT 446.21 566.27 Td (reprehenderit in)Tj ET Q +q 0.094 g BT 425.20 550.68 Td (voluptate velit esse)Tj ET Q +q 0.094 g BT 408.09 535.09 Td (cillum dolore eu fugiat)Tj ET Q +q 0.094 g BT 459.44 519.50 Td (nulla pariatur.)Tj ET Q +42.52 510.24 170.08 -338.74 re S +q 0.094 g BT 51.02 492.57 Td (Lorem ipsum dolor sit)Tj ET Q +q 0.094 g BT 51.02 476.98 Td (amet, consectetur)Tj ET Q +q 0.094 g BT 51.02 461.39 Td (adipisicing elit, sed do)Tj ET Q +q 0.094 g BT 51.02 445.80 Td (eiusmod tempor)Tj ET Q +q 0.094 g BT 51.02 430.21 Td (incididunt ut labore et)Tj ET Q +q 0.094 g BT 51.02 414.62 Td (dolore magna aliqua. Ut)Tj ET Q +q 0.094 g BT 51.02 399.03 Td (enim ad minim veniam,)Tj ET Q +q 0.094 g BT 51.02 383.44 Td (quis nostrud exercitation)Tj ET Q +q 0.094 g BT 51.02 367.85 Td (ullamco laboris nisi ut)Tj ET Q +q 0.094 g BT 51.02 352.26 Td (aliquip ex ea commodo)Tj ET Q +q 0.094 g BT 51.02 336.67 Td (consequat. Duis aute)Tj ET Q +q 0.094 g BT 51.02 321.08 Td (irure dolor in)Tj ET Q +q 0.094 g BT 51.02 305.49 Td (reprehenderit in)Tj ET Q +q 0.094 g BT 51.02 289.89 Td (voluptate velit esse)Tj ET Q +q 0.094 g BT 51.02 274.30 Td (cillum dolore eu fugiat)Tj ET Q +q 0.094 g BT 51.02 258.71 Td (nulla pariatur. Excepteur)Tj ET Q +q 0.094 g BT 51.02 243.12 Td (sint occaecat cupidatat)Tj ET Q +q 0.094 g BT 51.02 227.53 Td (non proident, sunt in)Tj ET Q +q 0.094 g BT 51.02 211.94 Td (culpa qui officia)Tj ET Q +q 0.094 g BT 51.02 196.35 Td (deserunt mollit anim id)Tj ET Q +q 0.094 g BT 51.02 180.76 Td (est laborum.)Tj ET Q +212.60 510.24 170.08 -338.74 re S +q 0.094 g BT 230.73 375.64 Td (Lorem ipsum dolor sit)Tj ET Q +q 0.094 g BT 242.00 360.05 Td (amet, consectetur)Tj ET Q +q 0.094 g BT 229.16 344.46 Td (adipisicing elit, sed do)Tj ET Q +q 0.094 g BT 247.45 328.87 Td (eiusmod tempor)Tj ET Q +q 0.094 g BT 231.10 313.28 Td (incididunt ut labore et)Tj ET Q +q 0.094 g BT 232.27 297.69 Td (dolore magna aliqua.)Tj ET Q +382.68 510.24 170.08 -338.74 re S +q 0.094 g BT 410.44 414.62 Td (Lorem ipsum dolor sit)Tj ET Q +q 0.094 g BT 432.98 399.03 Td (amet, consectetur)Tj ET Q +q 0.094 g BT 407.30 383.44 Td (adipisicing elit, sed do)Tj ET Q +q 0.094 g BT 443.89 367.85 Td (eiusmod tempor)Tj ET Q +q 0.094 g BT 411.18 352.26 Td (incididunt ut labore et)Tj ET Q +q 0.094 g BT 395.63 336.67 Td (dolore magna aliqua. Ut)Tj ET Q +q 0.094 g BT 400.33 321.08 Td (enim ad minim veniam,)Tj ET Q +q 0.094 g BT 392.52 305.49 Td (quis nostrud exercitation)Tj ET Q +q 0.094 g BT 410.44 289.89 Td (ullamco laboris nisi ut)Tj ET Q +q 0.094 g BT 400.30 274.30 Td (aliquip ex ea commodo)Tj ET Q +q 0.094 g BT 475.76 258.71 Td (consequat.)Tj ET Q + +endstream +endobj +1 0 obj +<> +endobj +5 0 obj +<> +endobj +2 0 obj +<< +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +/Font << +/F0a76705d18e0494dd24cb573e53aa0a8c710ec99 5 0 R +>> +/XObject << +>> +/ColorSpace << +>> +>> +endobj +6 0 obj +<< +/Producer (FPDF 1.7) +/CreationDate (D:20000101000000) +>> +endobj +7 0 obj +<< +/Type /Catalog +/Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000004984 00000 n +0000005167 00000 n +0000000009 00000 n +0000000087 00000 n +0000005071 00000 n +0000005328 00000 n +0000005403 00000 n +trailer +<< +/Size 8 +/Root 7 0 R +/Info 6 0 R +>> +startxref +5452 +%%EOF -- cgit v1.2.1-24-ge1ad From 5f4e2f65402b9aa611f93b2fa14ea69bf7b26d2d Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 18 May 2019 08:08:21 -0400 Subject: Generalize awk script that produces doc.go --- Makefile | 2 +- contrib/gofpdi/gofpdi.go | 11 ++++++----- doc/go.awk | 12 +++--------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index f2590bd..90624c5 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ doc/index.html : doc/document.md doc/html.txt --metadata pagetitle="GoFPDF Document Generator" < $< > $@ doc.go : doc/document.md doc/go.awk - pandoc --read=markdown --write=plain $< | awk -f doc/go.awk > $@ + pandoc --read=markdown --write=plain $< | awk --assign=package_name=gofpdf --file=doc/go.awk > $@ gofmt -s -w $@ build : diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go index d1b98e9..b951ea3 100644 --- a/contrib/gofpdi/gofpdi.go +++ b/contrib/gofpdi/gofpdi.go @@ -17,8 +17,9 @@ type gofpdiPdf interface { SetError(err error) } -// Imports a page of a PDF file with the specified box (/MediaBox, /TrimBox, /ArtBox, /CropBox, or /BleedBox). -// Returns a template id that can be used with UseImportedTemplate to draw the template onto the page. +// ImportPage imports a page of a PDF file with the specified box (/MediaBox, +// /TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id that can +// be used with UseImportedTemplate to draw the template onto the page. func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { // Set source file for fpdi fpdi.SetSourceFile(sourceFile) @@ -51,9 +52,9 @@ func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { return tpl } -// Draw the template onto the page at x,y -// If w is 0, the template will be scaled to fit based on h -// If h is 0, the template will be scaled to fit based on w +// UseImportedTemplate draws the template onto the page at x,y. If w is 0, the +// template will be scaled to fit based on h. If h is 0, the template will be +// scaled to fit based on w. func UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) { // Get values from fpdi tplName, scaleX, scaleY, tX, tY := fpdi.UseTemplate(tplid, x, y, w, h) diff --git a/doc/go.awk b/doc/go.awk index a325362..bcd4a7c 100644 --- a/doc/go.awk +++ b/doc/go.awk @@ -1,12 +1,6 @@ -BEGIN { - show = 0 - print "/*" -} +BEGIN { show = 0 ; print "/*" } -/^\-/ { - trim = 1 - print "" -} +/^\-/ { trim = 1 ; print "" } /^Package/ { show = 1 } @@ -16,4 +10,4 @@ trim { sub("^ +", "", $0) } show { print $0 } -END { print "*/\npackage gofpdf" } +END { print "*/\npackage " package_name } -- cgit v1.2.1-24-ge1ad From 290b8c334e0f9ce3f5fc95bb70002b13d3300bb5 Mon Sep 17 00:00:00 2001 From: Justin Schlechte Date: Wed, 22 May 2019 11:24:02 -0500 Subject: maintain precision of desired w & h of barcodes This fixes an issue with barcode scaling that limited barcode sizes to integer multiples of the pdf's unit. --- contrib/barcode/barcode.go | 10 +++++++--- contrib/barcode/barcode_test.go | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/contrib/barcode/barcode.go b/contrib/barcode/barcode.go index ad84fe5..7e0ac0d 100644 --- a/contrib/barcode/barcode.go +++ b/contrib/barcode/barcode.go @@ -93,13 +93,17 @@ func printBarcode(pdf barcodePdf, code string, x, y float64, w, h *float64, flow } } + scaleToWidthF := float64(scaleToWidth) + scaleToHeightF := float64(scaleToHeight) + if w != nil { - scaleToWidth = int(*w) + scaleToWidthF = *w } if h != nil { - scaleToHeight = int(*h) + scaleToHeightF = *h } - pdf.Image(bname, x, y, float64(scaleToWidth), float64(scaleToHeight), flow, "jpg", 0, "") + + pdf.Image(bname, x, y, scaleToWidthF, scaleToHeightF, flow, "jpg", 0, "") } diff --git a/contrib/barcode/barcode_test.go b/contrib/barcode/barcode_test.go index 2b402a3..066ac41 100644 --- a/contrib/barcode/barcode_test.go +++ b/contrib/barcode/barcode_test.go @@ -199,3 +199,24 @@ func TestGetUnscaledBarcodeDimensions(t *testing.T) { // Output: // Successfully generated ../../pdf/contrib_barcode_GetBarcodeDimensions.pdf } + +// TestBarcodeNonIntegerScalingFactors shows that the barcode may be scaled to non-integer sizes +func TestBarcodeNonIntegerScalingFactors(t *testing.T) { + pdf := gofpdf.New("L", "in", "A4", "") + pdf.SetFont("Helvetica", "", 12) + pdf.SetFillColor(200, 200, 220) + pdf.AddPage() + + key := barcode.RegisterQR(pdf, "qrcode", qr.H, qr.Unicode) + var scale float64 = 1.5 + barcode.BarcodeUnscalable(pdf, key, 0.5, 0.5, &scale, &scale, false) + + pdf.SetDrawColor(255, 0, 0) + pdf.Line(0.5, 0.5, 0.5+scale, 0.5+scale) + + fileStr := example.Filename("contrib_barcode_BarcodeScaling") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated ../../pdf/contrib_barcode_BarcodeScaling.pdf +} -- cgit v1.2.1-24-ge1ad From 25a362ddc90abe3b4786965ac8b38b143694519d Mon Sep 17 00:00:00 2001 From: Callum Li Date: Mon, 10 Jun 2019 13:52:42 +1200 Subject: Improve write performance --- fpdf.go | 4 ++-- go.mod | 4 ++++ go.sum | 5 ++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/fpdf.go b/fpdf.go index 3e4188c..e4b4261 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2537,7 +2537,7 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill if f.isCurrentUTF8 { c = []rune(s)[i] } else { - c = rune([]byte(s)[i]) + c = rune(byte(s[i])) } if c == '\n' { // Explicit line break @@ -2674,7 +2674,7 @@ func (f *Fpdf) write(h float64, txtStr string, link int, linkStr string) { if f.isCurrentUTF8 { c = []rune(s)[i] } else { - c = rune([]byte(s)[i]) + c = rune(byte(s[i])) } if c == '\n' { // Explicit line break diff --git a/go.mod b/go.mod index 663e024..2610432 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,10 @@ go 1.12 require ( github.com/boombuler/barcode v1.0.0 + github.com/phpdave11/gofpdi v1.0.3 + github.com/pkg/errors v0.8.1 // indirect github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec ) + +replace github.com/jung-kurt/gopdf => ./ diff --git a/go.sum b/go.sum index 8848810..1ed062b 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,10 @@ -github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/phpdave11/gofpdi v1.0.3/go.mod h1:B7ryN7q4MLItB8BDM5PJAplblJegAAcaI98viOZUihg= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 h1:nlG4Wa5+minh3S9LVFtNoY+GVRiudA2e3EVfcCi3RCA= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec h1:arXJwtMuk5vqI1NHX0UTnNw977rYk5Sl4jQqHj+hun4= golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -- cgit v1.2.1-24-ge1ad From db11935940567444dd230820da9a14acef0c96c2 Mon Sep 17 00:00:00 2001 From: JUN JIE NAN Date: Wed, 12 Jun 2019 14:53:58 +0800 Subject: Added UTF8CutFont With function `UTF8CutFont`, customized ttf font file(usually with small size) can be generated via gofpdf. --- utf8fontfile.go | 16 +++ utf8fontfile_test.go | 380 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 396 insertions(+) create mode 100644 utf8fontfile_test.go diff --git a/utf8fontfile.go b/utf8fontfile.go index 794bae2..07cf169 100644 --- a/utf8fontfile.go +++ b/utf8fontfile.go @@ -1138,3 +1138,19 @@ func keySortArrayRangeMap(s map[int][]int) []int { sort.Ints(keys) return keys } + +// UTF8CutFont cuts a set in cutset and returns the customized font bytes +// Parameters: +// in - the ttf bytes in, +// cutset - the cutset runes in string, +// Returns: +// out - the ttf bytes out, +func UTF8CutFont(in []byte, cutset string) (out []byte) { + f := newUTF8Font(&fileReader{readerPosition: 0, array: in}) + runes := map[int]int{} + for i, r := range cutset { + runes[i] = int(r) + } + out = f.GenerateСutFont(runes) + return +} diff --git a/utf8fontfile_test.go b/utf8fontfile_test.go new file mode 100644 index 0000000..0d808be --- /dev/null +++ b/utf8fontfile_test.go @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2013-2019 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( + "io/ioutil" + "os" + "testing" +) + +var testFontData = []byte{ + 0, 1, 0, 0, 0, 10, 0, 128, 0, 3, 0, 32, 79, 83, 47, 50, 159, + 99, 23, 238, 0, 0, 0, 172, 0, 0, 0, 96, 99, 109, 97, 112, 206, + 122, 158, 30, 0, 0, 1, 12, 0, 0, 0, 98, 103, 108, 121, 102, 42, + 32, 194, 143, 0, 0, 1, 112, 0, 0, 4, 76, 104, 101, 97, 100, 17, + 101, 20, 54, 0, 0, 5, 188, 0, 0, 0, 54, 104, 104, 101, 97, 12, + 17, 9, 201, 0, 0, 5, 244, 0, 0, 0, 36, 104, 109, 116, 120, 27, + 88, 2, 101, 0, 0, 6, 24, 0, 0, 0, 28, 108, 111, 99, 97, 3, 252, + 5, 12, 0, 0, 6, 52, 0, 0, 0, 16, 109, 97, 120, 112, 0, 49, 1, + 111, 0, 0, 6, 68, 0, 0, 0, 32, 110, 97, 109, 101, 33, 238, 45, + 114, 0, 0, 6, 100, 0, 0, 13, 229, 112, 111, 115, 116, 255, 134, + 0, 50, 0, 0, 20, 76, 0, 0, 0, 32, 0, 3, 3, 211, 1, 144, 0, 5, + 0, 0, 2, 138, 2, 88, 0, 0, 0, 75, 2, 138, 2, 88, 0, 0, 1, 94, + 0, 50, 1, 69, 0, 0, 2, 11, 5, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, + 3, 43, 223, 60, 16, 0, 0, 0, 22, 0, 0, 0, 0, 71, 79, 79, 71, + 0, 64, 0, 0, 255, 255, 3, 112, 255, 136, 0, 0, 4, 136, 1, 64, + 96, 46, 1, 7, 0, 0, 0, 0, 2, 31, 2, 221, 0, 0, 0, 32, 0, 6, 0, + 0, 0, 1, 0, 3, 0, 1, 0, 0, 0, 12, 0, 4, 0, 80, 0, 0, 0, 14, 0, + 8, 0, 2, 0, 6, 78, 45, 89, 125, 96, 168, 101, 135, 255, 1, 255, + 12, 255, 255, 0, 0, 78, 45, 89, 125, 96, 168, 101, 135, 255, + 1, 255, 12, 255, 255, 177, 212, 166, 133, 159, 91, 154, 125, + 1, 5, 0, 249, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 2, 0, 3, 0, 4, 0, 6, 0, 5, 0, 0, 0, 0, 0, 5, 0, 100, + 255, 136, 3, 132, 3, 112, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, + 0, 23, 17, 33, 17, 1, 1, 33, 1, 1, 17, 1, 33, 1, 1, 17, 1, 100, + 3, 32, 254, 112, 1, 62, 253, 132, 1, 94, 1, 62, 253, 100, 2, + 124, 254, 194, 254, 162, 1, 62, 120, 3, 232, 252, 24, 2, 29, + 1, 153, 254, 62, 254, 103, 3, 50, 252, 165, 1, 153, 1, 194, 252, + 206, 1, 153, 0, 0, 0, 3, 0, 100, 255, 180, 3, 131, 3, 69, 0, + 3, 0, 7, 0, 23, 0, 0, 1, 33, 17, 33, 1, 33, 17, 33, 37, 33, 17, + 35, 53, 33, 17, 35, 17, 33, 21, 35, 17, 33, 53, 51, 2, 24, 1, + 31, 254, 225, 254, 149, 1, 30, 254, 226, 1, 107, 1, 107, 76, + 254, 225, 77, 254, 226, 73, 1, 103, 77, 1, 65, 1, 9, 254, 247, + 1, 9, 73, 254, 44, 57, 254, 188, 1, 68, 62, 1, 217, 178, 0, 3, + 0, 30, 255, 178, 3, 188, 3, 68, 0, 8, 0, 45, 0, 80, 0, 0, 1, + 35, 6, 6, 7, 22, 23, 54, 54, 55, 23, 6, 6, 7, 22, 22, 23, 7, + 38, 39, 6, 6, 7, 38, 38, 39, 54, 54, 55, 38, 38, 39, 54, 54, + 55, 35, 53, 51, 54, 54, 55, 23, 6, 6, 7, 51, 5, 21, 35, 17, 20, + 6, 7, 6, 6, 39, 38, 38, 39, 22, 22, 55, 50, 53, 17, 35, 53, 51, + 53, 54, 54, 55, 33, 53, 33, 55, 23, 6, 6, 7, 21, 1, 94, 141, + 13, 31, 16, 60, 55, 31, 44, 43, 45, 12, 52, 41, 36, 60, 20, 50, + 38, 65, 42, 104, 62, 7, 27, 13, 59, 100, 40, 39, 83, 39, 18, + 36, 16, 92, 105, 11, 17, 5, 73, 7, 16, 11, 145, 2, 76, 220, 19, + 23, 23, 75, 58, 4, 16, 8, 44, 74, 11, 22, 231, 231, 38, 77, 31, + 254, 179, 1, 128, 17, 51, 37, 100, 53, 2, 51, 65, 124, 53, 39, + 44, 67, 162, 168, 11, 135, 215, 83, 31, 59, 26, 61, 49, 60, 66, + 98, 35, 14, 35, 10, 29, 95, 64, 33, 62, 26, 54, 141, 76, 69, + 53, 104, 47, 5, 46, 102, 51, 217, 71, 254, 180, 33, 35, 9, 8, + 5, 1, 16, 39, 16, 1, 1, 1, 19, 1, 76, 71, 114, 32, 90, 43, 69, + 4, 37, 55, 118, 46, 96, 0, 9, 0, 38, 255, 198, 3, 174, 3, 71, + 0, 21, 0, 31, 0, 41, 0, 51, 0, 69, 0, 79, 0, 95, 0, 118, 0, 128, + 0, 0, 1, 33, 6, 7, 38, 38, 39, 54, 54, 55, 23, 6, 7, 33, 55, + 23, 6, 6, 7, 39, 54, 54, 7, 55, 30, 2, 23, 7, 46, 2, 3, 7, 46, + 2, 39, 55, 30, 2, 3, 23, 6, 6, 7, 38, 38, 39, 54, 54, 55, 17, + 20, 6, 7, 6, 6, 35, 38, 38, 39, 22, 50, 55, 50, 54, 53, 17, 1, + 39, 62, 2, 55, 23, 14, 2, 19, 23, 6, 6, 7, 17, 35, 17, 6, 6, + 7, 38, 38, 39, 54, 54, 19, 51, 50, 54, 54, 55, 22, 22, 23, 14, + 2, 35, 35, 34, 38, 38, 53, 53, 51, 21, 20, 22, 37, 55, 30, 2, + 23, 7, 46, 2, 3, 77, 254, 136, 47, 57, 9, 35, 12, 51, 83, 25, + 69, 15, 18, 1, 118, 12, 51, 19, 43, 19, 63, 11, 25, 91, 60, 26, + 49, 40, 11, 64, 11, 39, 47, 150, 62, 12, 46, 56, 27, 57, 28, + 56, 48, 136, 68, 25, 73, 39, 10, 34, 12, 39, 66, 240, 14, 21, + 19, 63, 47, 3, 14, 7, 35, 56, 9, 10, 6, 254, 18, 70, 20, 38, + 32, 11, 67, 13, 31, 35, 137, 66, 18, 45, 25, 72, 23, 49, 24, + 7, 31, 11, 69, 127, 182, 230, 28, 27, 12, 2, 13, 40, 16, 5, 24, + 54, 50, 239, 58, 65, 25, 74, 29, 1, 143, 65, 24, 44, 35, 8, 71, + 7, 33, 42, 2, 166, 78, 56, 10, 29, 8, 44, 130, 70, 17, 37, 38, + 3, 14, 43, 92, 30, 13, 19, 52, 115, 28, 30, 71, 69, 28, 33, 28, + 71, 73, 254, 128, 36, 24, 61, 64, 26, 33, 25, 62, 60, 1, 160, + 19, 59, 112, 38, 9, 26, 7, 35, 99, 134, 254, 219, 28, 30, 8, + 9, 3, 15, 36, 14, 1, 1, 6, 8, 1, 36, 253, 88, 32, 29, 76, 78, + 32, 27, 32, 80, 77, 3, 76, 22, 37, 71, 35, 254, 106, 1, 61, 26, + 48, 20, 11, 37, 10, 52, 155, 253, 23, 16, 50, 50, 10, 15, 3, + 63, 68, 26, 17, 45, 40, 173, 172, 22, 12, 193, 25, 35, 81, 77, + 31, 29, 31, 79, 83, 0, 0, 0, 0, 3, 0, 40, 255, 181, 3, 195, 3, + 74, 0, 7, 0, 14, 0, 41, 0, 0, 1, 7, 38, 38, 39, 55, 22, 22, 23, + 33, 22, 22, 23, 54, 54, 37, 35, 6, 6, 7, 22, 22, 23, 6, 6, 7, + 38, 39, 6, 6, 7, 38, 38, 39, 54, 55, 38, 38, 39, 35, 53, 33, + 2, 66, 81, 9, 42, 23, 77, 23, 45, 141, 254, 88, 39, 109, 70, + 67, 102, 1, 22, 157, 43, 116, 75, 83, 202, 119, 13, 29, 9, 243, + 167, 84, 207, 125, 7, 28, 11, 246, 162, 77, 119, 44, 154, 3, + 128, 2, 177, 26, 31, 89, 37, 22, 35, 86, 133, 95, 169, 71, 68, + 166, 101, 118, 192, 77, 70, 104, 29, 13, 40, 16, 69, 150, 73, + 110, 40, 14, 42, 13, 70, 137, 80, 194, 113, 73, 0, 1, 0, 135, + 255, 149, 1, 74, 0, 235, 0, 18, 0, 0, 23, 39, 54, 54, 55, 6, + 34, 35, 34, 38, 53, 52, 54, 51, 50, 22, 21, 20, 6, 157, 22, 58, + 64, 4, 4, 8, 5, 31, 44, 45, 31, 41, 44, 94, 107, 53, 24, 72, + 51, 1, 36, 35, 35, 37, 62, 53, 81, 118, 0, 0, 0, 2, 0, 170, 255, + 251, 1, 74, 2, 236, 0, 5, 0, 17, 0, 0, 55, 3, 39, 51, 7, 3, 7, + 34, 38, 53, 52, 54, 51, 50, 22, 21, 20, 6, 217, 24, 3, 120, 2, + 25, 33, 33, 47, 47, 33, 33, 47, 47, 242, 1, 132, 118, 118, 254, + 124, 247, 42, 37, 35, 43, 43, 35, 37, 42, 0, 1, 0, 0, 0, 1, 1, + 6, 184, 191, 195, 30, 95, 15, 60, 245, 0, 1, 3, 232, 0, 0, 0, + 0, 209, 164, 13, 252, 0, 0, 0, 0, 217, 37, 193, 92, 252, 22, + 251, 232, 11, 112, 7, 16, 0, 0, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 4, 136, 254, 192, 0, 0, 11, 184, 252, 22, 255, 73, + 11, 112, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 3, 232, 0, 100, 3, 232, 0, 100, 3, 232, 0, 30, 3, 232, 0, 38, + 3, 232, 0, 40, 3, 232, 0, 135, 3, 232, 0, 170, 0, 0, 0, 44, 0, + 88, 0, 212, 1, 158, 1, 230, 2, 6, 2, 38, 0, 0, 0, 0, 0, 7, 1, + 110, 0, 41, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 1, 134, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 74, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 24, 0, 74, 0, 1, 0, 0, 0, + 0, 0, 2, 0, 7, 0, 98, 0, 1, 0, 0, 0, 0, 0, 3, 0, 38, 0, 105, + 0, 1, 0, 0, 0, 0, 0, 4, 0, 24, 0, 74, 0, 1, 0, 0, 0, 0, 0, 5, + 0, 58, 0, 143, 0, 1, 0, 0, 0, 0, 0, 6, 0, 21, 0, 201, 0, 1, 0, + 0, 0, 0, 0, 7, 0, 34, 0, 222, 0, 1, 0, 0, 0, 0, 0, 8, 0, 26, + 1, 0, 0, 1, 0, 0, 0, 0, 0, 9, 0, 195, 1, 26, 0, 1, 0, 0, 0, 0, + 0, 10, 0, 128, 1, 221, 0, 1, 0, 0, 0, 0, 0, 11, 0, 31, 2, 93, + 0, 1, 0, 0, 0, 0, 0, 12, 0, 26, 2, 124, 0, 1, 0, 0, 0, 0, 0, + 13, 1, 75, 2, 150, 0, 1, 0, 0, 0, 0, 0, 14, 0, 26, 3, 225, 0, + 1, 0, 0, 0, 0, 0, 16, 0, 16, 3, 251, 0, 3, 0, 1, 4, 9, 0, 0, + 0, 148, 4, 11, 0, 3, 0, 1, 4, 9, 0, 1, 0, 48, 4, 159, 0, 3, 0, + 1, 4, 9, 0, 2, 0, 14, 4, 207, 0, 3, 0, 1, 4, 9, 0, 3, 0, 76, + 4, 221, 0, 3, 0, 1, 4, 9, 0, 4, 0, 48, 4, 159, 0, 3, 0, 1, 4, + 9, 0, 5, 0, 116, 5, 41, 0, 3, 0, 1, 4, 9, 0, 6, 0, 42, 5, 157, + 0, 3, 0, 1, 4, 9, 0, 7, 0, 68, 5, 199, 0, 3, 0, 1, 4, 9, 0, 8, + 0, 52, 6, 11, 0, 3, 0, 1, 4, 9, 0, 9, 1, 186, 6, 63, 0, 3, 0, + 1, 4, 9, 0, 10, 1, 10, 7, 249, 0, 3, 0, 1, 4, 9, 0, 11, 0, 62, + 9, 3, 0, 3, 0, 1, 4, 9, 0, 12, 0, 52, 9, 65, 0, 3, 0, 1, 4, 9, + 0, 13, 2, 150, 9, 117, 0, 3, 0, 1, 4, 9, 0, 14, 0, 52, 12, 11, + 0, 3, 0, 1, 4, 9, 0, 16, 0, 32, 12, 63, 67, 111, 112, 121, 114, + 105, 103, 104, 116, 32, 169, 32, 50, 48, 49, 52, 44, 32, 50, + 48, 49, 53, 32, 65, 100, 111, 98, 101, 32, 83, 121, 115, 116, + 101, 109, 115, 32, 73, 110, 99, 111, 114, 112, 111, 114, 97, + 116, 101, 100, 32, 40, 104, 116, 116, 112, 58, 47, 47, 119, 119, + 119, 46, 97, 100, 111, 98, 101, 46, 99, 111, 109, 47, 41, 46, + 78, 111, 116, 111, 32, 83, 97, 110, 115, 32, 67, 74, 75, 32, + 83, 67, 32, 82, 101, 103, 117, 108, 97, 114, 82, 101, 103, 117, + 108, 97, 114, 49, 46, 48, 48, 52, 59, 71, 79, 79, 71, 59, 78, + 111, 116, 111, 83, 97, 110, 115, 67, 74, 75, 115, 99, 45, 82, + 101, 103, 117, 108, 97, 114, 59, 65, 68, 79, 66, 69, 86, 101, + 114, 115, 105, 111, 110, 32, 49, 46, 48, 48, 52, 59, 80, 83, + 32, 49, 46, 48, 48, 52, 59, 104, 111, 116, 99, 111, 110, 118, + 32, 49, 46, 48, 46, 56, 50, 59, 109, 97, 107, 101, 111, 116, + 102, 46, 108, 105, 98, 50, 46, 53, 46, 54, 51, 52, 48, 54, 78, + 111, 116, 111, 83, 97, 110, 115, 67, 74, 75, 115, 99, 45, 82, + 101, 103, 117, 108, 97, 114, 78, 111, 116, 111, 32, 105, 115, + 32, 97, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 71, 111, 111, 103, 108, 101, 32, 73, 110, 99, 46, 65, + 100, 111, 98, 101, 32, 83, 121, 115, 116, 101, 109, 115, 32, + 73, 110, 99, 111, 114, 112, 111, 114, 97, 116, 101, 100, 82, + 121, 111, 107, 111, 32, 78, 73, 83, 72, 73, 90, 85, 75, 65, 32, + 40, 107, 97, 110, 97, 32, 38, 32, 105, 100, 101, 111, 103, 114, + 97, 112, 104, 115, 41, 59, 32, 80, 97, 117, 108, 32, 68, 46, + 32, 72, 117, 110, 116, 32, 40, 76, 97, 116, 105, 110, 44, 32, + 71, 114, 101, 101, 107, 32, 38, 32, 67, 121, 114, 105, 108, 108, + 105, 99, 41, 59, 32, 87, 101, 110, 108, 111, 110, 103, 32, 90, + 72, 65, 78, 71, 32, 40, 98, 111, 112, 111, 109, 111, 102, 111, + 41, 59, 32, 83, 97, 110, 100, 111, 108, 108, 32, 67, 111, 109, + 109, 117, 110, 105, 99, 97, 116, 105, 111, 110, 44, 32, 83, 111, + 111, 45, 121, 111, 117, 110, 103, 32, 74, 65, 78, 71, 32, 38, + 32, 74, 111, 111, 45, 121, 101, 111, 110, 32, 75, 65, 78, 71, + 32, 40, 104, 97, 110, 103, 117, 108, 32, 101, 108, 101, 109, + 101, 110, 116, 115, 44, 32, 108, 101, 116, 116, 101, 114, 115, + 32, 38, 32, 115, 121, 108, 108, 97, 98, 108, 101, 115, 41, 68, + 114, 46, 32, 75, 101, 110, 32, 76, 117, 110, 100, 101, 32, 40, + 112, 114, 111, 106, 101, 99, 116, 32, 97, 114, 99, 104, 105, + 116, 101, 99, 116, 44, 32, 103, 108, 121, 112, 104, 32, 115, + 101, 116, 32, 100, 101, 102, 105, 110, 105, 116, 105, 111, 110, + 32, 38, 32, 111, 118, 101, 114, 97, 108, 108, 32, 112, 114, 111, + 100, 117, 99, 116, 105, 111, 110, 41, 59, 32, 77, 97, 115, 97, + 116, 97, 107, 97, 32, 72, 65, 84, 84, 79, 82, 73, 32, 40, 112, + 114, 111, 100, 117, 99, 116, 105, 111, 110, 32, 38, 32, 105, + 100, 101, 111, 103, 114, 97, 112, 104, 32, 101, 108, 101, 109, + 101, 110, 116, 115, 41, 104, 116, 116, 112, 58, 47, 47, 119, + 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, + 47, 103, 101, 116, 47, 110, 111, 116, 111, 47, 104, 116, 116, + 112, 58, 47, 47, 119, 119, 119, 46, 97, 100, 111, 98, 101, 46, + 99, 111, 109, 47, 116, 121, 112, 101, 47, 84, 104, 105, 115, + 32, 70, 111, 110, 116, 32, 83, 111, 102, 116, 119, 97, 114, 101, + 32, 105, 115, 32, 108, 105, 99, 101, 110, 115, 101, 100, 32, + 117, 110, 100, 101, 114, 32, 116, 104, 101, 32, 83, 73, 76, 32, + 79, 112, 101, 110, 32, 70, 111, 110, 116, 32, 76, 105, 99, 101, + 110, 115, 101, 44, 32, 86, 101, 114, 115, 105, 111, 110, 32, + 49, 46, 49, 46, 32, 84, 104, 105, 115, 32, 70, 111, 110, 116, + 32, 83, 111, 102, 116, 119, 97, 114, 101, 32, 105, 115, 32, 100, + 105, 115, 116, 114, 105, 98, 117, 116, 101, 100, 32, 111, 110, + 32, 97, 110, 32, 34, 65, 83, 32, 73, 83, 34, 32, 66, 65, 83, + 73, 83, 44, 32, 87, 73, 84, 72, 79, 85, 84, 32, 87, 65, 82, 82, + 65, 78, 84, 73, 69, 83, 32, 79, 82, 32, 67, 79, 78, 68, 73, 84, + 73, 79, 78, 83, 32, 79, 70, 32, 65, 78, 89, 32, 75, 73, 78, 68, + 44, 32, 101, 105, 116, 104, 101, 114, 32, 101, 120, 112, 114, + 101, 115, 115, 32, 111, 114, 32, 105, 109, 112, 108, 105, 101, + 100, 46, 32, 83, 101, 101, 32, 116, 104, 101, 32, 83, 73, 76, + 32, 79, 112, 101, 110, 32, 70, 111, 110, 116, 32, 76, 105, 99, + 101, 110, 115, 101, 32, 102, 111, 114, 32, 116, 104, 101, 32, + 115, 112, 101, 99, 105, 102, 105, 99, 32, 108, 97, 110, 103, + 117, 97, 103, 101, 44, 32, 112, 101, 114, 109, 105, 115, 115, + 105, 111, 110, 115, 32, 97, 110, 100, 32, 108, 105, 109, 105, + 116, 97, 116, 105, 111, 110, 115, 32, 103, 111, 118, 101, 114, + 110, 105, 110, 103, 32, 121, 111, 117, 114, 32, 117, 115, 101, + 32, 111, 102, 32, 116, 104, 105, 115, 32, 70, 111, 110, 116, + 32, 83, 111, 102, 116, 119, 97, 114, 101, 46, 104, 116, 116, + 112, 58, 47, 47, 115, 99, 114, 105, 112, 116, 115, 46, 115, 105, + 108, 46, 111, 114, 103, 47, 79, 70, 76, 78, 111, 116, 111, 32, + 83, 97, 110, 115, 32, 67, 74, 75, 32, 83, 67, 0, 67, 0, 111, + 0, 112, 0, 121, 0, 114, 0, 105, 0, 103, 0, 104, 0, 116, 0, 32, + 0, 169, 0, 32, 0, 50, 0, 48, 0, 49, 0, 52, 0, 44, 0, 32, 0, 50, + 0, 48, 0, 49, 0, 53, 0, 32, 0, 65, 0, 100, 0, 111, 0, 98, 0, + 101, 0, 32, 0, 83, 0, 121, 0, 115, 0, 116, 0, 101, 0, 109, 0, + 115, 0, 32, 0, 73, 0, 110, 0, 99, 0, 111, 0, 114, 0, 112, 0, + 111, 0, 114, 0, 97, 0, 116, 0, 101, 0, 100, 0, 32, 0, 40, 0, + 104, 0, 116, 0, 116, 0, 112, 0, 58, 0, 47, 0, 47, 0, 119, 0, + 119, 0, 119, 0, 46, 0, 97, 0, 100, 0, 111, 0, 98, 0, 101, 0, + 46, 0, 99, 0, 111, 0, 109, 0, 47, 0, 41, 0, 46, 0, 78, 0, 111, + 0, 116, 0, 111, 0, 32, 0, 83, 0, 97, 0, 110, 0, 115, 0, 32, 0, + 67, 0, 74, 0, 75, 0, 32, 0, 83, 0, 67, 0, 32, 0, 82, 0, 101, + 0, 103, 0, 117, 0, 108, 0, 97, 0, 114, 0, 82, 0, 101, 0, 103, + 0, 117, 0, 108, 0, 97, 0, 114, 0, 49, 0, 46, 0, 48, 0, 48, 0, + 52, 0, 59, 0, 71, 0, 79, 0, 79, 0, 71, 0, 59, 0, 78, 0, 111, + 0, 116, 0, 111, 0, 83, 0, 97, 0, 110, 0, 115, 0, 67, 0, 74, 0, + 75, 0, 115, 0, 99, 0, 45, 0, 82, 0, 101, 0, 103, 0, 117, 0, 108, + 0, 97, 0, 114, 0, 59, 0, 65, 0, 68, 0, 79, 0, 66, 0, 69, 0, 86, + 0, 101, 0, 114, 0, 115, 0, 105, 0, 111, 0, 110, 0, 32, 0, 49, + 0, 46, 0, 48, 0, 48, 0, 52, 0, 59, 0, 80, 0, 83, 0, 32, 0, 49, + 0, 46, 0, 48, 0, 48, 0, 52, 0, 59, 0, 104, 0, 111, 0, 116, 0, + 99, 0, 111, 0, 110, 0, 118, 0, 32, 0, 49, 0, 46, 0, 48, 0, 46, + 0, 56, 0, 50, 0, 59, 0, 109, 0, 97, 0, 107, 0, 101, 0, 111, 0, + 116, 0, 102, 0, 46, 0, 108, 0, 105, 0, 98, 0, 50, 0, 46, 0, 53, + 0, 46, 0, 54, 0, 51, 0, 52, 0, 48, 0, 54, 0, 78, 0, 111, 0, 116, + 0, 111, 0, 83, 0, 97, 0, 110, 0, 115, 0, 67, 0, 74, 0, 75, 0, + 115, 0, 99, 0, 45, 0, 82, 0, 101, 0, 103, 0, 117, 0, 108, 0, + 97, 0, 114, 0, 78, 0, 111, 0, 116, 0, 111, 0, 32, 0, 105, 0, + 115, 0, 32, 0, 97, 0, 32, 0, 116, 0, 114, 0, 97, 0, 100, 0, 101, + 0, 109, 0, 97, 0, 114, 0, 107, 0, 32, 0, 111, 0, 102, 0, 32, + 0, 71, 0, 111, 0, 111, 0, 103, 0, 108, 0, 101, 0, 32, 0, 73, + 0, 110, 0, 99, 0, 46, 0, 65, 0, 100, 0, 111, 0, 98, 0, 101, 0, + 32, 0, 83, 0, 121, 0, 115, 0, 116, 0, 101, 0, 109, 0, 115, 0, + 32, 0, 73, 0, 110, 0, 99, 0, 111, 0, 114, 0, 112, 0, 111, 0, + 114, 0, 97, 0, 116, 0, 101, 0, 100, 0, 82, 0, 121, 0, 111, 0, + 107, 0, 111, 0, 32, 0, 78, 0, 73, 0, 83, 0, 72, 0, 73, 0, 90, + 0, 85, 0, 75, 0, 65, 0, 32, 137, 127, 88, 90, 109, 188, 91, 80, + 0, 32, 0, 40, 0, 107, 0, 97, 0, 110, 0, 97, 0, 32, 0, 38, 0, + 32, 0, 105, 0, 100, 0, 101, 0, 111, 0, 103, 0, 114, 0, 97, 0, + 112, 0, 104, 0, 115, 0, 41, 0, 59, 0, 32, 0, 80, 0, 97, 0, 117, + 0, 108, 0, 32, 0, 68, 0, 46, 0, 32, 0, 72, 0, 117, 0, 110, 0, + 116, 0, 32, 0, 40, 0, 76, 0, 97, 0, 116, 0, 105, 0, 110, 0, 44, + 0, 32, 0, 71, 0, 114, 0, 101, 0, 101, 0, 107, 0, 32, 0, 38, 0, + 32, 0, 67, 0, 121, 0, 114, 0, 105, 0, 108, 0, 108, 0, 105, 0, + 99, 0, 41, 0, 59, 0, 32, 0, 87, 0, 101, 0, 110, 0, 108, 0, 111, + 0, 110, 0, 103, 0, 32, 0, 90, 0, 72, 0, 65, 0, 78, 0, 71, 0, + 32, 95, 32, 101, 135, 159, 153, 0, 32, 0, 40, 0, 98, 0, 111, + 0, 112, 0, 111, 0, 109, 0, 111, 0, 102, 0, 111, 0, 41, 0, 59, + 0, 32, 0, 83, 0, 97, 0, 110, 0, 100, 0, 111, 0, 108, 0, 108, + 0, 32, 0, 67, 0, 111, 0, 109, 0, 109, 0, 117, 0, 110, 0, 105, + 0, 99, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, 0, 32, 192, 176, + 179, 204, 206, 228, 187, 164, 178, 200, 207, 0, 199, 116, 193, + 88, 0, 44, 0, 32, 0, 83, 0, 111, 0, 111, 0, 45, 0, 121, 0, 111, + 0, 117, 0, 110, 0, 103, 0, 32, 0, 74, 0, 65, 0, 78, 0, 71, 0, + 32, 199, 165, 194, 24, 198, 1, 0, 32, 0, 38, 0, 32, 0, 74, 0, + 111, 0, 111, 0, 45, 0, 121, 0, 101, 0, 111, 0, 110, 0, 32, 0, + 75, 0, 65, 0, 78, 0, 71, 0, 32, 172, 21, 200, 252, 197, 240, + 0, 32, 0, 40, 0, 104, 0, 97, 0, 110, 0, 103, 0, 117, 0, 108, + 0, 32, 0, 101, 0, 108, 0, 101, 0, 109, 0, 101, 0, 110, 0, 116, + 0, 115, 0, 44, 0, 32, 0, 108, 0, 101, 0, 116, 0, 116, 0, 101, + 0, 114, 0, 115, 0, 32, 0, 38, 0, 32, 0, 115, 0, 121, 0, 108, + 0, 108, 0, 97, 0, 98, 0, 108, 0, 101, 0, 115, 0, 41, 0, 68, 0, + 114, 0, 46, 0, 32, 0, 75, 0, 101, 0, 110, 0, 32, 0, 76, 0, 117, + 0, 110, 0, 100, 0, 101, 0, 32, 0, 40, 0, 112, 0, 114, 0, 111, + 0, 106, 0, 101, 0, 99, 0, 116, 0, 32, 0, 97, 0, 114, 0, 99, 0, + 104, 0, 105, 0, 116, 0, 101, 0, 99, 0, 116, 0, 44, 0, 32, 0, + 103, 0, 108, 0, 121, 0, 112, 0, 104, 0, 32, 0, 115, 0, 101, 0, + 116, 0, 32, 0, 100, 0, 101, 0, 102, 0, 105, 0, 110, 0, 105, 0, + 116, 0, 105, 0, 111, 0, 110, 0, 32, 0, 38, 0, 32, 0, 111, 0, + 118, 0, 101, 0, 114, 0, 97, 0, 108, 0, 108, 0, 32, 0, 112, 0, + 114, 0, 111, 0, 100, 0, 117, 0, 99, 0, 116, 0, 105, 0, 111, 0, + 110, 0, 41, 0, 59, 0, 32, 0, 77, 0, 97, 0, 115, 0, 97, 0, 116, + 0, 97, 0, 107, 0, 97, 0, 32, 0, 72, 0, 65, 0, 84, 0, 84, 0, 79, + 0, 82, 0, 73, 0, 32, 103, 13, 144, 232, 107, 99, 140, 180, 0, + 32, 0, 40, 0, 112, 0, 114, 0, 111, 0, 100, 0, 117, 0, 99, 0, + 116, 0, 105, 0, 111, 0, 110, 0, 32, 0, 38, 0, 32, 0, 105, 0, + 100, 0, 101, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, + 32, 0, 101, 0, 108, 0, 101, 0, 109, 0, 101, 0, 110, 0, 116, 0, + 115, 0, 41, 0, 104, 0, 116, 0, 116, 0, 112, 0, 58, 0, 47, 0, + 47, 0, 119, 0, 119, 0, 119, 0, 46, 0, 103, 0, 111, 0, 111, 0, + 103, 0, 108, 0, 101, 0, 46, 0, 99, 0, 111, 0, 109, 0, 47, 0, + 103, 0, 101, 0, 116, 0, 47, 0, 110, 0, 111, 0, 116, 0, 111, 0, + 47, 0, 104, 0, 116, 0, 116, 0, 112, 0, 58, 0, 47, 0, 47, 0, 119, + 0, 119, 0, 119, 0, 46, 0, 97, 0, 100, 0, 111, 0, 98, 0, 101, + 0, 46, 0, 99, 0, 111, 0, 109, 0, 47, 0, 116, 0, 121, 0, 112, + 0, 101, 0, 47, 0, 84, 0, 104, 0, 105, 0, 115, 0, 32, 0, 70, 0, + 111, 0, 110, 0, 116, 0, 32, 0, 83, 0, 111, 0, 102, 0, 116, 0, + 119, 0, 97, 0, 114, 0, 101, 0, 32, 0, 105, 0, 115, 0, 32, 0, + 108, 0, 105, 0, 99, 0, 101, 0, 110, 0, 115, 0, 101, 0, 100, 0, + 32, 0, 117, 0, 110, 0, 100, 0, 101, 0, 114, 0, 32, 0, 116, 0, + 104, 0, 101, 0, 32, 0, 83, 0, 73, 0, 76, 0, 32, 0, 79, 0, 112, + 0, 101, 0, 110, 0, 32, 0, 70, 0, 111, 0, 110, 0, 116, 0, 32, + 0, 76, 0, 105, 0, 99, 0, 101, 0, 110, 0, 115, 0, 101, 0, 44, + 0, 32, 0, 86, 0, 101, 0, 114, 0, 115, 0, 105, 0, 111, 0, 110, + 0, 32, 0, 49, 0, 46, 0, 49, 0, 46, 0, 32, 0, 84, 0, 104, 0, 105, + 0, 115, 0, 32, 0, 70, 0, 111, 0, 110, 0, 116, 0, 32, 0, 83, 0, + 111, 0, 102, 0, 116, 0, 119, 0, 97, 0, 114, 0, 101, 0, 32, 0, + 105, 0, 115, 0, 32, 0, 100, 0, 105, 0, 115, 0, 116, 0, 114, 0, + 105, 0, 98, 0, 117, 0, 116, 0, 101, 0, 100, 0, 32, 0, 111, 0, + 110, 0, 32, 0, 97, 0, 110, 0, 32, 0, 34, 0, 65, 0, 83, 0, 32, + 0, 73, 0, 83, 0, 34, 0, 32, 0, 66, 0, 65, 0, 83, 0, 73, 0, 83, + 0, 44, 0, 32, 0, 87, 0, 73, 0, 84, 0, 72, 0, 79, 0, 85, 0, 84, + 0, 32, 0, 87, 0, 65, 0, 82, 0, 82, 0, 65, 0, 78, 0, 84, 0, 73, + 0, 69, 0, 83, 0, 32, 0, 79, 0, 82, 0, 32, 0, 67, 0, 79, 0, 78, + 0, 68, 0, 73, 0, 84, 0, 73, 0, 79, 0, 78, 0, 83, 0, 32, 0, 79, + 0, 70, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 75, 0, 73, 0, 78, + 0, 68, 0, 44, 0, 32, 0, 101, 0, 105, 0, 116, 0, 104, 0, 101, + 0, 114, 0, 32, 0, 101, 0, 120, 0, 112, 0, 114, 0, 101, 0, 115, + 0, 115, 0, 32, 0, 111, 0, 114, 0, 32, 0, 105, 0, 109, 0, 112, + 0, 108, 0, 105, 0, 101, 0, 100, 0, 46, 0, 32, 0, 83, 0, 101, + 0, 101, 0, 32, 0, 116, 0, 104, 0, 101, 0, 32, 0, 83, 0, 73, 0, + 76, 0, 32, 0, 79, 0, 112, 0, 101, 0, 110, 0, 32, 0, 70, 0, 111, + 0, 110, 0, 116, 0, 32, 0, 76, 0, 105, 0, 99, 0, 101, 0, 110, + 0, 115, 0, 101, 0, 32, 0, 102, 0, 111, 0, 114, 0, 32, 0, 116, + 0, 104, 0, 101, 0, 32, 0, 115, 0, 112, 0, 101, 0, 99, 0, 105, + 0, 102, 0, 105, 0, 99, 0, 32, 0, 108, 0, 97, 0, 110, 0, 103, + 0, 117, 0, 97, 0, 103, 0, 101, 0, 44, 0, 32, 0, 112, 0, 101, + 0, 114, 0, 109, 0, 105, 0, 115, 0, 115, 0, 105, 0, 111, 0, 110, + 0, 115, 0, 32, 0, 97, 0, 110, 0, 100, 0, 32, 0, 108, 0, 105, + 0, 109, 0, 105, 0, 116, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, + 0, 115, 0, 32, 0, 103, 0, 111, 0, 118, 0, 101, 0, 114, 0, 110, + 0, 105, 0, 110, 0, 103, 0, 32, 0, 121, 0, 111, 0, 117, 0, 114, + 0, 32, 0, 117, 0, 115, 0, 101, 0, 32, 0, 111, 0, 102, 0, 32, + 0, 116, 0, 104, 0, 105, 0, 115, 0, 32, 0, 70, 0, 111, 0, 110, + 0, 116, 0, 32, 0, 83, 0, 111, 0, 102, 0, 116, 0, 119, 0, 97, + 0, 114, 0, 101, 0, 46, 0, 104, 0, 116, 0, 116, 0, 112, 0, 58, + 0, 47, 0, 47, 0, 115, 0, 99, 0, 114, 0, 105, 0, 112, 0, 116, + 0, 115, 0, 46, 0, 115, 0, 105, 0, 108, 0, 46, 0, 111, 0, 114, + 0, 103, 0, 47, 0, 79, 0, 70, 0, 76, 0, 78, 0, 111, 0, 116, 0, + 111, 0, 32, 0, 83, 0, 97, 0, 110, 0, 115, 0, 32, 0, 67, 0, 74, + 0, 75, 0, 32, 0, 83, 0, 67, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 255, 131, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0} + +func TestUTF8CutFont(t *testing.T) { + in := testFontData + out := UTF8CutFont(in, "中") + if len(out) == 0 { + t.Fatal() + } + tf, err := ioutil.TempFile(os.TempDir(), "mcuts*.ttf") + if err != nil { + t.Fatal(err) + } + fn := tf.Name() + t.Log(fn) + defer os.Remove(fn) + ioutil.WriteFile(fn, out, 0644) + ttf, err := TtfParse(fn) + if err != nil { + t.Fatal(err) + } + chars := ttf.Chars + if l := len(chars); l != 1 { + t.Fatal(l) + } + if _, ok := chars[uint16(rune('中'))]; !ok { + t.Fatal(chars) + } +} -- cgit v1.2.1-24-ge1ad From 5050243a8fdfd7329d6413b856d7e557e9ffbf3d Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Tue, 18 Jun 2019 15:46:40 +0300 Subject: WriteAligned: use SplitText for UTF-8 --- fpdf.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fpdf.go b/fpdf.go index 3e4188c..4f562ae 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2802,7 +2802,15 @@ func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) width = pageWidth - (lMargin + rMargin) } - lines := f.SplitLines([]byte(textStr), width) + var lines []string + + if f.isCurrentUTF8 { + lines = f.SplitText(textStr, width) + } else { + for _, line := range f.SplitLines([]byte(textStr), width) { + lines = append(lines, string(line)) + } + } for _, lineBt := range lines { lineStr := string(lineBt) -- cgit v1.2.1-24-ge1ad From 31bdfeb6a974f0ac84d8847231d6b6f79e7d7ceb Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 18 Jun 2019 14:22:40 -0400 Subject: Demonstrate UTF8CutFont with test example --- fpdf_test.go | 48 +++++++ utf8fontfile.go | 15 +- utf8fontfile_test.go | 380 --------------------------------------------------- 3 files changed, 54 insertions(+), 389 deletions(-) delete mode 100644 utf8fontfile_test.go diff --git a/fpdf_test.go b/fpdf_test.go index 6b43af0..7ee0831 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2561,3 +2561,51 @@ func ExampleFpdf_AddUTF8Font() { // Output: // Successfully generated pdf/Fpdf_AddUTF8Font.pdf } + +// ExampleUTF8CutFont demonstrates how generate a TrueType font subset. +func ExampleUTF8CutFont() { + var pdfFileStr, fullFontFileStr, subFontFileStr string + var subFont, fullFont []byte + var err error + + pdfFileStr = example.Filename("Fpdf_UTF8CutFont") + fullFontFileStr = example.FontFile("calligra.ttf") + fullFont, err = ioutil.ReadFile(fullFontFileStr) + if err == nil { + subFontFileStr = "calligra_abcde.ttf" + subFont = gofpdf.UTF8CutFont(fullFont, "abcde") + err = ioutil.WriteFile(subFontFileStr, subFont, 0600) + if err == nil { + y := 24.0 + pdf := gofpdf.New("P", "mm", "A4", "") + fontHt := 17.0 + lineHt := pdf.PointConvert(fontHt) + write := func(format string, args ...interface{}) { + pdf.SetXY(24.0, y) + pdf.Cell(200.0, lineHt, fmt.Sprintf(format, args...)) + y += lineHt + } + writeSize := func(fileStr string) { + var info os.FileInfo + var err error + info, err = os.Stat(fileStr) + if err == nil { + write("%6d: size of %s", info.Size(), fileStr) + } + } + pdf.AddPage() + pdf.AddUTF8Font("calligra", "", subFontFileStr) + pdf.SetFont("calligra", "", fontHt) + write("cabbed") + write("vwxyz") + pdf.SetFont("courier", "", fontHt) + writeSize(fullFontFileStr) + writeSize(subFontFileStr) + err = pdf.OutputFileAndClose(pdfFileStr) + os.Remove(subFontFileStr) + } + } + example.Summary(err, pdfFileStr) + // Output: + // Successfully generated pdf/Fpdf_UTF8CutFont.pdf +} diff --git a/utf8fontfile.go b/utf8fontfile.go index 07cf169..4d90f28 100644 --- a/utf8fontfile.go +++ b/utf8fontfile.go @@ -1139,18 +1139,15 @@ func keySortArrayRangeMap(s map[int][]int) []int { return keys } -// UTF8CutFont cuts a set in cutset and returns the customized font bytes -// Parameters: -// in - the ttf bytes in, -// cutset - the cutset runes in string, -// Returns: -// out - the ttf bytes out, -func UTF8CutFont(in []byte, cutset string) (out []byte) { - f := newUTF8Font(&fileReader{readerPosition: 0, array: in}) +// UTF8CutFont is a utility function that generates a TrueType font composed +// only of the runes included in cutset. The rune glyphs are copied from This +// function is demonstrated in ExampleUTF8CutFont(). +func UTF8CutFont(inBuf []byte, cutset string) (outBuf []byte) { + f := newUTF8Font(&fileReader{readerPosition: 0, array: inBuf}) runes := map[int]int{} for i, r := range cutset { runes[i] = int(r) } - out = f.GenerateСutFont(runes) + outBuf = f.GenerateСutFont(runes) return } diff --git a/utf8fontfile_test.go b/utf8fontfile_test.go deleted file mode 100644 index 0d808be..0000000 --- a/utf8fontfile_test.go +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2013-2019 Kurt Jung (Gmail: kurt.w.jung) - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package gofpdf - -import ( - "io/ioutil" - "os" - "testing" -) - -var testFontData = []byte{ - 0, 1, 0, 0, 0, 10, 0, 128, 0, 3, 0, 32, 79, 83, 47, 50, 159, - 99, 23, 238, 0, 0, 0, 172, 0, 0, 0, 96, 99, 109, 97, 112, 206, - 122, 158, 30, 0, 0, 1, 12, 0, 0, 0, 98, 103, 108, 121, 102, 42, - 32, 194, 143, 0, 0, 1, 112, 0, 0, 4, 76, 104, 101, 97, 100, 17, - 101, 20, 54, 0, 0, 5, 188, 0, 0, 0, 54, 104, 104, 101, 97, 12, - 17, 9, 201, 0, 0, 5, 244, 0, 0, 0, 36, 104, 109, 116, 120, 27, - 88, 2, 101, 0, 0, 6, 24, 0, 0, 0, 28, 108, 111, 99, 97, 3, 252, - 5, 12, 0, 0, 6, 52, 0, 0, 0, 16, 109, 97, 120, 112, 0, 49, 1, - 111, 0, 0, 6, 68, 0, 0, 0, 32, 110, 97, 109, 101, 33, 238, 45, - 114, 0, 0, 6, 100, 0, 0, 13, 229, 112, 111, 115, 116, 255, 134, - 0, 50, 0, 0, 20, 76, 0, 0, 0, 32, 0, 3, 3, 211, 1, 144, 0, 5, - 0, 0, 2, 138, 2, 88, 0, 0, 0, 75, 2, 138, 2, 88, 0, 0, 1, 94, - 0, 50, 1, 69, 0, 0, 2, 11, 5, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, - 3, 43, 223, 60, 16, 0, 0, 0, 22, 0, 0, 0, 0, 71, 79, 79, 71, - 0, 64, 0, 0, 255, 255, 3, 112, 255, 136, 0, 0, 4, 136, 1, 64, - 96, 46, 1, 7, 0, 0, 0, 0, 2, 31, 2, 221, 0, 0, 0, 32, 0, 6, 0, - 0, 0, 1, 0, 3, 0, 1, 0, 0, 0, 12, 0, 4, 0, 80, 0, 0, 0, 14, 0, - 8, 0, 2, 0, 6, 78, 45, 89, 125, 96, 168, 101, 135, 255, 1, 255, - 12, 255, 255, 0, 0, 78, 45, 89, 125, 96, 168, 101, 135, 255, - 1, 255, 12, 255, 255, 177, 212, 166, 133, 159, 91, 154, 125, - 1, 5, 0, 249, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 2, 0, 3, 0, 4, 0, 6, 0, 5, 0, 0, 0, 0, 0, 5, 0, 100, - 255, 136, 3, 132, 3, 112, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, - 0, 23, 17, 33, 17, 1, 1, 33, 1, 1, 17, 1, 33, 1, 1, 17, 1, 100, - 3, 32, 254, 112, 1, 62, 253, 132, 1, 94, 1, 62, 253, 100, 2, - 124, 254, 194, 254, 162, 1, 62, 120, 3, 232, 252, 24, 2, 29, - 1, 153, 254, 62, 254, 103, 3, 50, 252, 165, 1, 153, 1, 194, 252, - 206, 1, 153, 0, 0, 0, 3, 0, 100, 255, 180, 3, 131, 3, 69, 0, - 3, 0, 7, 0, 23, 0, 0, 1, 33, 17, 33, 1, 33, 17, 33, 37, 33, 17, - 35, 53, 33, 17, 35, 17, 33, 21, 35, 17, 33, 53, 51, 2, 24, 1, - 31, 254, 225, 254, 149, 1, 30, 254, 226, 1, 107, 1, 107, 76, - 254, 225, 77, 254, 226, 73, 1, 103, 77, 1, 65, 1, 9, 254, 247, - 1, 9, 73, 254, 44, 57, 254, 188, 1, 68, 62, 1, 217, 178, 0, 3, - 0, 30, 255, 178, 3, 188, 3, 68, 0, 8, 0, 45, 0, 80, 0, 0, 1, - 35, 6, 6, 7, 22, 23, 54, 54, 55, 23, 6, 6, 7, 22, 22, 23, 7, - 38, 39, 6, 6, 7, 38, 38, 39, 54, 54, 55, 38, 38, 39, 54, 54, - 55, 35, 53, 51, 54, 54, 55, 23, 6, 6, 7, 51, 5, 21, 35, 17, 20, - 6, 7, 6, 6, 39, 38, 38, 39, 22, 22, 55, 50, 53, 17, 35, 53, 51, - 53, 54, 54, 55, 33, 53, 33, 55, 23, 6, 6, 7, 21, 1, 94, 141, - 13, 31, 16, 60, 55, 31, 44, 43, 45, 12, 52, 41, 36, 60, 20, 50, - 38, 65, 42, 104, 62, 7, 27, 13, 59, 100, 40, 39, 83, 39, 18, - 36, 16, 92, 105, 11, 17, 5, 73, 7, 16, 11, 145, 2, 76, 220, 19, - 23, 23, 75, 58, 4, 16, 8, 44, 74, 11, 22, 231, 231, 38, 77, 31, - 254, 179, 1, 128, 17, 51, 37, 100, 53, 2, 51, 65, 124, 53, 39, - 44, 67, 162, 168, 11, 135, 215, 83, 31, 59, 26, 61, 49, 60, 66, - 98, 35, 14, 35, 10, 29, 95, 64, 33, 62, 26, 54, 141, 76, 69, - 53, 104, 47, 5, 46, 102, 51, 217, 71, 254, 180, 33, 35, 9, 8, - 5, 1, 16, 39, 16, 1, 1, 1, 19, 1, 76, 71, 114, 32, 90, 43, 69, - 4, 37, 55, 118, 46, 96, 0, 9, 0, 38, 255, 198, 3, 174, 3, 71, - 0, 21, 0, 31, 0, 41, 0, 51, 0, 69, 0, 79, 0, 95, 0, 118, 0, 128, - 0, 0, 1, 33, 6, 7, 38, 38, 39, 54, 54, 55, 23, 6, 7, 33, 55, - 23, 6, 6, 7, 39, 54, 54, 7, 55, 30, 2, 23, 7, 46, 2, 3, 7, 46, - 2, 39, 55, 30, 2, 3, 23, 6, 6, 7, 38, 38, 39, 54, 54, 55, 17, - 20, 6, 7, 6, 6, 35, 38, 38, 39, 22, 50, 55, 50, 54, 53, 17, 1, - 39, 62, 2, 55, 23, 14, 2, 19, 23, 6, 6, 7, 17, 35, 17, 6, 6, - 7, 38, 38, 39, 54, 54, 19, 51, 50, 54, 54, 55, 22, 22, 23, 14, - 2, 35, 35, 34, 38, 38, 53, 53, 51, 21, 20, 22, 37, 55, 30, 2, - 23, 7, 46, 2, 3, 77, 254, 136, 47, 57, 9, 35, 12, 51, 83, 25, - 69, 15, 18, 1, 118, 12, 51, 19, 43, 19, 63, 11, 25, 91, 60, 26, - 49, 40, 11, 64, 11, 39, 47, 150, 62, 12, 46, 56, 27, 57, 28, - 56, 48, 136, 68, 25, 73, 39, 10, 34, 12, 39, 66, 240, 14, 21, - 19, 63, 47, 3, 14, 7, 35, 56, 9, 10, 6, 254, 18, 70, 20, 38, - 32, 11, 67, 13, 31, 35, 137, 66, 18, 45, 25, 72, 23, 49, 24, - 7, 31, 11, 69, 127, 182, 230, 28, 27, 12, 2, 13, 40, 16, 5, 24, - 54, 50, 239, 58, 65, 25, 74, 29, 1, 143, 65, 24, 44, 35, 8, 71, - 7, 33, 42, 2, 166, 78, 56, 10, 29, 8, 44, 130, 70, 17, 37, 38, - 3, 14, 43, 92, 30, 13, 19, 52, 115, 28, 30, 71, 69, 28, 33, 28, - 71, 73, 254, 128, 36, 24, 61, 64, 26, 33, 25, 62, 60, 1, 160, - 19, 59, 112, 38, 9, 26, 7, 35, 99, 134, 254, 219, 28, 30, 8, - 9, 3, 15, 36, 14, 1, 1, 6, 8, 1, 36, 253, 88, 32, 29, 76, 78, - 32, 27, 32, 80, 77, 3, 76, 22, 37, 71, 35, 254, 106, 1, 61, 26, - 48, 20, 11, 37, 10, 52, 155, 253, 23, 16, 50, 50, 10, 15, 3, - 63, 68, 26, 17, 45, 40, 173, 172, 22, 12, 193, 25, 35, 81, 77, - 31, 29, 31, 79, 83, 0, 0, 0, 0, 3, 0, 40, 255, 181, 3, 195, 3, - 74, 0, 7, 0, 14, 0, 41, 0, 0, 1, 7, 38, 38, 39, 55, 22, 22, 23, - 33, 22, 22, 23, 54, 54, 37, 35, 6, 6, 7, 22, 22, 23, 6, 6, 7, - 38, 39, 6, 6, 7, 38, 38, 39, 54, 55, 38, 38, 39, 35, 53, 33, - 2, 66, 81, 9, 42, 23, 77, 23, 45, 141, 254, 88, 39, 109, 70, - 67, 102, 1, 22, 157, 43, 116, 75, 83, 202, 119, 13, 29, 9, 243, - 167, 84, 207, 125, 7, 28, 11, 246, 162, 77, 119, 44, 154, 3, - 128, 2, 177, 26, 31, 89, 37, 22, 35, 86, 133, 95, 169, 71, 68, - 166, 101, 118, 192, 77, 70, 104, 29, 13, 40, 16, 69, 150, 73, - 110, 40, 14, 42, 13, 70, 137, 80, 194, 113, 73, 0, 1, 0, 135, - 255, 149, 1, 74, 0, 235, 0, 18, 0, 0, 23, 39, 54, 54, 55, 6, - 34, 35, 34, 38, 53, 52, 54, 51, 50, 22, 21, 20, 6, 157, 22, 58, - 64, 4, 4, 8, 5, 31, 44, 45, 31, 41, 44, 94, 107, 53, 24, 72, - 51, 1, 36, 35, 35, 37, 62, 53, 81, 118, 0, 0, 0, 2, 0, 170, 255, - 251, 1, 74, 2, 236, 0, 5, 0, 17, 0, 0, 55, 3, 39, 51, 7, 3, 7, - 34, 38, 53, 52, 54, 51, 50, 22, 21, 20, 6, 217, 24, 3, 120, 2, - 25, 33, 33, 47, 47, 33, 33, 47, 47, 242, 1, 132, 118, 118, 254, - 124, 247, 42, 37, 35, 43, 43, 35, 37, 42, 0, 1, 0, 0, 0, 1, 1, - 6, 184, 191, 195, 30, 95, 15, 60, 245, 0, 1, 3, 232, 0, 0, 0, - 0, 209, 164, 13, 252, 0, 0, 0, 0, 217, 37, 193, 92, 252, 22, - 251, 232, 11, 112, 7, 16, 0, 0, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 4, 136, 254, 192, 0, 0, 11, 184, 252, 22, 255, 73, - 11, 112, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, - 3, 232, 0, 100, 3, 232, 0, 100, 3, 232, 0, 30, 3, 232, 0, 38, - 3, 232, 0, 40, 3, 232, 0, 135, 3, 232, 0, 170, 0, 0, 0, 44, 0, - 88, 0, 212, 1, 158, 1, 230, 2, 6, 2, 38, 0, 0, 0, 0, 0, 7, 1, - 110, 0, 41, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 1, 134, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 74, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 24, 0, 74, 0, 1, 0, 0, 0, - 0, 0, 2, 0, 7, 0, 98, 0, 1, 0, 0, 0, 0, 0, 3, 0, 38, 0, 105, - 0, 1, 0, 0, 0, 0, 0, 4, 0, 24, 0, 74, 0, 1, 0, 0, 0, 0, 0, 5, - 0, 58, 0, 143, 0, 1, 0, 0, 0, 0, 0, 6, 0, 21, 0, 201, 0, 1, 0, - 0, 0, 0, 0, 7, 0, 34, 0, 222, 0, 1, 0, 0, 0, 0, 0, 8, 0, 26, - 1, 0, 0, 1, 0, 0, 0, 0, 0, 9, 0, 195, 1, 26, 0, 1, 0, 0, 0, 0, - 0, 10, 0, 128, 1, 221, 0, 1, 0, 0, 0, 0, 0, 11, 0, 31, 2, 93, - 0, 1, 0, 0, 0, 0, 0, 12, 0, 26, 2, 124, 0, 1, 0, 0, 0, 0, 0, - 13, 1, 75, 2, 150, 0, 1, 0, 0, 0, 0, 0, 14, 0, 26, 3, 225, 0, - 1, 0, 0, 0, 0, 0, 16, 0, 16, 3, 251, 0, 3, 0, 1, 4, 9, 0, 0, - 0, 148, 4, 11, 0, 3, 0, 1, 4, 9, 0, 1, 0, 48, 4, 159, 0, 3, 0, - 1, 4, 9, 0, 2, 0, 14, 4, 207, 0, 3, 0, 1, 4, 9, 0, 3, 0, 76, - 4, 221, 0, 3, 0, 1, 4, 9, 0, 4, 0, 48, 4, 159, 0, 3, 0, 1, 4, - 9, 0, 5, 0, 116, 5, 41, 0, 3, 0, 1, 4, 9, 0, 6, 0, 42, 5, 157, - 0, 3, 0, 1, 4, 9, 0, 7, 0, 68, 5, 199, 0, 3, 0, 1, 4, 9, 0, 8, - 0, 52, 6, 11, 0, 3, 0, 1, 4, 9, 0, 9, 1, 186, 6, 63, 0, 3, 0, - 1, 4, 9, 0, 10, 1, 10, 7, 249, 0, 3, 0, 1, 4, 9, 0, 11, 0, 62, - 9, 3, 0, 3, 0, 1, 4, 9, 0, 12, 0, 52, 9, 65, 0, 3, 0, 1, 4, 9, - 0, 13, 2, 150, 9, 117, 0, 3, 0, 1, 4, 9, 0, 14, 0, 52, 12, 11, - 0, 3, 0, 1, 4, 9, 0, 16, 0, 32, 12, 63, 67, 111, 112, 121, 114, - 105, 103, 104, 116, 32, 169, 32, 50, 48, 49, 52, 44, 32, 50, - 48, 49, 53, 32, 65, 100, 111, 98, 101, 32, 83, 121, 115, 116, - 101, 109, 115, 32, 73, 110, 99, 111, 114, 112, 111, 114, 97, - 116, 101, 100, 32, 40, 104, 116, 116, 112, 58, 47, 47, 119, 119, - 119, 46, 97, 100, 111, 98, 101, 46, 99, 111, 109, 47, 41, 46, - 78, 111, 116, 111, 32, 83, 97, 110, 115, 32, 67, 74, 75, 32, - 83, 67, 32, 82, 101, 103, 117, 108, 97, 114, 82, 101, 103, 117, - 108, 97, 114, 49, 46, 48, 48, 52, 59, 71, 79, 79, 71, 59, 78, - 111, 116, 111, 83, 97, 110, 115, 67, 74, 75, 115, 99, 45, 82, - 101, 103, 117, 108, 97, 114, 59, 65, 68, 79, 66, 69, 86, 101, - 114, 115, 105, 111, 110, 32, 49, 46, 48, 48, 52, 59, 80, 83, - 32, 49, 46, 48, 48, 52, 59, 104, 111, 116, 99, 111, 110, 118, - 32, 49, 46, 48, 46, 56, 50, 59, 109, 97, 107, 101, 111, 116, - 102, 46, 108, 105, 98, 50, 46, 53, 46, 54, 51, 52, 48, 54, 78, - 111, 116, 111, 83, 97, 110, 115, 67, 74, 75, 115, 99, 45, 82, - 101, 103, 117, 108, 97, 114, 78, 111, 116, 111, 32, 105, 115, - 32, 97, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, - 102, 32, 71, 111, 111, 103, 108, 101, 32, 73, 110, 99, 46, 65, - 100, 111, 98, 101, 32, 83, 121, 115, 116, 101, 109, 115, 32, - 73, 110, 99, 111, 114, 112, 111, 114, 97, 116, 101, 100, 82, - 121, 111, 107, 111, 32, 78, 73, 83, 72, 73, 90, 85, 75, 65, 32, - 40, 107, 97, 110, 97, 32, 38, 32, 105, 100, 101, 111, 103, 114, - 97, 112, 104, 115, 41, 59, 32, 80, 97, 117, 108, 32, 68, 46, - 32, 72, 117, 110, 116, 32, 40, 76, 97, 116, 105, 110, 44, 32, - 71, 114, 101, 101, 107, 32, 38, 32, 67, 121, 114, 105, 108, 108, - 105, 99, 41, 59, 32, 87, 101, 110, 108, 111, 110, 103, 32, 90, - 72, 65, 78, 71, 32, 40, 98, 111, 112, 111, 109, 111, 102, 111, - 41, 59, 32, 83, 97, 110, 100, 111, 108, 108, 32, 67, 111, 109, - 109, 117, 110, 105, 99, 97, 116, 105, 111, 110, 44, 32, 83, 111, - 111, 45, 121, 111, 117, 110, 103, 32, 74, 65, 78, 71, 32, 38, - 32, 74, 111, 111, 45, 121, 101, 111, 110, 32, 75, 65, 78, 71, - 32, 40, 104, 97, 110, 103, 117, 108, 32, 101, 108, 101, 109, - 101, 110, 116, 115, 44, 32, 108, 101, 116, 116, 101, 114, 115, - 32, 38, 32, 115, 121, 108, 108, 97, 98, 108, 101, 115, 41, 68, - 114, 46, 32, 75, 101, 110, 32, 76, 117, 110, 100, 101, 32, 40, - 112, 114, 111, 106, 101, 99, 116, 32, 97, 114, 99, 104, 105, - 116, 101, 99, 116, 44, 32, 103, 108, 121, 112, 104, 32, 115, - 101, 116, 32, 100, 101, 102, 105, 110, 105, 116, 105, 111, 110, - 32, 38, 32, 111, 118, 101, 114, 97, 108, 108, 32, 112, 114, 111, - 100, 117, 99, 116, 105, 111, 110, 41, 59, 32, 77, 97, 115, 97, - 116, 97, 107, 97, 32, 72, 65, 84, 84, 79, 82, 73, 32, 40, 112, - 114, 111, 100, 117, 99, 116, 105, 111, 110, 32, 38, 32, 105, - 100, 101, 111, 103, 114, 97, 112, 104, 32, 101, 108, 101, 109, - 101, 110, 116, 115, 41, 104, 116, 116, 112, 58, 47, 47, 119, - 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, - 47, 103, 101, 116, 47, 110, 111, 116, 111, 47, 104, 116, 116, - 112, 58, 47, 47, 119, 119, 119, 46, 97, 100, 111, 98, 101, 46, - 99, 111, 109, 47, 116, 121, 112, 101, 47, 84, 104, 105, 115, - 32, 70, 111, 110, 116, 32, 83, 111, 102, 116, 119, 97, 114, 101, - 32, 105, 115, 32, 108, 105, 99, 101, 110, 115, 101, 100, 32, - 117, 110, 100, 101, 114, 32, 116, 104, 101, 32, 83, 73, 76, 32, - 79, 112, 101, 110, 32, 70, 111, 110, 116, 32, 76, 105, 99, 101, - 110, 115, 101, 44, 32, 86, 101, 114, 115, 105, 111, 110, 32, - 49, 46, 49, 46, 32, 84, 104, 105, 115, 32, 70, 111, 110, 116, - 32, 83, 111, 102, 116, 119, 97, 114, 101, 32, 105, 115, 32, 100, - 105, 115, 116, 114, 105, 98, 117, 116, 101, 100, 32, 111, 110, - 32, 97, 110, 32, 34, 65, 83, 32, 73, 83, 34, 32, 66, 65, 83, - 73, 83, 44, 32, 87, 73, 84, 72, 79, 85, 84, 32, 87, 65, 82, 82, - 65, 78, 84, 73, 69, 83, 32, 79, 82, 32, 67, 79, 78, 68, 73, 84, - 73, 79, 78, 83, 32, 79, 70, 32, 65, 78, 89, 32, 75, 73, 78, 68, - 44, 32, 101, 105, 116, 104, 101, 114, 32, 101, 120, 112, 114, - 101, 115, 115, 32, 111, 114, 32, 105, 109, 112, 108, 105, 101, - 100, 46, 32, 83, 101, 101, 32, 116, 104, 101, 32, 83, 73, 76, - 32, 79, 112, 101, 110, 32, 70, 111, 110, 116, 32, 76, 105, 99, - 101, 110, 115, 101, 32, 102, 111, 114, 32, 116, 104, 101, 32, - 115, 112, 101, 99, 105, 102, 105, 99, 32, 108, 97, 110, 103, - 117, 97, 103, 101, 44, 32, 112, 101, 114, 109, 105, 115, 115, - 105, 111, 110, 115, 32, 97, 110, 100, 32, 108, 105, 109, 105, - 116, 97, 116, 105, 111, 110, 115, 32, 103, 111, 118, 101, 114, - 110, 105, 110, 103, 32, 121, 111, 117, 114, 32, 117, 115, 101, - 32, 111, 102, 32, 116, 104, 105, 115, 32, 70, 111, 110, 116, - 32, 83, 111, 102, 116, 119, 97, 114, 101, 46, 104, 116, 116, - 112, 58, 47, 47, 115, 99, 114, 105, 112, 116, 115, 46, 115, 105, - 108, 46, 111, 114, 103, 47, 79, 70, 76, 78, 111, 116, 111, 32, - 83, 97, 110, 115, 32, 67, 74, 75, 32, 83, 67, 0, 67, 0, 111, - 0, 112, 0, 121, 0, 114, 0, 105, 0, 103, 0, 104, 0, 116, 0, 32, - 0, 169, 0, 32, 0, 50, 0, 48, 0, 49, 0, 52, 0, 44, 0, 32, 0, 50, - 0, 48, 0, 49, 0, 53, 0, 32, 0, 65, 0, 100, 0, 111, 0, 98, 0, - 101, 0, 32, 0, 83, 0, 121, 0, 115, 0, 116, 0, 101, 0, 109, 0, - 115, 0, 32, 0, 73, 0, 110, 0, 99, 0, 111, 0, 114, 0, 112, 0, - 111, 0, 114, 0, 97, 0, 116, 0, 101, 0, 100, 0, 32, 0, 40, 0, - 104, 0, 116, 0, 116, 0, 112, 0, 58, 0, 47, 0, 47, 0, 119, 0, - 119, 0, 119, 0, 46, 0, 97, 0, 100, 0, 111, 0, 98, 0, 101, 0, - 46, 0, 99, 0, 111, 0, 109, 0, 47, 0, 41, 0, 46, 0, 78, 0, 111, - 0, 116, 0, 111, 0, 32, 0, 83, 0, 97, 0, 110, 0, 115, 0, 32, 0, - 67, 0, 74, 0, 75, 0, 32, 0, 83, 0, 67, 0, 32, 0, 82, 0, 101, - 0, 103, 0, 117, 0, 108, 0, 97, 0, 114, 0, 82, 0, 101, 0, 103, - 0, 117, 0, 108, 0, 97, 0, 114, 0, 49, 0, 46, 0, 48, 0, 48, 0, - 52, 0, 59, 0, 71, 0, 79, 0, 79, 0, 71, 0, 59, 0, 78, 0, 111, - 0, 116, 0, 111, 0, 83, 0, 97, 0, 110, 0, 115, 0, 67, 0, 74, 0, - 75, 0, 115, 0, 99, 0, 45, 0, 82, 0, 101, 0, 103, 0, 117, 0, 108, - 0, 97, 0, 114, 0, 59, 0, 65, 0, 68, 0, 79, 0, 66, 0, 69, 0, 86, - 0, 101, 0, 114, 0, 115, 0, 105, 0, 111, 0, 110, 0, 32, 0, 49, - 0, 46, 0, 48, 0, 48, 0, 52, 0, 59, 0, 80, 0, 83, 0, 32, 0, 49, - 0, 46, 0, 48, 0, 48, 0, 52, 0, 59, 0, 104, 0, 111, 0, 116, 0, - 99, 0, 111, 0, 110, 0, 118, 0, 32, 0, 49, 0, 46, 0, 48, 0, 46, - 0, 56, 0, 50, 0, 59, 0, 109, 0, 97, 0, 107, 0, 101, 0, 111, 0, - 116, 0, 102, 0, 46, 0, 108, 0, 105, 0, 98, 0, 50, 0, 46, 0, 53, - 0, 46, 0, 54, 0, 51, 0, 52, 0, 48, 0, 54, 0, 78, 0, 111, 0, 116, - 0, 111, 0, 83, 0, 97, 0, 110, 0, 115, 0, 67, 0, 74, 0, 75, 0, - 115, 0, 99, 0, 45, 0, 82, 0, 101, 0, 103, 0, 117, 0, 108, 0, - 97, 0, 114, 0, 78, 0, 111, 0, 116, 0, 111, 0, 32, 0, 105, 0, - 115, 0, 32, 0, 97, 0, 32, 0, 116, 0, 114, 0, 97, 0, 100, 0, 101, - 0, 109, 0, 97, 0, 114, 0, 107, 0, 32, 0, 111, 0, 102, 0, 32, - 0, 71, 0, 111, 0, 111, 0, 103, 0, 108, 0, 101, 0, 32, 0, 73, - 0, 110, 0, 99, 0, 46, 0, 65, 0, 100, 0, 111, 0, 98, 0, 101, 0, - 32, 0, 83, 0, 121, 0, 115, 0, 116, 0, 101, 0, 109, 0, 115, 0, - 32, 0, 73, 0, 110, 0, 99, 0, 111, 0, 114, 0, 112, 0, 111, 0, - 114, 0, 97, 0, 116, 0, 101, 0, 100, 0, 82, 0, 121, 0, 111, 0, - 107, 0, 111, 0, 32, 0, 78, 0, 73, 0, 83, 0, 72, 0, 73, 0, 90, - 0, 85, 0, 75, 0, 65, 0, 32, 137, 127, 88, 90, 109, 188, 91, 80, - 0, 32, 0, 40, 0, 107, 0, 97, 0, 110, 0, 97, 0, 32, 0, 38, 0, - 32, 0, 105, 0, 100, 0, 101, 0, 111, 0, 103, 0, 114, 0, 97, 0, - 112, 0, 104, 0, 115, 0, 41, 0, 59, 0, 32, 0, 80, 0, 97, 0, 117, - 0, 108, 0, 32, 0, 68, 0, 46, 0, 32, 0, 72, 0, 117, 0, 110, 0, - 116, 0, 32, 0, 40, 0, 76, 0, 97, 0, 116, 0, 105, 0, 110, 0, 44, - 0, 32, 0, 71, 0, 114, 0, 101, 0, 101, 0, 107, 0, 32, 0, 38, 0, - 32, 0, 67, 0, 121, 0, 114, 0, 105, 0, 108, 0, 108, 0, 105, 0, - 99, 0, 41, 0, 59, 0, 32, 0, 87, 0, 101, 0, 110, 0, 108, 0, 111, - 0, 110, 0, 103, 0, 32, 0, 90, 0, 72, 0, 65, 0, 78, 0, 71, 0, - 32, 95, 32, 101, 135, 159, 153, 0, 32, 0, 40, 0, 98, 0, 111, - 0, 112, 0, 111, 0, 109, 0, 111, 0, 102, 0, 111, 0, 41, 0, 59, - 0, 32, 0, 83, 0, 97, 0, 110, 0, 100, 0, 111, 0, 108, 0, 108, - 0, 32, 0, 67, 0, 111, 0, 109, 0, 109, 0, 117, 0, 110, 0, 105, - 0, 99, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, 0, 32, 192, 176, - 179, 204, 206, 228, 187, 164, 178, 200, 207, 0, 199, 116, 193, - 88, 0, 44, 0, 32, 0, 83, 0, 111, 0, 111, 0, 45, 0, 121, 0, 111, - 0, 117, 0, 110, 0, 103, 0, 32, 0, 74, 0, 65, 0, 78, 0, 71, 0, - 32, 199, 165, 194, 24, 198, 1, 0, 32, 0, 38, 0, 32, 0, 74, 0, - 111, 0, 111, 0, 45, 0, 121, 0, 101, 0, 111, 0, 110, 0, 32, 0, - 75, 0, 65, 0, 78, 0, 71, 0, 32, 172, 21, 200, 252, 197, 240, - 0, 32, 0, 40, 0, 104, 0, 97, 0, 110, 0, 103, 0, 117, 0, 108, - 0, 32, 0, 101, 0, 108, 0, 101, 0, 109, 0, 101, 0, 110, 0, 116, - 0, 115, 0, 44, 0, 32, 0, 108, 0, 101, 0, 116, 0, 116, 0, 101, - 0, 114, 0, 115, 0, 32, 0, 38, 0, 32, 0, 115, 0, 121, 0, 108, - 0, 108, 0, 97, 0, 98, 0, 108, 0, 101, 0, 115, 0, 41, 0, 68, 0, - 114, 0, 46, 0, 32, 0, 75, 0, 101, 0, 110, 0, 32, 0, 76, 0, 117, - 0, 110, 0, 100, 0, 101, 0, 32, 0, 40, 0, 112, 0, 114, 0, 111, - 0, 106, 0, 101, 0, 99, 0, 116, 0, 32, 0, 97, 0, 114, 0, 99, 0, - 104, 0, 105, 0, 116, 0, 101, 0, 99, 0, 116, 0, 44, 0, 32, 0, - 103, 0, 108, 0, 121, 0, 112, 0, 104, 0, 32, 0, 115, 0, 101, 0, - 116, 0, 32, 0, 100, 0, 101, 0, 102, 0, 105, 0, 110, 0, 105, 0, - 116, 0, 105, 0, 111, 0, 110, 0, 32, 0, 38, 0, 32, 0, 111, 0, - 118, 0, 101, 0, 114, 0, 97, 0, 108, 0, 108, 0, 32, 0, 112, 0, - 114, 0, 111, 0, 100, 0, 117, 0, 99, 0, 116, 0, 105, 0, 111, 0, - 110, 0, 41, 0, 59, 0, 32, 0, 77, 0, 97, 0, 115, 0, 97, 0, 116, - 0, 97, 0, 107, 0, 97, 0, 32, 0, 72, 0, 65, 0, 84, 0, 84, 0, 79, - 0, 82, 0, 73, 0, 32, 103, 13, 144, 232, 107, 99, 140, 180, 0, - 32, 0, 40, 0, 112, 0, 114, 0, 111, 0, 100, 0, 117, 0, 99, 0, - 116, 0, 105, 0, 111, 0, 110, 0, 32, 0, 38, 0, 32, 0, 105, 0, - 100, 0, 101, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, - 32, 0, 101, 0, 108, 0, 101, 0, 109, 0, 101, 0, 110, 0, 116, 0, - 115, 0, 41, 0, 104, 0, 116, 0, 116, 0, 112, 0, 58, 0, 47, 0, - 47, 0, 119, 0, 119, 0, 119, 0, 46, 0, 103, 0, 111, 0, 111, 0, - 103, 0, 108, 0, 101, 0, 46, 0, 99, 0, 111, 0, 109, 0, 47, 0, - 103, 0, 101, 0, 116, 0, 47, 0, 110, 0, 111, 0, 116, 0, 111, 0, - 47, 0, 104, 0, 116, 0, 116, 0, 112, 0, 58, 0, 47, 0, 47, 0, 119, - 0, 119, 0, 119, 0, 46, 0, 97, 0, 100, 0, 111, 0, 98, 0, 101, - 0, 46, 0, 99, 0, 111, 0, 109, 0, 47, 0, 116, 0, 121, 0, 112, - 0, 101, 0, 47, 0, 84, 0, 104, 0, 105, 0, 115, 0, 32, 0, 70, 0, - 111, 0, 110, 0, 116, 0, 32, 0, 83, 0, 111, 0, 102, 0, 116, 0, - 119, 0, 97, 0, 114, 0, 101, 0, 32, 0, 105, 0, 115, 0, 32, 0, - 108, 0, 105, 0, 99, 0, 101, 0, 110, 0, 115, 0, 101, 0, 100, 0, - 32, 0, 117, 0, 110, 0, 100, 0, 101, 0, 114, 0, 32, 0, 116, 0, - 104, 0, 101, 0, 32, 0, 83, 0, 73, 0, 76, 0, 32, 0, 79, 0, 112, - 0, 101, 0, 110, 0, 32, 0, 70, 0, 111, 0, 110, 0, 116, 0, 32, - 0, 76, 0, 105, 0, 99, 0, 101, 0, 110, 0, 115, 0, 101, 0, 44, - 0, 32, 0, 86, 0, 101, 0, 114, 0, 115, 0, 105, 0, 111, 0, 110, - 0, 32, 0, 49, 0, 46, 0, 49, 0, 46, 0, 32, 0, 84, 0, 104, 0, 105, - 0, 115, 0, 32, 0, 70, 0, 111, 0, 110, 0, 116, 0, 32, 0, 83, 0, - 111, 0, 102, 0, 116, 0, 119, 0, 97, 0, 114, 0, 101, 0, 32, 0, - 105, 0, 115, 0, 32, 0, 100, 0, 105, 0, 115, 0, 116, 0, 114, 0, - 105, 0, 98, 0, 117, 0, 116, 0, 101, 0, 100, 0, 32, 0, 111, 0, - 110, 0, 32, 0, 97, 0, 110, 0, 32, 0, 34, 0, 65, 0, 83, 0, 32, - 0, 73, 0, 83, 0, 34, 0, 32, 0, 66, 0, 65, 0, 83, 0, 73, 0, 83, - 0, 44, 0, 32, 0, 87, 0, 73, 0, 84, 0, 72, 0, 79, 0, 85, 0, 84, - 0, 32, 0, 87, 0, 65, 0, 82, 0, 82, 0, 65, 0, 78, 0, 84, 0, 73, - 0, 69, 0, 83, 0, 32, 0, 79, 0, 82, 0, 32, 0, 67, 0, 79, 0, 78, - 0, 68, 0, 73, 0, 84, 0, 73, 0, 79, 0, 78, 0, 83, 0, 32, 0, 79, - 0, 70, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 75, 0, 73, 0, 78, - 0, 68, 0, 44, 0, 32, 0, 101, 0, 105, 0, 116, 0, 104, 0, 101, - 0, 114, 0, 32, 0, 101, 0, 120, 0, 112, 0, 114, 0, 101, 0, 115, - 0, 115, 0, 32, 0, 111, 0, 114, 0, 32, 0, 105, 0, 109, 0, 112, - 0, 108, 0, 105, 0, 101, 0, 100, 0, 46, 0, 32, 0, 83, 0, 101, - 0, 101, 0, 32, 0, 116, 0, 104, 0, 101, 0, 32, 0, 83, 0, 73, 0, - 76, 0, 32, 0, 79, 0, 112, 0, 101, 0, 110, 0, 32, 0, 70, 0, 111, - 0, 110, 0, 116, 0, 32, 0, 76, 0, 105, 0, 99, 0, 101, 0, 110, - 0, 115, 0, 101, 0, 32, 0, 102, 0, 111, 0, 114, 0, 32, 0, 116, - 0, 104, 0, 101, 0, 32, 0, 115, 0, 112, 0, 101, 0, 99, 0, 105, - 0, 102, 0, 105, 0, 99, 0, 32, 0, 108, 0, 97, 0, 110, 0, 103, - 0, 117, 0, 97, 0, 103, 0, 101, 0, 44, 0, 32, 0, 112, 0, 101, - 0, 114, 0, 109, 0, 105, 0, 115, 0, 115, 0, 105, 0, 111, 0, 110, - 0, 115, 0, 32, 0, 97, 0, 110, 0, 100, 0, 32, 0, 108, 0, 105, - 0, 109, 0, 105, 0, 116, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, - 0, 115, 0, 32, 0, 103, 0, 111, 0, 118, 0, 101, 0, 114, 0, 110, - 0, 105, 0, 110, 0, 103, 0, 32, 0, 121, 0, 111, 0, 117, 0, 114, - 0, 32, 0, 117, 0, 115, 0, 101, 0, 32, 0, 111, 0, 102, 0, 32, - 0, 116, 0, 104, 0, 105, 0, 115, 0, 32, 0, 70, 0, 111, 0, 110, - 0, 116, 0, 32, 0, 83, 0, 111, 0, 102, 0, 116, 0, 119, 0, 97, - 0, 114, 0, 101, 0, 46, 0, 104, 0, 116, 0, 116, 0, 112, 0, 58, - 0, 47, 0, 47, 0, 115, 0, 99, 0, 114, 0, 105, 0, 112, 0, 116, - 0, 115, 0, 46, 0, 115, 0, 105, 0, 108, 0, 46, 0, 111, 0, 114, - 0, 103, 0, 47, 0, 79, 0, 70, 0, 76, 0, 78, 0, 111, 0, 116, 0, - 111, 0, 32, 0, 83, 0, 97, 0, 110, 0, 115, 0, 32, 0, 67, 0, 74, - 0, 75, 0, 32, 0, 83, 0, 67, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, - 255, 131, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0} - -func TestUTF8CutFont(t *testing.T) { - in := testFontData - out := UTF8CutFont(in, "中") - if len(out) == 0 { - t.Fatal() - } - tf, err := ioutil.TempFile(os.TempDir(), "mcuts*.ttf") - if err != nil { - t.Fatal(err) - } - fn := tf.Name() - t.Log(fn) - defer os.Remove(fn) - ioutil.WriteFile(fn, out, 0644) - ttf, err := TtfParse(fn) - if err != nil { - t.Fatal(err) - } - chars := ttf.Chars - if l := len(chars); l != 1 { - t.Fatal(l) - } - if _, ok := chars[uint16(rune('中'))]; !ok { - t.Fatal(chars) - } -} -- cgit v1.2.1-24-ge1ad From 3aaf0b1a66c0ab02d925917376898a5856061d59 Mon Sep 17 00:00:00 2001 From: Kurt Date: Wed, 3 Jul 2019 07:41:40 -0400 Subject: Do not execute Multicell if instance is in error state --- fpdf.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fpdf.go b/fpdf.go index 0b2aa25..35496c2 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2476,6 +2476,9 @@ func (f *Fpdf) SplitLines(txt []byte, w float64) [][]byte { // // h indicates the line height of each cell in the unit of measure specified in New(). func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill bool) { + if f.err != nil { + return + } // dbg("MultiCell") if alignStr == "" { alignStr = "J" -- cgit v1.2.1-24-ge1ad From 09261e84da53502557bf24a24fdc36e7cc215ddf Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Thu, 18 Jul 2019 15:00:05 +0300 Subject: fix utf8 text wrapping UTF8 text splitted correctly by SplitText function in WriteAligned method: https://github.com/jung-kurt/gofpdf/blob/3aaf0b1a66c0ab02d925917376898a5856061d59/fpdf.go#L2811 Then, lines of text are written via Write function, and if text is already wrapped by given width it will be printed using 'last chunk' case: https://github.com/jung-kurt/gofpdf/blob/3aaf0b1a66c0ab02d925917376898a5856061d59/fpdf.go#L2747,L2754 But in this case, gofpdf does not move cursor to the next cell, which cause all text to be printed on the same line without actual wrapping. This commit makes workaround for it by explicitly setting right margin to force automatic line break case: https://github.com/jung-kurt/gofpdf/blob/3aaf0b1a66c0ab02d925917376898a5856061d59/fpdf.go#L2705 --- fpdf.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fpdf.go b/fpdf.go index 35496c2..b3d0b0e 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2800,8 +2800,8 @@ func (f *Fpdf) WriteLinkID(h float64, displayStr string, linkID int) { func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) { lMargin, _, rMargin, _ := f.GetMargins() + pageWidth, _ := f.GetPageSize() if width == 0 { - pageWidth, _ := f.GetPageSize() width = pageWidth - (lMargin + rMargin) } @@ -2819,6 +2819,7 @@ func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) lineStr := string(lineBt) lineWidth := f.GetStringWidth(lineStr) + f.SetLeftMargin(lMargin + (width - lineWidth) - 2.01*f.cMargin) switch alignStr { case "C": f.SetLeftMargin(lMargin + ((width - lineWidth) / 2)) @@ -2831,6 +2832,7 @@ func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) default: f.Write(lineHeight, lineStr) } + f.SetRightMargin(rMargin) } } -- cgit v1.2.1-24-ge1ad From d0f2d2e94a89ab84c0c647ebb0873f43593d89fd Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Thu, 18 Jul 2019 15:41:13 +0300 Subject: fix bug introduced in #279 --- fpdf.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fpdf.go b/fpdf.go index b3d0b0e..f46680b 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2819,7 +2819,6 @@ func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) lineStr := string(lineBt) lineWidth := f.GetStringWidth(lineStr) - f.SetLeftMargin(lMargin + (width - lineWidth) - 2.01*f.cMargin) switch alignStr { case "C": f.SetLeftMargin(lMargin + ((width - lineWidth) / 2)) @@ -2830,9 +2829,10 @@ func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) f.Write(lineHeight, lineStr) f.SetLeftMargin(lMargin) default: + f.SetRightMargin(pageWidth - lMargin - width) f.Write(lineHeight, lineStr) + f.SetRightMargin(rMargin) } - f.SetRightMargin(rMargin) } } -- cgit v1.2.1-24-ge1ad From 4c5c3288c806b7d607796adfe13d676714796954 Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 18 Jul 2019 08:45:23 -0400 Subject: Revert "Merge branch 'seletskiy-master'" This reverts commit a542cf333bc2e3e4e138bb4848f02997aba71ce9, reversing changes made to 3aaf0b1a66c0ab02d925917376898a5856061d59. --- fpdf.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fpdf.go b/fpdf.go index b3d0b0e..35496c2 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2800,8 +2800,8 @@ func (f *Fpdf) WriteLinkID(h float64, displayStr string, linkID int) { func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) { lMargin, _, rMargin, _ := f.GetMargins() - pageWidth, _ := f.GetPageSize() if width == 0 { + pageWidth, _ := f.GetPageSize() width = pageWidth - (lMargin + rMargin) } @@ -2819,7 +2819,6 @@ func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) lineStr := string(lineBt) lineWidth := f.GetStringWidth(lineStr) - f.SetLeftMargin(lMargin + (width - lineWidth) - 2.01*f.cMargin) switch alignStr { case "C": f.SetLeftMargin(lMargin + ((width - lineWidth) / 2)) @@ -2832,7 +2831,6 @@ func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) default: f.Write(lineHeight, lineStr) } - f.SetRightMargin(rMargin) } } -- cgit v1.2.1-24-ge1ad From e914c59514da0d291277444b0de1b572fb9544d9 Mon Sep 17 00:00:00 2001 From: estenssoros Date: Thu, 18 Jul 2019 15:25:55 -0600 Subject: added imageoptionsreader --- fpdf.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fpdf_test.go | 23 +++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/fpdf.go b/fpdf.go index 35496c2..c34226c 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2984,6 +2984,73 @@ func (f *Fpdf) ImageOptions(imageNameStr string, x, y, w, h float64, flow bool, return } +// ImageOptionsReader registers an image, reading it from Reader r, and puts a +// JPEG, PNG or GIF image in the current page. The size it will take on the +// page can be specified in different ways. If both w and h are 0, the image +// is rendered at 96 dpi. If either w or h is zero, it will be calculated from +// the other dimension so that the aspect ratio is maintained. If w and/or h are -1, +// the dpi for that dimension will be read from the ImageInfoType object. PNG +// files can contain dpi information, and if present, this information will be +// populated in the ImageInfoType object and used in Width, Height, and Extent +// calculations. Otherwise, the SetDpi function can be used to change the dpi +// from the default of 72. +// +// If w and h are any other negative value, their absolute values +// indicate their dpi extents. +// +// Supported JPEG formats are 24 bit, 32 bit and gray scale. Supported PNG +// formats are 24 bit, indexed color, and 8 bit indexed gray scale. If a GIF +// image is animated, only the first frame is rendered. Transparency is +// supported. It is possible to put a link on the image. +// +// imageNameStr may be the name of an image as registered with a call to either +// RegisterImageReader() or RegisterImage(). In the first case, the image is +// loaded using an io.Reader. This is generally useful when the image is +// obtained from some other means than as a disk-based file. In the second +// case, the image is loaded as a file. Alternatively, imageNameStr may +// directly specify a sufficiently qualified filename. +// +// r is an io.Reader that implements the Read() function +// +// However the image is loaded, if it is used more than once only one copy is +// embedded in the file. +// +// If x is negative, the current abscissa is used. +// +// If flow is true, the current y value is advanced after placing the image and +// a page break may be made if necessary. +// +// If link refers to an internal page anchor (that is, it is non-zero; see +// AddLink()), the image will be a clickable internal link. Otherwise, if +// linkStr specifies a URL, the image will be a clickable external link. +func (f *Fpdf) ImageOptionsReader(imageNameStr string, r io.Reader, x, y, w, h float64, flow bool, options ImageOptions, link int, linkStr string) { + if f.err != nil { + return + } + + var info *ImageInfoType + + i, ok := f.images[imageNameStr] + if ok { + info = i + } else { + if options.ImageType == "" { + pos := strings.LastIndex(imageNameStr, ".") + if pos < 0 { + f.err = fmt.Errorf("image file has no extension and no type was specified: %s", imageNameStr) + return + } + options.ImageType = imageNameStr[pos+1:] + } + info = f.RegisterImageOptionsReader(imageNameStr, options, r) + if f.err != nil { + return + } + } + f.imageOut(info, x, y, w, h, options.AllowNegativePosition, flow, link, linkStr) + return +} + // RegisterImageReader registers an image, reading it from Reader r, adding it // to the PDF file but not adding it to the page. // diff --git a/fpdf_test.go b/fpdf_test.go index 7ee0831..5ef88aa 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -858,6 +858,29 @@ func ExampleFpdf_ImageOptions() { // Successfully generated pdf/Fpdf_ImageOptions.pdf } +// ImageOption struct can be used to affect horizontal image placement. +func ExampleFpdf_ImageOptionsReader() { + var opt gofpdf.ImageOptions + + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "", 11) + pdf.SetX(60) + opt.ImageType = "png" + bytes, err := ioutil.ReadAll(example.ImageFile("logo.png")) + if err!=nil{ + t.Fatal(err) + } + pdf.ImageOptionsReader(example.ImageFile("logo.png"), bytes.NewReader(bytes),-10, 10, 30, 0, false, opt, 0, "") + opt.AllowNegativePosition = true + pdf.ImageOptionsReader(example.ImageFile("logo.png"),bytes.NewReader(bytes), -10, 50, 30, 0, false, opt, 0, "") + fileStr := example.Filename("Fpdf_ImageOptionsReader") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_ImageOptionsReader.pdf +} + // This examples demonstrates Landscape mode with images. func ExampleFpdf_SetAcceptPageBreakFunc() { var y0 float64 -- cgit v1.2.1-24-ge1ad From 20e5ed95b595d65457b8b33d68afdbdd99aa31f9 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 20 Jul 2019 09:41:38 -0400 Subject: Correct placement of pageWidth variable --- fpdf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpdf.go b/fpdf.go index a676331..f46680b 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2800,8 +2800,8 @@ func (f *Fpdf) WriteLinkID(h float64, displayStr string, linkID int) { func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) { lMargin, _, rMargin, _ := f.GetMargins() + pageWidth, _ := f.GetPageSize() if width == 0 { - pageWidth, _ := f.GetPageSize() width = pageWidth - (lMargin + rMargin) } -- cgit v1.2.1-24-ge1ad From 5a3837eac46daca22df96b6b65a184cafef7e03e Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 20 Jul 2019 09:53:13 -0400 Subject: Wrap some comments --- fpdf.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fpdf.go b/fpdf.go index f46680b..ca48fb5 100644 --- a/fpdf.go +++ b/fpdf.go @@ -3187,12 +3187,14 @@ func (f *Fpdf) putImportedTemplates() { } } -// UseImportedTemplate uses imported template from gofpdi - draws imported PDF page onto page +// UseImportedTemplate uses imported template from gofpdi. It draws imported +// PDF page onto page. func (f *Fpdf) UseImportedTemplate(tplName string, scaleX float64, scaleY float64, tX float64, tY float64) { f.outf("q 0 J 1 w 0 j 0 G 0 g q %.4F 0 0 %.4F %.4F %.4F cm %s Do Q Q\n", scaleX*f.k, scaleY*f.k, tX*f.k, (tY+f.h)*f.k, tplName) } -// ImportTemplates imports gofpdi template names into importedTplObjs - to be included in the procset dictionary +// ImportTemplates imports gofpdi template names into importedTplObjs for +// inclusion in the procset dictionary func (f *Fpdf) ImportTemplates(tpls map[string]string) { for tplName, tplID := range tpls { f.importedTplObjs[tplName] = tplID -- cgit v1.2.1-24-ge1ad From 19ac748275dda1bd9cb6a618c380a18482a2da71 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 20 Jul 2019 10:10:49 -0400 Subject: Use file as reader for ImageOptionsReader --- fpdf_test.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/fpdf_test.go b/fpdf_test.go index 5ef88aa..54de6c2 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -861,22 +861,29 @@ func ExampleFpdf_ImageOptions() { // ImageOption struct can be used to affect horizontal image placement. func ExampleFpdf_ImageOptionsReader() { var opt gofpdf.ImageOptions + var pdfStr, imgStr string + var fl *os.File + var err error + pdfStr = example.Filename("Fpdf_ImageOptionsReader") pdf := gofpdf.New("P", "mm", "A4", "") pdf.AddPage() pdf.SetFont("Arial", "", 11) pdf.SetX(60) opt.ImageType = "png" - bytes, err := ioutil.ReadAll(example.ImageFile("logo.png")) - if err!=nil{ - t.Fatal(err) + imgStr = example.ImageFile("logo.png") + fl, err = os.Open(imgStr) + if err == nil { + pdf.ImageOptionsReader(imgStr, fl, -10, 10, 30, 0, false, opt, 0, "") + opt.AllowNegativePosition = true + _, err = fl.Seek(0, 0) + if err == nil { + pdf.ImageOptionsReader(imgStr, fl, -10, 50, 30, 0, false, opt, 0, "") + err = pdf.OutputFileAndClose(pdfStr) + } + fl.Close() } - pdf.ImageOptionsReader(example.ImageFile("logo.png"), bytes.NewReader(bytes),-10, 10, 30, 0, false, opt, 0, "") - opt.AllowNegativePosition = true - pdf.ImageOptionsReader(example.ImageFile("logo.png"),bytes.NewReader(bytes), -10, 50, 30, 0, false, opt, 0, "") - fileStr := example.Filename("Fpdf_ImageOptionsReader") - err := pdf.OutputFileAndClose(fileStr) - example.Summary(err, fileStr) + example.Summary(err, pdfStr) // Output: // Successfully generated pdf/Fpdf_ImageOptionsReader.pdf } -- cgit v1.2.1-24-ge1ad From d17d13df9df41d4505501e831ff0ada5b2222ff8 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 20 Jul 2019 12:23:47 -0400 Subject: Remove ImageOptionsReader and rework example to demonstrate RegisterImageOptionsReader() --- fpdf.go | 67 ------------------------------------------------------------ fpdf_test.go | 40 ++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 87 deletions(-) diff --git a/fpdf.go b/fpdf.go index 319e89d..ca48fb5 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2986,73 +2986,6 @@ func (f *Fpdf) ImageOptions(imageNameStr string, x, y, w, h float64, flow bool, return } -// ImageOptionsReader registers an image, reading it from Reader r, and puts a -// JPEG, PNG or GIF image in the current page. The size it will take on the -// page can be specified in different ways. If both w and h are 0, the image -// is rendered at 96 dpi. If either w or h is zero, it will be calculated from -// the other dimension so that the aspect ratio is maintained. If w and/or h are -1, -// the dpi for that dimension will be read from the ImageInfoType object. PNG -// files can contain dpi information, and if present, this information will be -// populated in the ImageInfoType object and used in Width, Height, and Extent -// calculations. Otherwise, the SetDpi function can be used to change the dpi -// from the default of 72. -// -// If w and h are any other negative value, their absolute values -// indicate their dpi extents. -// -// Supported JPEG formats are 24 bit, 32 bit and gray scale. Supported PNG -// formats are 24 bit, indexed color, and 8 bit indexed gray scale. If a GIF -// image is animated, only the first frame is rendered. Transparency is -// supported. It is possible to put a link on the image. -// -// imageNameStr may be the name of an image as registered with a call to either -// RegisterImageReader() or RegisterImage(). In the first case, the image is -// loaded using an io.Reader. This is generally useful when the image is -// obtained from some other means than as a disk-based file. In the second -// case, the image is loaded as a file. Alternatively, imageNameStr may -// directly specify a sufficiently qualified filename. -// -// r is an io.Reader that implements the Read() function -// -// However the image is loaded, if it is used more than once only one copy is -// embedded in the file. -// -// If x is negative, the current abscissa is used. -// -// If flow is true, the current y value is advanced after placing the image and -// a page break may be made if necessary. -// -// If link refers to an internal page anchor (that is, it is non-zero; see -// AddLink()), the image will be a clickable internal link. Otherwise, if -// linkStr specifies a URL, the image will be a clickable external link. -func (f *Fpdf) ImageOptionsReader(imageNameStr string, r io.Reader, x, y, w, h float64, flow bool, options ImageOptions, link int, linkStr string) { - if f.err != nil { - return - } - - var info *ImageInfoType - - i, ok := f.images[imageNameStr] - if ok { - info = i - } else { - if options.ImageType == "" { - pos := strings.LastIndex(imageNameStr, ".") - if pos < 0 { - f.err = fmt.Errorf("image file has no extension and no type was specified: %s", imageNameStr) - return - } - options.ImageType = imageNameStr[pos+1:] - } - info = f.RegisterImageOptionsReader(imageNameStr, options, r) - if f.err != nil { - return - } - } - f.imageOut(info, x, y, w, h, options.AllowNegativePosition, flow, link, linkStr) - return -} - // RegisterImageReader registers an image, reading it from Reader r, adding it // to the PDF file but not adding it to the page. // diff --git a/fpdf_test.go b/fpdf_test.go index 54de6c2..63c28c5 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -858,37 +858,37 @@ func ExampleFpdf_ImageOptions() { // Successfully generated pdf/Fpdf_ImageOptions.pdf } -// ImageOption struct can be used to affect horizontal image placement. -func ExampleFpdf_ImageOptionsReader() { - var opt gofpdf.ImageOptions - var pdfStr, imgStr string - var fl *os.File - var err error +// ExampleFpdf_RegisterImageOptionsReader demonstrates how to load an image +// from a io.Reader (in this case, a file) and register it with options. +func ExampleFpdf_RegisterImageOptionsReader() { + var ( + opt gofpdf.ImageOptions + pdfStr string + fl *os.File + err error + ) - pdfStr = example.Filename("Fpdf_ImageOptionsReader") + pdfStr = example.Filename("Fpdf_RegisterImageOptionsReader") pdf := gofpdf.New("P", "mm", "A4", "") pdf.AddPage() pdf.SetFont("Arial", "", 11) - pdf.SetX(60) - opt.ImageType = "png" - imgStr = example.ImageFile("logo.png") - fl, err = os.Open(imgStr) + fl, err = os.Open(example.ImageFile("logo.png")) if err == nil { - pdf.ImageOptionsReader(imgStr, fl, -10, 10, 30, 0, false, opt, 0, "") + opt.ImageType = "png" opt.AllowNegativePosition = true - _, err = fl.Seek(0, 0) - if err == nil { - pdf.ImageOptionsReader(imgStr, fl, -10, 50, 30, 0, false, opt, 0, "") - err = pdf.OutputFileAndClose(pdfStr) - } + _ = pdf.RegisterImageOptionsReader("logo", opt, fl) fl.Close() + for x := -20.0; x <= 40.0; x += 5 { + pdf.ImageOptions("logo", x, x+30, 0, 0, false, opt, 0, "") + } + err = pdf.OutputFileAndClose(pdfStr) } example.Summary(err, pdfStr) // Output: - // Successfully generated pdf/Fpdf_ImageOptionsReader.pdf + // Successfully generated pdf/Fpdf_RegisterImageOptionsReader.pdf } -// This examples demonstrates Landscape mode with images. +// This example demonstrates Landscape mode with images. func ExampleFpdf_SetAcceptPageBreakFunc() { var y0 float64 var crrntCol int @@ -948,7 +948,7 @@ func ExampleFpdf_SetAcceptPageBreakFunc() { // Successfully generated pdf/Fpdf_SetAcceptPageBreakFunc_landscape.pdf } -// This examples tests corner cases as reported by the gocov tool. +// This example tests corner cases as reported by the gocov tool. func ExampleFpdf_SetKeywords() { var err error fileStr := example.Filename("Fpdf_SetKeywords") -- cgit v1.2.1-24-ge1ad From f3ee9b63d7affa5386053fe7c2b44c06ae4159d4 Mon Sep 17 00:00:00 2001 From: matthias Date: Fri, 9 Aug 2019 14:31:01 +0200 Subject: update contrib/gofpdi from v1.0.3 to v1.0.7 and expose new functionality * imports pdf documents from any io.ReadSeeker * exposes page sizes of imported pdf documents --- contrib/gofpdi/gofpdi.go | 24 ++++++++++++++++++++++++ go.mod | 3 +-- go.sum | 3 +++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go index b951ea3..58f8fae 100644 --- a/contrib/gofpdi/gofpdi.go +++ b/contrib/gofpdi/gofpdi.go @@ -2,6 +2,7 @@ package gofpdi import ( realgofpdi "github.com/phpdave11/gofpdi" + "io" ) // Create new gofpdi instance @@ -23,7 +24,21 @@ type gofpdiPdf interface { func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { // Set source file for fpdi fpdi.SetSourceFile(sourceFile) + // return template id + return getTemplateID(f, pageno, box) +} +// ImportPage imports a page of a PDF with the specified box (/MediaBox, +// /TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id that can +// be used with UseImportedTemplate to draw the template onto the page. +func ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int { + // Set source stream for fpdi + fpdi.SetSourceStream(rs) + // return template id + return getTemplateID(f, pageno, box) +} + +func getTemplateID(f gofpdiPdf, pageno int, box string) int { // Import page tpl := fpdi.ImportPage(pageno, box) @@ -61,3 +76,12 @@ func UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64 f.UseImportedTemplate(tplName, scaleX, scaleY, tX, tY) } + +// GetPageSizes returns page dimensions for all pages of the imported pdf. +// Result consists of map[]map[]map[]. +// : page number, note that page numbers start at 1 +// : box identifier, e.g. "/MediaBox" +// : dimension string, either "w" or "h" +func GetPageSizes() map[int]map[string]map[string]float64 { + return fpdi.GetPageSizes() +} diff --git a/go.mod b/go.mod index 2610432..6af14f1 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,7 @@ go 1.12 require ( github.com/boombuler/barcode v1.0.0 - github.com/phpdave11/gofpdi v1.0.3 - github.com/pkg/errors v0.8.1 // indirect + github.com/phpdave11/gofpdi v1.0.7 github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec ) diff --git a/go.sum b/go.sum index 1ed062b..917bb71 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,9 @@ github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/phpdave11/gofpdi v1.0.3/go.mod h1:B7ryN7q4MLItB8BDM5PJAplblJegAAcaI98viOZUihg= +github.com/phpdave11/gofpdi v1.0.7 h1:k2oy4yhkQopCK+qW8KjCla0iU2RpDow+QUDmH9DDt44= +github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -- cgit v1.2.1-24-ge1ad From 7c5006543b654248bb1fb640703faf0a53f59f71 Mon Sep 17 00:00:00 2001 From: Brigham Thompson Date: Sun, 11 Aug 2019 20:52:54 -0700 Subject: adds RoundedRect per Issue #272 --- fpdf.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ fpdf_test.go | 13 +++++++++++++ 2 files changed, 62 insertions(+) diff --git a/fpdf.go b/fpdf.go index ca48fb5..46d57df 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1103,6 +1103,55 @@ func (f *Fpdf) Rect(x, y, w, h float64, styleStr string) { f.outf("%.2f %.2f %.2f %.2f re %s", x*f.k, (f.h-y)*f.k, w*f.k, -h*f.k, fillDrawOp(styleStr)) } +// RoundedRect outputs a rectangle of width w and height h with the upper left +// corner positioned at point (x, y). It can be drawn (border only), filled +// (with no border) or both. styleStr can be "F" for filled, "D" for outlined +// only, or "DF" or "FD" for outlined and filled. An empty string will be replaced +// with "D". Drawing uses the current draw color and line width centered on the +// rectangle's perimeter. Filling uses the current fill color. The rounded corners +// of the rectangle are specified by radius r. corners runs clockwise with 1 at the +// top left corner. +func (f *Fpdf) RoundedRect(x, y, w, h, r float64, corners string, stylestr string) { + k := f.k + hp := f.h + myArc := (4.0 / 3.0) * (math.Sqrt2 - 1.0) + f.outf("q %.5f %.5f m", (x+r)*k, (hp-y)*k) + xc := x + w - r + yc := y + r + f.outf("%.5f %.5f l", xc*k, (hp-y)*k) + if strings.Contains(corners, "2") == false { + f.outf("%.5f %.5f l", (x+w)*k, (hp-y)*k) + } else { + f.clipArc(xc+r*myArc, yc-r, xc+r, yc-r*myArc, xc+r, yc) + } + xc = x + w - r + yc = y + h - r + f.outf("%.5f %.5f l", (x+w)*k, (hp-yc)*k) + if strings.Contains(corners, "3") == false { + f.outf("%.5f %.5f l", (x+w)*k, (hp-(y + h))*k) + } else { + f.clipArc(xc+r, yc+r*myArc, xc+r*myArc, yc+r, xc, yc+r) + } + xc = x + r + yc = y + h - r + f.outf("%.5f %.5f l", xc*k, (hp-(y+h))*k) + if strings.Contains(corners, "4") == false { + f.outf("%.5f %.5f l", x*k, (hp-(y+h))*k) + } else { + f.clipArc(xc-r*myArc, yc+r, xc-r, yc+r*myArc, xc-r, yc) + } + xc = x + r + yc = y + r + f.outf("%.5f %.5f l", x*k, (hp-yc)*k) + if strings.Contains(corners, "1") == false { + f.outf("%.5f %.5f l", x*k, (hp-y)*k) + f.outf("%.5f %.5f l", (x+r)*k, (hp-y)*k) + } else { + f.clipArc(xc-r, yc-r*myArc, xc-r*myArc, yc-r, xc, yc-r) + f.outf(" re %s", fillDrawOp(stylestr)) + } +} + // Circle draws a circle centered on point (x, y) with radius r. // // styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for diff --git a/fpdf_test.go b/fpdf_test.go index 63c28c5..08814e0 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2639,3 +2639,16 @@ func ExampleUTF8CutFont() { // Output: // Successfully generated pdf/Fpdf_UTF8CutFont.pdf } + +func ExampleFpdf_RoundedRect() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFillColor(160, 160, 160) + pdf.SetLineWidth(0.5) + pdf.RoundedRect(70, 30, 68, 46, 20, "1234", "FD") + fileStr := example.Filename("Fpdf_RoundedRect") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_RoundedRect.pdf +} -- cgit v1.2.1-24-ge1ad From 0d44f4b8df0f8964427cbaaa5eb70f98ae56a0ca Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 12 Aug 2019 09:20:09 -0400 Subject: Revise comment, fix style write, extend example for RoundedRect --- fpdf.go | 83 +++++++++++++++++++++++++++++++----------------------------- fpdf_test.go | 56 ++++++++++++++++++++++++++++++++-------- 2 files changed, 89 insertions(+), 50 deletions(-) diff --git a/fpdf.go b/fpdf.go index 46d57df..28f69cf 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1106,50 +1106,53 @@ func (f *Fpdf) Rect(x, y, w, h float64, styleStr string) { // RoundedRect outputs a rectangle of width w and height h with the upper left // corner positioned at point (x, y). It can be drawn (border only), filled // (with no border) or both. styleStr can be "F" for filled, "D" for outlined -// only, or "DF" or "FD" for outlined and filled. An empty string will be replaced -// with "D". Drawing uses the current draw color and line width centered on the -// rectangle's perimeter. Filling uses the current fill color. The rounded corners -// of the rectangle are specified by radius r. corners runs clockwise with 1 at the -// top left corner. +// only, or "DF" or "FD" for outlined and filled. An empty string will be +// replaced with "D". Drawing uses the current draw color and line width +// centered on the rectangle's perimeter. Filling uses the current fill color. +// The rounded corners of the rectangle are specified by radius r. corners is a +// string that includes "1" to round the upper left corner, "2" to round the +// upper right corner, "3" to round the lower right corner, and "4" to round +// the lower left corner. The RoundedRect example demonstrates this method. func (f *Fpdf) RoundedRect(x, y, w, h, r float64, corners string, stylestr string) { - k := f.k - hp := f.h - myArc := (4.0 / 3.0) * (math.Sqrt2 - 1.0) - f.outf("q %.5f %.5f m", (x+r)*k, (hp-y)*k) - xc := x + w - r + // This routine was adapted by Brigham Thompson from a script by Christophe Prugnaud + k := f.k + hp := f.h + myArc := r * (4.0 / 3.0) * (math.Sqrt2 - 1.0) + f.outf("q %.5f %.5f m", (x+r)*k, (hp-y)*k) + xc := x + w - r yc := y + r - f.outf("%.5f %.5f l", xc*k, (hp-y)*k) - if strings.Contains(corners, "2") == false { - f.outf("%.5f %.5f l", (x+w)*k, (hp-y)*k) - } else { - f.clipArc(xc+r*myArc, yc-r, xc+r, yc-r*myArc, xc+r, yc) - } - xc = x + w - r + f.outf("%.5f %.5f l", xc*k, (hp-y)*k) + if strings.Contains(corners, "2") == false { + f.outf("%.5f %.5f l", (x+w)*k, (hp-y)*k) + } else { + f.clipArc(xc+myArc, yc-r, xc+r, yc-myArc, xc+r, yc) + } + xc = x + w - r + yc = y + h - r + f.outf("%.5f %.5f l", (x+w)*k, (hp-yc)*k) + if strings.Contains(corners, "3") == false { + f.outf("%.5f %.5f l", (x+w)*k, (hp-(y+h))*k) + } else { + f.clipArc(xc+r, yc+myArc, xc+myArc, yc+r, xc, yc+r) + } + xc = x + r yc = y + h - r - f.outf("%.5f %.5f l", (x+w)*k, (hp-yc)*k) - if strings.Contains(corners, "3") == false { - f.outf("%.5f %.5f l", (x+w)*k, (hp-(y + h))*k) - } else { - f.clipArc(xc+r, yc+r*myArc, xc+r*myArc, yc+r, xc, yc+r) - } - xc = x + r - yc = y + h - r - f.outf("%.5f %.5f l", xc*k, (hp-(y+h))*k) - if strings.Contains(corners, "4") == false { - f.outf("%.5f %.5f l", x*k, (hp-(y+h))*k) - } else { - f.clipArc(xc-r*myArc, yc+r, xc-r, yc+r*myArc, xc-r, yc) - } - xc = x + r + f.outf("%.5f %.5f l", xc*k, (hp-(y+h))*k) + if strings.Contains(corners, "4") == false { + f.outf("%.5f %.5f l", x*k, (hp-(y+h))*k) + } else { + f.clipArc(xc-myArc, yc+r, xc-r, yc+myArc, xc-r, yc) + } + xc = x + r yc = y + r - f.outf("%.5f %.5f l", x*k, (hp-yc)*k) - if strings.Contains(corners, "1") == false { - f.outf("%.5f %.5f l", x*k, (hp-y)*k) - f.outf("%.5f %.5f l", (x+r)*k, (hp-y)*k) - } else { - f.clipArc(xc-r, yc-r*myArc, xc-r*myArc, yc-r, xc, yc-r) - f.outf(" re %s", fillDrawOp(stylestr)) - } + f.outf("%.5f %.5f l", x*k, (hp-yc)*k) + if strings.Contains(corners, "1") == false { + f.outf("%.5f %.5f l", x*k, (hp-y)*k) + f.outf("%.5f %.5f l", (x+r)*k, (hp-y)*k) + } else { + f.clipArc(xc-r, yc-myArc, xc-myArc, yc-r, xc, yc-r) + } + f.out(fillDrawOp(stylestr)) } // Circle draws a circle centered on point (x, y) with radius r. diff --git a/fpdf_test.go b/fpdf_test.go index 08814e0..c6020f3 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2641,14 +2641,50 @@ func ExampleUTF8CutFont() { } func ExampleFpdf_RoundedRect() { - pdf := gofpdf.New("P", "mm", "A4", "") - pdf.AddPage() - pdf.SetFillColor(160, 160, 160) - pdf.SetLineWidth(0.5) - pdf.RoundedRect(70, 30, 68, 46, 20, "1234", "FD") - fileStr := example.Filename("Fpdf_RoundedRect") - err := pdf.OutputFileAndClose(fileStr) - example.Summary(err, fileStr) - // Output: - // Successfully generated pdf/Fpdf_RoundedRect.pdf + const ( + wd = 40.0 + hgap = 10.0 + radius = 10.0 + ht = 60.0 + vgap = 10.0 + ) + corner := func(b1, b2, b3, b4 bool) (cstr string) { + if b1 { + cstr = "1" + } + if b2 { + cstr += "2" + } + if b3 { + cstr += "3" + } + if b4 { + cstr += "4" + } + return + } + pdf := gofpdf.New("P", "mm", "A4", "") // 210 x 297 + pdf.AddPage() + pdf.SetLineWidth(0.5) + y := vgap + r := 40 + g := 30 + b := 20 + for row := 0; row < 4; row++ { + x := hgap + for col := 0; col < 4; col++ { + pdf.SetFillColor(r, g, b) + pdf.RoundedRect(x, y, wd, ht, radius, corner(row&1 == 1, row&2 == 2, col&1 == 1, col&2 == 2), "FD") + r += 8 + g += 10 + b += 12 + x += wd + hgap + } + y += ht + vgap + } + fileStr := example.Filename("Fpdf_RoundedRect") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_RoundedRect.pdf } -- cgit v1.2.1-24-ge1ad From a9a0e5d100759b0563d809ea80eae2c33cc4599a Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 12 Aug 2019 10:36:31 -0400 Subject: Acknowledge Brigham Thompson's contribution. --- README.md | 3 ++- doc.go | 3 ++- doc/document.md | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 811bbc3..38ef38d 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,8 @@ are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added -support for imported objects and templates. +support for imported objects and templates. Brigham Thompson added +support for rounded rectangles. ## Roadmap diff --git a/doc.go b/doc.go index 6ad0461..b3721e7 100644 --- a/doc.go +++ b/doc.go @@ -256,7 +256,8 @@ are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added -support for imported objects and templates. +support for imported objects and templates. Brigham Thompson added +support for rounded rectangles. Roadmap diff --git a/doc/document.md b/doc/document.md index fa544af..d7d84cd 100644 --- a/doc/document.md +++ b/doc/document.md @@ -228,6 +228,7 @@ templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added support for imported objects and templates. +Brigham Thompson added support for rounded rectangles. ## Roadmap -- cgit v1.2.1-24-ge1ad From fdac35522f22a910970fc07bd6922f4f53ba6642 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 12 Aug 2019 10:52:03 -0400 Subject: Corrected comment to match function name --- contrib/gofpdi/gofpdi.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go index 58f8fae..e600fb1 100644 --- a/contrib/gofpdi/gofpdi.go +++ b/contrib/gofpdi/gofpdi.go @@ -28,9 +28,10 @@ func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { return getTemplateID(f, pageno, box) } -// ImportPage imports a page of a PDF with the specified box (/MediaBox, -// /TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id that can -// be used with UseImportedTemplate to draw the template onto the page. +// ImportPageFromStream imports a page of a PDF with the specified box +// (/MediaBox, TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id +// that can be used with UseImportedTemplate to draw the template onto the +// page. func ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int { // Set source stream for fpdi fpdi.SetSourceStream(rs) -- cgit v1.2.1-24-ge1ad From abb2841fca8cde49264525e891960687315a3908 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 12 Aug 2019 10:56:47 -0400 Subject: Run go mod tidy --- go.sum | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/go.sum b/go.sum index 917bb71..f642b76 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,18 @@ +github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/phpdave11/gofpdi v1.0.3/go.mod h1:B7ryN7q4MLItB8BDM5PJAplblJegAAcaI98viOZUihg= github.com/phpdave11/gofpdi v1.0.7 h1:k2oy4yhkQopCK+qW8KjCla0iU2RpDow+QUDmH9DDt44= github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 h1:nlG4Wa5+minh3S9LVFtNoY+GVRiudA2e3EVfcCi3RCA= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec h1:arXJwtMuk5vqI1NHX0UTnNw977rYk5Sl4jQqHj+hun4= golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -- cgit v1.2.1-24-ge1ad From e697c5fb90d8afbc84be98bfec2154653e03382b Mon Sep 17 00:00:00 2001 From: matthias Date: Tue, 13 Aug 2019 14:03:28 +0200 Subject: wrap contrib/gofpdi:realgofpdi.Importer * allow for multiple independent Importer instances * keep a default Importer for backwards compatibility * add package level comment --- contrib/gofpdi/gofpdi.go | 87 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 16 deletions(-) diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go index e600fb1..7b9c822 100644 --- a/contrib/gofpdi/gofpdi.go +++ b/contrib/gofpdi/gofpdi.go @@ -1,3 +1,11 @@ +/* +Package gofpdi wraps the gofpdi PDF library to import existing PDFs as templates. See github.com/phpdave11/gofpdi +for further information and examples. + +Users should call NewImporter() to obtain their own Importer instance to work with. +To retain backwards compatibility, the package offers a default Importer that may be used via global functions. Note +however that use of the default Importer is not thread safe. +*/ package gofpdi import ( @@ -5,9 +13,6 @@ import ( "io" ) -// Create new gofpdi instance -var fpdi = realgofpdi.NewImporter() - // gofpdiPdf is a partial interface that only implements the functions we need // from the PDF generator to put the imported PDF templates on the PDF. type gofpdiPdf interface { @@ -18,49 +23,61 @@ type gofpdiPdf interface { SetError(err error) } +// Importer wraps an Importer from the gofpdi library. +type Importer struct { + fpdi *realgofpdi.Importer +} + +// NewImporter creates a new Importer wrapping functionality from the gofpdi library. +func NewImporter() *Importer { + return &Importer{ + fpdi: realgofpdi.NewImporter(), + } +} + // ImportPage imports a page of a PDF file with the specified box (/MediaBox, // /TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id that can // be used with UseImportedTemplate to draw the template onto the page. -func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { +func (i *Importer) ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { // Set source file for fpdi - fpdi.SetSourceFile(sourceFile) + i.fpdi.SetSourceFile(sourceFile) // return template id - return getTemplateID(f, pageno, box) + return i.getTemplateID(f, pageno, box) } // ImportPageFromStream imports a page of a PDF with the specified box // (/MediaBox, TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id // that can be used with UseImportedTemplate to draw the template onto the // page. -func ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int { +func (i *Importer) ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int { // Set source stream for fpdi - fpdi.SetSourceStream(rs) + i.fpdi.SetSourceStream(rs) // return template id - return getTemplateID(f, pageno, box) + return i.getTemplateID(f, pageno, box) } -func getTemplateID(f gofpdiPdf, pageno int, box string) int { +func (i *Importer) getTemplateID(f gofpdiPdf, pageno int, box string) int { // Import page - tpl := fpdi.ImportPage(pageno, box) + tpl := i.fpdi.ImportPage(pageno, box) // Import objects into current pdf document // Unordered means that the objects will be returned with a sha1 hash instead of an integer // The objects themselves may have references to other hashes which will be replaced in ImportObjects() - tplObjIDs := fpdi.PutFormXobjectsUnordered() + tplObjIDs := i.fpdi.PutFormXobjectsUnordered() // Set template names and ids (hashes) in gofpdf f.ImportTemplates(tplObjIDs) // Get a map[string]string of the imported objects. // The map keys will be the ID of each object. - imported := fpdi.GetImportedObjectsUnordered() + imported := i.fpdi.GetImportedObjectsUnordered() // Import gofpdi objects into gofpdf f.ImportObjects(imported) // Get a map[string]map[int]string of the object hashes and their positions within each object, // to be replaced with object ids (integers). - importedObjPos := fpdi.GetImportedObjHashPos() + importedObjPos := i.fpdi.GetImportedObjHashPos() // Import gofpdi object hashes and their positions into gopdf f.ImportObjPos(importedObjPos) @@ -71,9 +88,9 @@ func getTemplateID(f gofpdiPdf, pageno int, box string) int { // UseImportedTemplate draws the template onto the page at x,y. If w is 0, the // template will be scaled to fit based on h. If h is 0, the template will be // scaled to fit based on w. -func UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) { +func (i *Importer) UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) { // Get values from fpdi - tplName, scaleX, scaleY, tX, tY := fpdi.UseTemplate(tplid, x, y, w, h) + tplName, scaleX, scaleY, tX, tY := i.fpdi.UseTemplate(tplid, x, y, w, h) f.UseImportedTemplate(tplName, scaleX, scaleY, tX, tY) } @@ -83,6 +100,44 @@ func UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64 // : page number, note that page numbers start at 1 // : box identifier, e.g. "/MediaBox" // : dimension string, either "w" or "h" +func (i *Importer) GetPageSizes() map[int]map[string]map[string]float64 { + return i.fpdi.GetPageSizes() +} + +// Default Importer used by global functions +var fpdi = NewImporter() + +// ImportPage imports a page of a PDF file with the specified box (/MediaBox, +// /TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id that can +// be used with UseImportedTemplate to draw the template onto the page. +// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer. +func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { + return fpdi.ImportPage(f, sourceFile, pageno, box) +} + +// ImportPageFromStream imports a page of a PDF with the specified box +// (/MediaBox, TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id +// that can be used with UseImportedTemplate to draw the template onto the +// page. +// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer. +func ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int { + return fpdi.ImportPageFromStream(f, rs, pageno, box) +} + +// UseImportedTemplate draws the template onto the page at x,y. If w is 0, the +// template will be scaled to fit based on h. If h is 0, the template will be +// scaled to fit based on w. +// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer. +func UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) { + fpdi.UseImportedTemplate(f, tplid, x, y, w, h) +} + +// GetPageSizes returns page dimensions for all pages of the imported pdf. +// Result consists of map[]map[]map[]. +// : page number, note that page numbers start at 1 +// : box identifier, e.g. "/MediaBox" +// : dimension string, either "w" or "h" +// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer. func GetPageSizes() map[int]map[string]map[string]float64 { return fpdi.GetPageSizes() } -- cgit v1.2.1-24-ge1ad From 94823924d17ac5bdb913c7c212a82a1ff746356a Mon Sep 17 00:00:00 2001 From: Tim S Date: Thu, 15 Aug 2019 14:39:41 +0200 Subject: Add method `SetProducer` This allows changing or removing the PDF producer string in the metadata of the PDF file. --- def.go | 1 + fpdf.go | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/def.go b/def.go index efa573e..95da6ba 100644 --- a/def.go +++ b/def.go @@ -563,6 +563,7 @@ type Fpdf struct { zoomMode string // zoom display mode layoutMode string // layout display mode xmp []byte // XMP metadata + producer string // producer title string // title subject string // subject author string // author diff --git a/fpdf.go b/fpdf.go index 28f69cf..377f152 100644 --- a/fpdf.go +++ b/fpdf.go @@ -198,6 +198,7 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) f.gradientList = append(f.gradientList, gradientType{}) // gradientList[0] is unused // Set default PDF version number f.pdfVersion = "1.3" + f.SetProducer("FPDF "+cnFpdfVersion, true) f.layerInit() f.catalogSort = gl.catalogSort f.creationDate = gl.creationDate @@ -559,6 +560,15 @@ func (f *Fpdf) SetCompression(compress bool) { f.compress = compress } +// SetProducer defines the producer of the document. isUTF8 indicates if the string +// is encoded in ISO-8859-1 (false) or UTF-8 (true). +func (f *Fpdf) SetProducer(producerStr string, isUTF8 bool) { + if isUTF8 { + producerStr = utf8toutf16(producerStr) + } + f.producer = producerStr +} + // SetTitle defines the title of the document. isUTF8 indicates if the string // is encoded in ISO-8859-1 (false) or UTF-8 (true). func (f *Fpdf) SetTitle(titleStr string, isUTF8 bool) { @@ -4473,7 +4483,9 @@ func (f *Fpdf) putresources() { func (f *Fpdf) putinfo() { var tm time.Time - f.outf("/Producer %s", f.textstring("FPDF "+cnFpdfVersion)) + if len(f.producer) > 0 { + f.outf("/Producer %s", f.textstring(f.producer)) + } if len(f.title) > 0 { f.outf("/Title %s", f.textstring(f.title)) } -- cgit v1.2.1-24-ge1ad From 03b1cc4baaf3f7c9ae441b711e18fdd5671a5dd4 Mon Sep 17 00:00:00 2001 From: matthias Date: Thu, 15 Aug 2019 17:27:56 +0200 Subject: add simple example --- contrib/gofpdi/gofpdi_test.go | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 contrib/gofpdi/gofpdi_test.go diff --git a/contrib/gofpdi/gofpdi_test.go b/contrib/gofpdi/gofpdi_test.go new file mode 100644 index 0000000..1ecc5ca --- /dev/null +++ b/contrib/gofpdi/gofpdi_test.go @@ -0,0 +1,52 @@ +package gofpdi + +import ( + "bytes" + "github.com/jung-kurt/gofpdf" + "github.com/jung-kurt/gofpdf/internal/example" + "io" +) + +func ExampleGofpdiImporter() { + // create new pdf + pdf := gofpdf.New("P", "pt", "A4", "") + + // for testing purposes, get an arbitrary template pdf as stream + rs, _ := getTemplatePdf() + + // create a new Importer instance + imp := NewImporter() + + // import first page and determine page sizes + tpl := imp.ImportPageFromStream(pdf, &rs, 1, "/MediaBox") + pageSizes := imp.GetPageSizes() + nrPages := len(imp.GetPageSizes()) + + // add all pages from template pdf + for i := 1; i <= nrPages; i++ { + pdf.AddPage() + if i > 1 { + tpl = imp.ImportPageFromStream(pdf, &rs, i, "/MediaBox") + } + imp.UseImportedTemplate(pdf, tpl, 0, 0, pageSizes[i]["/MediaBox"]["w"], pageSizes[i]["/MediaBox"]["h"]) + } + + // output + fileStr := example.Filename("contrib_gofpdi_Importer") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated ../../pdf/contrib_gofpdi_Importer.pdf +} + +func getTemplatePdf() (io.ReadSeeker, error) { + tpdf := gofpdf.New("P", "pt", "A4", "") + tpdf.AddPage() + tpdf.SetFont("Arial", "", 12) + tpdf.Text(20, 20, "Example Page 1") + tpdf.AddPage() + tpdf.Text(20, 20, "Example Page 2") + tbuf := bytes.Buffer{} + err := tpdf.Output(&tbuf) + return bytes.NewReader(tbuf.Bytes()), err +} -- cgit v1.2.1-24-ge1ad From afaa377e877515c31a941b4c88953e20ead17255 Mon Sep 17 00:00:00 2001 From: matthias Date: Thu, 15 Aug 2019 17:33:26 +0200 Subject: add simple test for data race detection --- contrib/gofpdi/gofpdi_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/contrib/gofpdi/gofpdi_test.go b/contrib/gofpdi/gofpdi_test.go index 1ecc5ca..77db338 100644 --- a/contrib/gofpdi/gofpdi_test.go +++ b/contrib/gofpdi/gofpdi_test.go @@ -5,6 +5,8 @@ import ( "github.com/jung-kurt/gofpdf" "github.com/jung-kurt/gofpdf/internal/example" "io" + "sync" + "testing" ) func ExampleGofpdiImporter() { @@ -39,6 +41,29 @@ func ExampleGofpdiImporter() { // Successfully generated ../../pdf/contrib_gofpdi_Importer.pdf } +func TestGofpdiConcurrent(t *testing.T) { + wg := sync.WaitGroup{} + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + defer wg.Done() + pdf := gofpdf.New("P", "mm", "A4", "") + rs, _ := getTemplatePdf() + imp := NewImporter() + tpl := imp.ImportPageFromStream(pdf, &rs, 1, "/MediaBox") + pdf.AddPage() + tpl = imp.ImportPageFromStream(pdf, &rs, 1, "/MediaBox") + imp.UseImportedTemplate(pdf, tpl, 0, 0, 210.0, 297.0) + // write to bytes buffer + buf := bytes.Buffer{} + if err := pdf.Output(&buf); err != nil { + t.Fail() + } + }() + } + wg.Wait() +} + func getTemplatePdf() (io.ReadSeeker, error) { tpdf := gofpdf.New("P", "pt", "A4", "") tpdf.AddPage() -- cgit v1.2.1-24-ge1ad From dab6c0551d4d91973e1bb91341619885e48797a9 Mon Sep 17 00:00:00 2001 From: matthias Date: Thu, 15 Aug 2019 17:55:42 +0200 Subject: fix checks --- contrib/gofpdi/gofpdi_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contrib/gofpdi/gofpdi_test.go b/contrib/gofpdi/gofpdi_test.go index 77db338..70ef6cc 100644 --- a/contrib/gofpdi/gofpdi_test.go +++ b/contrib/gofpdi/gofpdi_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -func ExampleGofpdiImporter() { +func ExampleNewImporter() { // create new pdf pdf := gofpdf.New("P", "pt", "A4", "") @@ -48,11 +48,10 @@ func TestGofpdiConcurrent(t *testing.T) { go func() { defer wg.Done() pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() rs, _ := getTemplatePdf() imp := NewImporter() tpl := imp.ImportPageFromStream(pdf, &rs, 1, "/MediaBox") - pdf.AddPage() - tpl = imp.ImportPageFromStream(pdf, &rs, 1, "/MediaBox") imp.UseImportedTemplate(pdf, tpl, 0, 0, 210.0, 297.0) // write to bytes buffer buf := bytes.Buffer{} -- cgit v1.2.1-24-ge1ad From 33558d447b489420d1bbc1cb9188f963cb6abda1 Mon Sep 17 00:00:00 2001 From: hyzgh <31174102+hyzgh@users.noreply.github.com> Date: Tue, 20 Aug 2019 19:50:37 +0800 Subject: improve the speed of MultiCell Change-Id: Ieaacbf19acfce1e776eccbfa3bbc030a2ab93d5f --- fpdf.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fpdf.go b/fpdf.go index 377f152..747346f 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2596,11 +2596,12 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill ls := 0 ns := 0 nl := 1 + srune := []rune(s) for i < nb { // Get next character var c rune if f.isCurrentUTF8 { - c = []rune(s)[i] + c = srune[i] } else { c = rune(byte(s[i])) } @@ -2620,7 +2621,7 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill newAlignStr = "L" } } - f.CellFormat(w, h, string([]rune(s)[j:i]), b, 2, newAlignStr, fill, 0, "") + f.CellFormat(w, h, string(srune[j:i]), b, 2, newAlignStr, fill, 0, "") } else { f.CellFormat(w, h, s[j:i], b, 2, alignStr, fill, 0, "") } @@ -2656,7 +2657,7 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill f.out("0 Tw") } if f.isCurrentUTF8 { - f.CellFormat(w, h, string([]rune(s)[j:i]), b, 2, alignStr, fill, 0, "") + f.CellFormat(w, h, string(srune[j:i]), b, 2, alignStr, fill, 0, "") } else { f.CellFormat(w, h, s[j:i], b, 2, alignStr, fill, 0, "") } @@ -2670,7 +2671,7 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill f.outf("%.3f Tw", f.ws*f.k) } if f.isCurrentUTF8 { - f.CellFormat(w, h, string([]rune(s)[j:sep]), b, 2, alignStr, fill, 0, "") + f.CellFormat(w, h, string(srune[j:sep]), b, 2, alignStr, fill, 0, "") } else { f.CellFormat(w, h, s[j:sep], b, 2, alignStr, fill, 0, "") } @@ -2704,7 +2705,7 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill alignStr = "" } } - f.CellFormat(w, h, string([]rune(s)[j:i]), b, 2, alignStr, fill, 0, "") + f.CellFormat(w, h, string(srune[j:i]), b, 2, alignStr, fill, 0, "") } else { f.CellFormat(w, h, s[j:i], b, 2, alignStr, fill, 0, "") } -- cgit v1.2.1-24-ge1ad From 5cb8bab84fe08b93191ed0385c016592d2ac7cc4 Mon Sep 17 00:00:00 2001 From: hyzgh <31174102+hyzgh@users.noreply.github.com> Date: Tue, 20 Aug 2019 19:50:37 +0800 Subject: fix split line bug Change-Id: I224a7ec1af8386dcbef757c76389fb88316401bc --- fpdf.go | 17 ++++++++++------- splittext.go | 3 +-- util.go | 8 ++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/fpdf.go b/fpdf.go index 747346f..7c53811 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2551,20 +2551,23 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill } wmax := int(math.Ceil((w - 2*f.cMargin) * 1000 / f.fontSize)) s := strings.Replace(txtStr, "\r", "", -1) + srune := []rune(s) + // remove extra line breaks var nb int if f.isCurrentUTF8 { - nb = len([]rune(s)) - for nb > 0 && []rune(s)[nb-1] == '\n' { + nb = len(srune) + for nb > 0 && srune[nb-1] == '\n' { nb-- - s = string([]rune(s)[0:nb]) } + srune = srune[0:nb] } else { nb = len(s) - if nb > 0 && []byte(s)[nb-1] == '\n' { + bytes2 := []byte(s) + for nb > 0 && bytes2[nb-1] == '\n' { nb-- - s = s[0:nb] } + s = s[0:nb] } // dbg("[%s]\n", s) var b, b2 string @@ -2603,7 +2606,7 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill if f.isCurrentUTF8 { c = srune[i] } else { - c = rune(byte(s[i])) + c = rune(s[i]) } if c == '\n' { // Explicit line break @@ -2636,7 +2639,7 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill } continue } - if c == ' ' { + if c == ' ' || isChinese(c) { sep = i ls = l ns++ diff --git a/splittext.go b/splittext.go index 3902199..525f93b 100644 --- a/splittext.go +++ b/splittext.go @@ -26,8 +26,7 @@ func (f *Fpdf) SplitText(txt string, w float64) (lines []string) { for i < nb { c := s[i] l += cw[c] - if unicode.IsSpace(c) { - // if c == ' ' || c == '\t' || c == '\n' { + if unicode.IsSpace(c) || isChinese(c) { sep = i } if c == '\n' || l > wmax { diff --git a/util.go b/util.go index 3902500..99a1ba5 100644 --- a/util.go +++ b/util.go @@ -444,3 +444,11 @@ func remove(arr []int, key int) []int { } return append(arr[:n], arr[n+1:]...) } + +func isChinese(rune2 rune) bool { + // chinese unicode: 4e00-9fa5 + if rune2 >= rune(0x4e00) && rune2 <= rune(0x9fa5) { + return true + } + return false +} -- cgit v1.2.1-24-ge1ad From 106ebb343df00b76335e7932cb74baf76be0b09e Mon Sep 17 00:00:00 2001 From: hyzgh <31174102+hyzgh@users.noreply.github.com> Date: Wed, 21 Aug 2019 18:30:32 +0800 Subject: fix split line bug Change-Id: I4fdf3b7b23fbb2340427d06a7eadd88e081effb6 --- fpdf.go | 1 - 1 file changed, 1 deletion(-) diff --git a/fpdf.go b/fpdf.go index 7c53811..d64a324 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2599,7 +2599,6 @@ func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill ls := 0 ns := 0 nl := 1 - srune := []rune(s) for i < nb { // Get next character var c rune -- cgit v1.2.1-24-ge1ad From 06680f145154e962a17ba7aaf33ab597ce83ef2e Mon Sep 17 00:00:00 2001 From: Joe Westcott Date: Thu, 22 Aug 2019 22:31:52 +0100 Subject: Add SetUnderlineThickness method --- def.go | 4 +++- fpdf.go | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/def.go b/def.go index 95da6ba..7fddc82 100644 --- a/def.go +++ b/def.go @@ -452,6 +452,7 @@ type Pdf interface { SetTextSpotColor(nameStr string, tint byte) SetTitle(titleStr string, isUTF8 bool) SetTopMargin(margin float64) + SetUnderlineThickness(thickness float64) SetXmpMetadata(xmpStream []byte) SetX(x float64) SetXY(x, y float64) @@ -595,7 +596,8 @@ type Fpdf struct { // Composite values of colors draw, fill, text colorType } - spotColorMap map[string]spotColorType // Map of named ink-based colors + spotColorMap map[string]spotColorType // Map of named ink-based colors + userUnderlineThickness float64 // A custom user underline thickness multiplier. } type encType struct { diff --git a/fpdf.go b/fpdf.go index d64a324..f77717f 100644 --- a/fpdf.go +++ b/fpdf.go @@ -202,6 +202,7 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) f.layerInit() f.catalogSort = gl.catalogSort f.creationDate = gl.creationDate + f.userUnderlineThickness = 1 return } @@ -3538,10 +3539,16 @@ func blankCount(str string) (count int) { return } +// SetUnderlineThickness accepts a multiplier for adjusting the text underline +// thickness, defaulting to 1. See SetUnderlineThickness example. +func (f *Fpdf) SetUnderlineThickness(thickness float64) { + f.userUnderlineThickness = thickness +} + // Underline text func (f *Fpdf) dounderline(x, y float64, txt string) string { up := float64(f.currentFont.Up) - ut := float64(f.currentFont.Ut) + ut := float64(f.currentFont.Ut) * f.userUnderlineThickness w := f.GetStringWidth(txt) + f.ws*float64(blankCount(txt)) return sprintf("%.2f %.2f %.2f %.2f re f", x*f.k, (f.h-(y-up/1000*f.fontSize))*f.k, w*f.k, -ut/1000*f.fontSizePt) -- cgit v1.2.1-24-ge1ad From 1f076cb96ab154628c2f1087099e2d6159476e65 Mon Sep 17 00:00:00 2001 From: Joe Westcott Date: Thu, 22 Aug 2019 22:32:16 +0100 Subject: Add test for SetUnderlineThickness --- fpdf_test.go | 23 +++++++++++++++++++++++ pdf/reference/Fpdf_UnderlineThickness.pdf | Bin 0 -> 1156 bytes 2 files changed, 23 insertions(+) create mode 100644 pdf/reference/Fpdf_UnderlineThickness.pdf diff --git a/fpdf_test.go b/fpdf_test.go index c6020f3..43cea30 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2688,3 +2688,26 @@ func ExampleFpdf_RoundedRect() { // Output: // Successfully generated pdf/Fpdf_RoundedRect.pdf } + +// ExampleFpdf_SetUnderlineThickness demonstrates how to adjust the text +// underline thickness. +func ExampleFpdf_SetUnderlineThickness() { + pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm + pdf.AddPage() + pdf.SetFont("Arial", "U", 12) + + pdf.SetUnderlineThickness(0.5) + pdf.CellFormat(0, 10, "Thin underline", "", 1, "", false, 0, "") + + pdf.SetUnderlineThickness(1) + pdf.CellFormat(0, 10, "Normal underline", "", 1, "", false, 0, "") + + pdf.SetUnderlineThickness(2) + pdf.CellFormat(0, 10, "Thicker underline", "", 1, "", false, 0, "") + + fileStr := example.Filename("Fpdf_UnderlineThickness") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_UnderlineThickness.pdf +} diff --git a/pdf/reference/Fpdf_UnderlineThickness.pdf b/pdf/reference/Fpdf_UnderlineThickness.pdf new file mode 100644 index 0000000..49ad9b1 Binary files /dev/null and b/pdf/reference/Fpdf_UnderlineThickness.pdf differ -- cgit v1.2.1-24-ge1ad From ed240cb3be2b6e232a4944f9ae13cc762735e86c Mon Sep 17 00:00:00 2001 From: Joe Westcott Date: Fri, 23 Aug 2019 12:06:16 +0100 Subject: Add DS_Store to gitignore (#292) --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 87a2697..1fae316 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ doc/body.md doc/index.html doc/index.html.ok coverage.html + +# macOS +.DS_Store \ No newline at end of file -- cgit v1.2.1-24-ge1ad From 7b84d27f314deae8fab88961e3b835cea57f13cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20St=C3=B6ckl?= Date: Wed, 28 Aug 2019 16:46:46 +0200 Subject: added SVG support for horizontal and vertical lines --- svgbasic.go | 21 ++++++++++++++++++++- svgwrite.go | 19 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/svgbasic.go b/svgbasic.go index cc35073..6900afa 100644 --- a/svgbasic.go +++ b/svgbasic.go @@ -31,7 +31,9 @@ func init() { pathCmdSub = strings.NewReplacer(",", " ", "L", " L ", "l", " l ", "C", " C ", "c", " c ", - "M", " M ", "m", " m ") + "M", " M ", "m", " m ", + "H", " H ", "h", " h ", + "V", " V ", "v", " v ") } // SVGBasicSegmentType describes a single curve or position segment @@ -79,6 +81,19 @@ func absolutizePath(segs []SVGBasicSegmentType) { segPtr.Cmd = 'C' x = segPtr.Arg[4] y = segPtr.Arg[5] + case 'H': + x = seg.Arg[0] + case 'h': + segPtr.Arg[0] += x + segPtr.Cmd = 'H' + x += seg.Arg[0] + case 'V': + y = seg.Arg[0] + case 'v': + segPtr.Arg[0] += y + segPtr.Cmd = 'V' + y += seg.Arg[0] + } } } @@ -127,8 +142,12 @@ func pathParse(pathStr string) (segs []SVGBasicSegmentType, err error) { setup(2) case 'C', 'c': // Absolute/relative Bézier curve: cx0, cy0, cx1, cy1, x1, y1 setup(6) + case 'H', 'h': // Absolute/relative horizontal line to: x + setup(1) case 'L', 'l': // Absolute/relative lineto: x, y setup(2) + case 'V', 'v': // Absolute/relative vertical line to: x + setup(1) case 'Z', 'z': // closepath instruction (takes no arguments) break default: diff --git a/svgwrite.go b/svgwrite.go index 7e455fb..a612539 100644 --- a/svgwrite.go +++ b/svgwrite.go @@ -29,8 +29,17 @@ func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { var cx0, cy0, cx1, cy1 float64 var path []SVGBasicSegmentType var seg SVGBasicSegmentType + sval := func(origin float64, arg int) float64 { + return origin + scale*seg.Arg[arg] + } + xval := func(arg int) float64 { + return sval(originX, arg) + } + yval := func(arg int) float64 { + return sval(originY, arg) + } val := func(arg int) (float64, float64) { - return originX + scale*seg.Arg[arg], originY + scale*seg.Arg[arg+1] + return xval(arg), yval(arg + 1) } for j := 0; j < len(sb.Segments) && f.Ok(); j++ { path = sb.Segments[j] @@ -50,6 +59,14 @@ func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { newX, newY = val(4) f.CurveCubic(x, y, cx0, cy0, newX, newY, cx1, cy1, "D") x, y = newX, newY + case 'H': + newX = xval(0) + f.Line(x, y, newX, y) + x = newX + case 'V': + newY = yval(0) + f.Line(x, y, x, newY) + y = newY case 'Z': f.Line(x, y, originX, originY) default: -- cgit v1.2.1-24-ge1ad From 936c634e15265fb3c7239e07c71fc3c6ac027d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20St=C3=B6ckl?= Date: Wed, 28 Aug 2019 17:10:23 +0200 Subject: added SVG support for quadratic curves --- svgbasic.go | 14 +++++++++++++- svgwrite.go | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/svgbasic.go b/svgbasic.go index 6900afa..0eea754 100644 --- a/svgbasic.go +++ b/svgbasic.go @@ -33,7 +33,8 @@ func init() { "C", " C ", "c", " c ", "M", " M ", "m", " m ", "H", " H ", "h", " h ", - "V", " V ", "v", " v ") + "V", " V ", "v", " v ", + "Q", " Q ", "q", " q ", ) } // SVGBasicSegmentType describes a single curve or position segment @@ -81,6 +82,15 @@ func absolutizePath(segs []SVGBasicSegmentType) { segPtr.Cmd = 'C' x = segPtr.Arg[4] y = segPtr.Arg[5] + case 'Q': + x = seg.Arg[2] + y = seg.Arg[3] + case 'q': + adjust(0, x, y) + adjust(2, x, y) + segPtr.Cmd = 'Q' + x = segPtr.Arg[2] + y = segPtr.Arg[3] case 'H': x = seg.Arg[0] case 'h': @@ -146,6 +156,8 @@ func pathParse(pathStr string) (segs []SVGBasicSegmentType, err error) { setup(1) case 'L', 'l': // Absolute/relative lineto: x, y setup(2) + case 'Q', 'q': // Absolute/relative quadratic curve: x0, y0, x1, y1 + setup(4) case 'V', 'v': // Absolute/relative vertical line to: x setup(1) case 'Z', 'z': // closepath instruction (takes no arguments) diff --git a/svgwrite.go b/svgwrite.go index a612539..d438393 100644 --- a/svgwrite.go +++ b/svgwrite.go @@ -59,6 +59,11 @@ func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { newX, newY = val(4) f.CurveCubic(x, y, cx0, cy0, newX, newY, cx1, cy1, "D") x, y = newX, newY + case 'Q': + cx0, cy0 = val(0) + newX, newY = val(2) + f.Curve(x, y, cx0, cy0, newX, newY, "D") + x, y = newX, newY case 'H': newX = xval(0) f.Line(x, y, newX, y) -- cgit v1.2.1-24-ge1ad From 761de3879c5b4b3e0b7d2d9d30ced3aa56f8a39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20St=C3=B6ckl?= Date: Wed, 28 Aug 2019 19:05:11 +0200 Subject: added closepath support in SVG --- svgbasic.go | 8 +++++--- svgwrite.go | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/svgbasic.go b/svgbasic.go index 0eea754..51a93fe 100644 --- a/svgbasic.go +++ b/svgbasic.go @@ -34,7 +34,8 @@ func init() { "M", " M ", "m", " m ", "H", " H ", "h", " h ", "V", " V ", "v", " v ", - "Q", " Q ", "q", " q ", ) + "Q", " Q ", "q", " q ", + "Z", " Z ", "z", " z ") } // SVGBasicSegmentType describes a single curve or position segment @@ -103,7 +104,8 @@ func absolutizePath(segs []SVGBasicSegmentType) { segPtr.Arg[0] += y segPtr.Cmd = 'V' y += seg.Arg[0] - + case 'z': + segPtr.Cmd = 'Z' } } } @@ -161,7 +163,7 @@ func pathParse(pathStr string) (segs []SVGBasicSegmentType, err error) { case 'V', 'v': // Absolute/relative vertical line to: x setup(1) case 'Z', 'z': // closepath instruction (takes no arguments) - break + segs = append(segs, seg) default: err = fmt.Errorf("expecting SVG path command at position %d, got %s", j, str) } diff --git a/svgwrite.go b/svgwrite.go index d438393..7045199 100644 --- a/svgwrite.go +++ b/svgwrite.go @@ -29,6 +29,7 @@ func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { var cx0, cy0, cx1, cy1 float64 var path []SVGBasicSegmentType var seg SVGBasicSegmentType + var startX, startY float64 sval := func(origin float64, arg int) float64 { return origin + scale*seg.Arg[arg] } @@ -48,6 +49,7 @@ func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { switch seg.Cmd { case 'M': x, y = val(0) + startX, startY = x, y f.SetXY(x, y) case 'L': newX, newY = val(0) @@ -73,7 +75,7 @@ func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { f.Line(x, y, x, newY) y = newY case 'Z': - f.Line(x, y, originX, originY) + f.Line(x, y, startX, startY) default: f.SetErrorf("Unexpected path command '%c'", seg.Cmd) } -- cgit v1.2.1-24-ge1ad From dd51a599c9b1e52e1479d8a6f6e7d802431cf8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20St=C3=B6ckl?= Date: Wed, 28 Aug 2019 19:07:43 +0200 Subject: updated SVG comments --- svgbasic.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/svgbasic.go b/svgbasic.go index 51a93fe..f75d69f 100644 --- a/svgbasic.go +++ b/svgbasic.go @@ -160,7 +160,7 @@ func pathParse(pathStr string) (segs []SVGBasicSegmentType, err error) { setup(2) case 'Q', 'q': // Absolute/relative quadratic curve: x0, y0, x1, y1 setup(4) - case 'V', 'v': // Absolute/relative vertical line to: x + case 'V', 'v': // Absolute/relative vertical line to: y setup(1) case 'Z', 'z': // closepath instruction (takes no arguments) segs = append(segs, seg) @@ -201,7 +201,8 @@ type SVGBasicType struct { // information generated by jSignature, is supported. The returned path data // includes only the commands 'M' (absolute moveto: x, y), 'L' (absolute // lineto: x, y), 'C' (absolute cubic Bézier curve: cx0, cy0, cx1, cy1, -// x1,y1) and 'Z' (closepath). +// x1,y1), 'Q' (absolute quadratic Bézier curve: x0, y0, x1, y1) and 'Z' +// (closepath). func SVGBasicParse(buf []byte) (sig SVGBasicType, err error) { type pathType struct { D string `xml:"d,attr"` -- cgit v1.2.1-24-ge1ad From 409472296c9a05767ffb4478f1b9690ca75139d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20St=C3=B6ckl?= Date: Wed, 28 Aug 2019 20:37:17 +0200 Subject: attached z, q, h, and v instructions to the Fpdf_SVGBasicWrite --- image/signature.svg | 72 +- pdf/reference/Fpdf_SVGBasicWrite.pdf | 1207 +++++++++++++++++++++++++--------- 2 files changed, 930 insertions(+), 349 deletions(-) diff --git a/image/signature.svg b/image/signature.svg index cdbb4af..956c3c6 100644 --- a/image/signature.svg +++ b/image/signature.svg @@ -1,43 +1,73 @@ - + + d="m 234.43804,111.69821 c 50.21866,26.50627 126.75595,-3.87395 151.46369,-35.941621 24.70774,-32.067668 10.41159,-51.980992 -16.41089,-58.072772 -26.82248,-6.09178 -42.17661,10.494756 -57.68933,33.13636 -15.51272,22.641602 -22.3395,49.640453 -26.04984,89.319923 -3.71034,39.67947 -2.57151,103.67609 -16.65175,144.69433 -14.08024,41.01824 -40.79012,59.98014 -80.0876,71.50199 -39.29748,11.52185 -96.607494,6.67866 -126.372407,-24.20296 -29.764916,-30.88162 -24.693439,-84.55794 0.62001,-107.05538 25.313453,-22.49744 49.916587,-21.8463 53.386947,18.74456 3.47036,40.59086 -77.347635,106.99944 -102.157295,102.59574 -24.80966,-4.4037 -9.1930819,0 -13.78962288,0" /> + d="m 535.44946,262.31206 c 16.02735,-13.54645 29.98118,-31.39768 32.51139,-52.84016 1.4974,-10.24434 -1.94415,-22.06454 -11.64632,-27.13714 -22.66026,-14.31032 -51.37591,-9.68663 -75.27088,-1.12303 -29.57925,11.19994 -56.66841,28.48168 -80.87983,48.69857 -15.56749,13.48245 -30.31327,28.65126 -40.17476,46.87113 -10.56334,25.04076 5.93271,58.80187 33.76392,62.35287 20.97698,3.69753 41.31134,-5.15667 59.15595,-15.26739 23.68053,-12.07041 45.37059,-27.68722 65.11773,-45.42392 5.85816,-4.99109 11.66007,-10.04795 17.4228,-15.14884" /> + d="m 605.17805,221.06416 c -39.71057,22.89155 -90.21146,57.33437 -110.62013,81.46882 -20.40867,24.13445 1.74636,32.16167 21.51346,33.96557 19.7671,1.8039 40.22731,-5.81242 63.90833,-18.83825 23.68102,-13.02583 54.88215,-39.05314 73.09016,-60.24005 18.20801,-21.18691 37.84165,-41.69088 43.78312,-57.46575 5.94147,-15.77487 6.81292,-20.38898 -2.3045,-26.03079" /> + d="m 576.69736,336.95111 c 59.46452,-49.53559 110.50457,-110.94455 181.15663,-145.53797 21.55772,-14.53068 69.21456,-30.38164 74.52476,8.12435 2.15457,32.87115 -24.99905,56.36851 -41.3729,81.85669 -11.33394,14.91071 -34.85688,47.22341 -38.29416,51.12061 38.40925,-59.07476 94.0006,-105.23813 152.94098,-142.74425 21.53324,-14.17578 76.3474,-17.732 63.14039,22.44093 -6.44013,30.30909 -29.58192,52.20309 -51.31162,72.13403 -22.35245,20.18703 -11.93986,55.81184 21.21245,48.89199 28.04358,-1.72994 49.86098,-21.80465 73.62851,-34.51546 51.0484,-39.90132 89.3284,-97.12351 150.3008,-123.60116 30.7216,-12.02494 70.5868,-23.14241 98.2954,1.38478 22.9075,21.32517 9.8573,56.2678 -7.0675,76.93906 -18.1931,26.99594 -44.6741,46.96256 -74.8471,58.94304 -34.0583,20.33195 -79.3725,18.48794 -110.8061,-6.03301 -1.0838,-0.69666 -2.2533,-1.23366 -3.4004,-1.81269" /> + d="m 1145.2696,144.64925 c -19.2615,48.72397 -39.2763,98.0821 -71.8076,139.71403 -28.4578,44.00142 -46.4445,94.33551 -79.72453,135.30113 -23.78316,32.93768 -48.80204,65.54924 -80.01549,91.86673 -19.47895,6.1922 -20.04137,-20.7923 -14.66105,-32.91267 12.83153,-36.25521 37.22095,-66.57625 54.90924,-100.3885 22.07476,-38.69659 54.05253,-69.56182 85.74383,-100.24739" /> + d="m 1067.4918,308.53814 c 41.6055,37.74324 106.1656,40.87499 155.2476,16.47425 79.7307,-33.80513 147.627,-88.69981 215.7912,-140.91414 38.5692,-31.19936 75.8068,-66.58379 98.2999,-111.442691 5.2858,-16.340836 11.2358,-38.191353 -2.3042,-51.988823 -24.8579,-9.392422 -44.7459,19.21292 -62.7133,32.466761 -42.206,41.159272 -75.9104,90.348773 -105.7076,140.969903 -18.1332,33.9424 -36.3441,60.40033 -45.1009,105.84746 -4.8684,25.26636 17.3519,40.01019 38.489,36.24378 27.2382,-1.27906 52.1821,-14.06224 77.2642,-23.5167 20.2617,-9.77194 38.052,-23.75443 55.7341,-37.47313" /> + d="m 1509.1585,216.87147 c 45.3671,35.48031 84.7434,37.23796 135.7328,25.17331 14.925,-4.86754 25.7515,-17.97315 30.1445,-32.73996 6.2047,-12.9545 -0.2899,-27.91555 -12.929,-33.8982 -19.5006,-12.36806 -44.6888,-10.55607 -64.9092,-0.92535 -33.4028,14.45512 -59.4353,40.93033 -84.563,66.45243 -13.9248,16.55902 -22.671,38.06079 -22.9956,59.74639 0.7543,12.73146 10.7427,22.65661 22.5942,25.94215 28.6381,11.95988 61.6748,18.05546 91.8527,8.36881 20.1474,-7.27059 39.868,-15.91987 58.8894,-25.73255 22.7573,-13.36221 41.3454,-32.41648 60.072,-50.72036" /> + d="m 1779.9918,343.26036 c 28.6993,3.03127 63.3496,2.62457 82.7159,-22.45172 21.6447,-19.99229 43.1941,-48.10952 35.6329,-79.45221 -4.1368,-22.17497 -33.5802,-38.22486 -52.1616,-22.03003 -31.7488,22.47063 -31.372,70.25063 -12.8813,101.12391 23.6727,38.55114 74.0602,50.51158 116.164,41.35476 54.0203,-10.31179 104.4208,-53.87389 110.9357,-110.27278 0.7888,-32.83995 0.7757,-65.72269 4.9445,-98.36663 3.9298,-42.7466 9.9471,-89.084405 39.2166,-122.675002 17.104,-18.491716 51.2258,-26.9233518 69.4545,-5.555968 14.6931,19.194858 3.0296,45.294939 -10.7419,61.486039 -16.3416,25.138501 -48.7197,29.136431 -75.3811,36.237431 -26.4792,5.77658 -58.6276,2.75073 -76.1034,-20.51069 -9.6512,-10.713121 -20.4603,-22.768271 -20.6837,-38.053993" /> + d="m 2245.2696,122.42703 c -3.9166,0.81691 -6.5582,5.39919 -5.219,9.18763 1.2777,3.63173 4.3682,6.64885 8.1357,7.58096 2.108,0.12035 4.1149,-1.67454 4.2375,-3.78089 0.7885,-3.73488 0.2701,-7.91813 -2.1144,-10.99661 -1.2461,-1.37634 -3.1464,-2.37225 -5.0398,-1.99109" /> + d="m 2219.5751,170.3437 c -29.9457,39.95653 -58.8628,80.7409 -86.118,122.56461 -5.4378,11.43956 -6.9218,27.24913 2.6137,36.94004 11.5344,8.50012 26.6093,3.95387 39.1614,0.62975 31.967,-8.46295 63.2786,-21.86206 88.264,-43.97857 15.2095,-12.48824 29.1196,-26.55137 41.4956,-41.85028" /> + d="m 2487.38,203.45563 c -3.3292,-19.2489 -24.4513,-30.55681 -42.8081,-28.63327 -39.0192,-1.47124 -74.6768,18.22839 -106.1126,39.27122 -27.4601,19.28281 -52.9628,45.12902 -62.0025,78.30592 -2.9108,24.00347 18.676,49.02117 43.417,46.57579 41.4005,-0.49369 78.4941,-23.55071 108.3115,-50.5202 26.5153,-22.3804 52.8121,-49.50782 59.1947,-84.99946" /> + d="m 2515.4085,226.5937 c -48.3542,24.84206 -95.4271,57.89871 -121.9801,106.67545 -38.548,57.86235 -85.0736,109.83278 -130.7587,162.02483 -14.3416,13.79585 -31.8449,28.78802 -52.8206,28.38924 -22.4201,-5.81296 -20.145,-35.44311 -3.7589,-46.92382 18.3472,-20.65863 39.7594,-38.46949 61.3752,-55.55681 37.3089,-27.01631 74.2659,-55.34905 116.5753,-74.2272 45.8819,-21.27356 92.5741,-41.44894 133.4511,-71.77058" /> + d="m 2561.9362,176.5937 c -11.728,39.55572 -31.7885,76.05727 -54.1537,110.51619 -11.367,17.27415 -23.5479,34.0347 -36.8185,49.90047" /> + d="m 2471.6585,334.92703 c 39.4203,-54.93792 84.2673,-108.82208 144.2119,-142.13528 20.4555,-10.53089 43.6781,-13.18946 66.1233,-16.24748 15.4075,-2.13385 35.1588,8.90133 33.4692,26.24623 -2.9508,16.37726 -14.16,29.73489 -22.9962,43.3486 -13.3021,19.00229 -30.5436,36.66009 -36.611,59.58253 -4.3581,18.38699 14.1449,34.91044 31.9547,29.10574 16.8023,-4.83584 31.073,-15.60156 46.3125,-23.86514 23.356,-14.17855 45.5509,-30.69352 63.9244,-51.0352" /> + d="m 2945.2696,276.5937 c 22.3825,-18.04222 43.6601,-40.96167 49.1836,-70.14766 1.6596,-16.7076 -14.1662,-31.70685 -30.5059,-31.31677 -38.4972,-6.9588 -76.9683,9.1156 -108.0208,30.84253 -27.6063,19.08076 -55.1974,41.48489 -69.2262,72.82154 -7.1903,18.94072 -2.0574,44.40278 17.325,53.92146 22.3966,12.66022 50.5757,7.55107 71.8376,-5.02642 25.3952,-13.7463 46.7256,-33.50699 69.4067,-51.09468" /> + d="m 3032.0751,221.03814 c -34.9663,24.39777 -159.9904,94.46573 -91.1404,111.19476 49.5078,12.02932 120.689,-54.55505 178.2367,-101.75128 57.5477,-47.19623 164.1423,-136.348841 176.2724,-205.706175 12.1301,-69.357335 -35.8274,25.038279 -57.6617,62.402284 -21.8343,37.364011 -53.1817,114.582201 -93.4244,175.681151 -55.9422,84.93494 14.2268,97.70016 78.695,54.07139 43.4593,-29.41104 56.0463,-39.23804 79.8558,-64.64213" /> + d="m 3119.5751,163.39925 c 51.3284,2.8018 102.806,4.27265 154.1667,1.38889" /> + d="m 3359.1585,166.17703 c -26.0554,38.94967 -53.443,76.90675 -75.3826,118.80876 -8.2374,15.73252 -12.8945,40.55439 6.2938,47.64921 25.3545,6.43589 34.5616,-2.95338 49.294,-7.34667 48.0292,-19.31164 87.8533,-54.50776 122.854,-93.37814 15.42,-20.923 30.5124,-42.09003 46.9408,-62.26134" /> + d="m 3511.2418,168.95481 c -31.3786,34.96488 -59.3857,72.92099 -84.9995,112.24284 -6.288,13.61689 -16.1644,29.28735 -9.8599,44.58789 7.0942,13.41865 25.2642,10.69636 37.6171,7.93765 31.8778,-9.70921 58.1068,-31.49347 83.8755,-51.77583 20.5616,-16.72078 38.3203,-36.60992 53.5974,-58.18739 14.5478,-17.73424 29.2159,-35.93086 39.6787,-56.3568 4.934,-18.95097 -28.1547,-19.20088 -17.7187,-0.12487 9.5405,17.82935 32.3392,18.53167 50.1021,19.48194 16.3122,-3.37266 23.3898,15.5346 12.9603,26.5127 -6.8718,8.02389 -13.7478,15.769 -19.1588,24.9829 -16.8576,24.69747 -36.847,48.68268 -44.6449,78.10881 -3.0723,19.33042 19.5849,33.62972 36.7818,27.38476 35.6706,-8.34057 67.9833,-26.49985 99.2689,-44.93349" /> + d="m 3763.3251,216.87147 c 33.1817,22.33062 74.828,35.62344 114.8149,27.5851 15.6821,-3.20582 30.2525,-10.71137 43.1524,-19.942 17.3248,-14.2012 16.9209,-44.79145 -2.1675,-57.28603 -13.4925,-8.89012 -30.6833,-5.87659 -45.6599,-3.46265 -33.5763,7.00049 -61.9142,28.29846 -85.8989,51.8761 -25.4017,22.73023 -42.112,57.70516 -36.9155,92.17467 6.3894,18.1743 25.3211,28.36102 43.6991,29.78005 26.397,2.30348 52.8197,-3.96515 77.6246,-12.547 39.816,-14.49663 75.2011,-38.73414 108.0175,-65.12268" /> + + + + + + + + + + + + + + + diff --git a/pdf/reference/Fpdf_SVGBasicWrite.pdf b/pdf/reference/Fpdf_SVGBasicWrite.pdf index bc05a2b..b6cc82a 100644 --- a/pdf/reference/Fpdf_SVGBasicWrite.pdf +++ b/pdf/reference/Fpdf_SVGBasicWrite.pdf @@ -7,335 +7,884 @@ /Contents 4 0 R>> endobj 4 0 obj -<> +<> stream 0 J 0 j 0.57 w -BT /F0 16.00 Tf ET +BT /Fd08375f64eb9861c6eae4dfcfdbd3500fbdbe33e 16.00 Tf ET 0.000 G 0.000 g -BT 31.19 800.74 Td (This example renders a simple ) Tj ET -q 0.000 0.000 0.502 rg BT 230.70 800.74 Td (SVG) Tj ET 230.70 799.14 32.00 -0.80 re f Q -BT 262.70 800.74 Td ( \(scalable vector graphics\) image that contains) Tj ET -BT 31.18 784.74 Td (only basic path commands without any styling, color fill, reflection or endpoint) Tj ET -BT 31.18 768.74 Td (closures. In particular, the type of vector graphic returned from a ) Tj ET -q 0.000 0.000 0.502 rg BT 450.17 768.74 Td (jSignature) Tj ET 450.17 767.14 65.78 -0.80 re f Q -BT 515.95 768.74 Td ( web) Tj ET -BT 31.18 752.74 Td (control is supported and is used in this example.) Tj ET +BT /Fd08375f64eb9861c6eae4dfcfdbd3500fbdbe33e 16.00 Tf ET +BT 31.19 800.74 Td (This example renders a simple )Tj ET +BT /Fd08375f64eb9861c6eae4dfcfdbd3500fbdbe33e 16.00 Tf ET +q 0.000 0.000 0.502 rg BT 230.70 800.74 Td (SVG)Tj ET 230.70 799.14 32.00 -0.80 re f Q +BT /Fd08375f64eb9861c6eae4dfcfdbd3500fbdbe33e 16.00 Tf ET +BT 262.70 800.74 Td ( \(scalable vector graphics\) image that contains)Tj ET +BT 31.18 784.74 Td (only basic path commands without any styling, color fill, reflection or endpoint)Tj ET +BT 31.18 768.74 Td (closures. In particular, the type of vector graphic returned from a )Tj ET +BT /Fd08375f64eb9861c6eae4dfcfdbd3500fbdbe33e 16.00 Tf ET +q 0.000 0.000 0.502 rg BT 450.17 768.74 Td (jSignature)Tj ET 450.17 767.14 65.78 -0.80 re f Q +BT /Fd08375f64eb9861c6eae4dfcfdbd3500fbdbe33e 16.00 Tf ET +BT 515.95 768.74 Td ( web)Tj ET +BT 31.18 752.74 Td (control is supported and is used in this example.)Tj ET 1 J 0.71 w 0.000 0.000 0.502 RG -173.14 728.26 m -176.69201 726.39095 182.10238 728.53851 183.84896 730.80536 c S -183.85 730.81 m -185.59553 733.07220 184.58495 734.47986 182.68888 734.91049 c S -182.69 734.91 m -180.79282 735.34111 179.70744 734.16862 178.61086 732.56810 c S -178.61 732.57 m -177.51427 730.96757 177.03169 729.05904 176.76941 726.25412 c S -176.77 726.25 m -176.50713 723.44920 176.58763 718.92532 175.59231 716.02576 c S -175.59 716.03 m -174.59698 713.12621 172.70888 711.78580 169.93096 710.97133 c S -169.93 710.97 m -167.15304 710.15686 163.10183 710.49922 160.99777 712.68222 c S -161.00 712.68 m -158.89370 714.86523 159.25220 718.65958 161.04160 720.24991 c S -161.04 720.25 m -162.83099 721.84024 164.57017 721.79421 164.81549 718.92486 c S -164.82 718.92 m -165.06081 716.05552 159.34783 711.36114 157.59405 711.67243 c S -157.59 711.67 m -155.84027 711.98373 156.94420 711.67243 156.61927 711.67243 c S -194.42 717.62 m -195.55336 718.57545 196.53975 719.83734 196.71861 721.35310 c S -196.72 721.35 m -196.82446 722.07726 196.58118 722.91283 195.89534 723.27141 c S -195.90 723.27 m -194.29350 724.28299 192.26361 723.95615 190.57449 723.35079 c S -190.57 723.35 m -188.48355 722.55908 186.56863 721.33744 184.85714 719.90832 c S -184.86 719.91 m -183.75668 718.95525 182.71431 717.88298 182.01721 716.59503 c S -182.02 716.60 m -181.27049 714.82491 182.43659 712.43836 184.40396 712.18734 c S -184.40 712.19 m -185.88681 711.92596 187.32423 712.55186 188.58566 713.26658 c S -188.59 713.27 m -190.25962 714.11983 191.79288 715.22377 193.18879 716.47757 c S -193.19 716.48 m -193.60290 716.83039 194.01304 717.18786 194.42040 717.54843 c S -199.35 720.53 m -196.54236 718.91546 192.97248 716.48071 191.52980 714.77466 c S -191.53 714.77 m -190.08712 713.06861 191.65325 712.50117 193.05058 712.37366 c S -193.05 712.37 m -194.44790 712.24614 195.89422 712.78453 197.56822 713.70532 c S -197.57 713.71 m -199.24222 714.62611 201.44780 716.46597 202.73492 717.96366 c S -202.73 717.96 m -204.02203 719.46135 205.40992 720.91076 205.82992 722.02588 c S -205.83 722.03 m -206.24992 723.14099 206.31152 723.46716 205.66702 723.86598 c S -197.34 712.34 m -201.53970 715.84331 205.14769 720.18427 210.14205 722.62966 c S -210.14 722.63 m -211.66595 723.65683 215.03478 724.77732 215.41016 722.05536 c S -215.41 722.06 m -215.56246 719.73171 213.64299 718.07070 212.48553 716.26895 c S -212.49 716.27 m -211.68434 715.21492 210.02152 712.93076 209.77854 712.65527 c S -209.78 712.66 m -212.49367 716.83123 216.42339 720.09449 220.58985 722.74578 c S -220.59 722.75 m -222.11202 723.74785 225.98680 723.99924 225.05321 721.15944 c S -225.05 721.16 m -224.59796 719.01691 222.96208 717.46923 221.42602 716.06033 c S -221.43 716.06 m -219.84594 714.63332 220.58200 712.11502 222.92551 712.60418 c S -222.93 712.60 m -224.90790 712.72647 226.45016 714.14554 228.13027 715.04406 c S -228.13 715.04 m -231.73885 717.86466 234.44484 721.90966 238.75494 723.78135 c S -238.75 723.78 m -240.92664 724.63139 243.74468 725.41728 245.70339 723.68346 c S -245.70 723.68 m -247.32271 722.17600 246.40020 719.70592 245.20379 718.24469 c S -245.20 718.24 m -243.91773 716.33636 242.04581 714.92493 239.91289 714.07804 c S -239.91 714.08 m -237.50533 712.64078 234.30210 712.77113 232.08008 714.50451 c S -232.08 714.50 m -232.00346 714.55375 231.92079 714.59171 231.83970 714.63264 c S -237.53 725.94 m -236.16664 722.49110 234.75181 719.00201 232.45219 716.05907 c S -232.45 716.06 m -230.44053 712.94864 229.16906 709.39055 226.81651 706.49471 c S -226.82 706.49 m -225.13530 704.16637 223.36673 701.86107 221.16026 700.00071 c S -221.16 700.00 m -219.78331 699.56298 219.74355 701.47050 220.12388 702.32728 c S -220.12 702.33 m -221.03094 704.89014 222.75501 707.03352 224.00539 709.42369 c S -224.01 709.42 m -225.56584 712.15913 227.82633 714.34097 230.06657 716.51012 c S -232.03 714.35 m -234.97123 711.68212 239.53495 711.46073 243.00452 713.18561 c S -243.00 713.19 m -248.64064 715.57527 253.44019 719.45575 258.25868 723.14675 c S -258.26 723.15 m -260.98511 725.35221 263.61742 727.85352 265.20744 731.02457 c S -265.21 731.02 m -265.58109 732.17969 266.00169 733.72429 265.04456 734.69963 c S -265.04 734.70 m -263.28737 735.36357 261.88150 733.34147 260.61139 732.40457 c S -260.61 732.40 m -257.62787 729.49504 255.24533 726.01787 253.13898 722.43949 c S -253.14 722.44 m -251.85716 720.04012 250.56984 718.16982 249.95083 714.95719 c S -249.95 714.96 m -249.60668 713.17113 251.17742 712.12890 252.67159 712.39514 c S -252.67 712.40 m -254.59704 712.48556 256.36031 713.38919 258.13335 714.05752 c S -258.13 714.06 m -259.56564 714.74830 260.82323 715.73671 262.07316 716.70648 c S -263.25 720.83 m -266.45830 718.32194 269.24179 718.19770 272.84620 719.05054 c S -272.85 719.05 m -273.90124 719.39462 274.66655 720.32105 274.97709 721.36491 c S -274.98 721.36 m -275.41570 722.28065 274.95660 723.33824 274.06315 723.76115 c S -274.06 723.76 m -272.68466 724.63544 270.90412 724.50736 269.47476 723.82657 c S -269.47 723.83 m -267.11353 722.80474 265.27331 720.93322 263.49705 719.12908 c S -263.50 719.13 m -262.51271 717.95853 261.89445 716.43859 261.87150 714.90564 c S -261.87 714.91 m -261.92482 714.00566 262.63090 713.30406 263.46867 713.07181 c S -263.47 713.07 m -265.49308 712.22637 267.82843 711.79548 269.96169 712.48022 c S -269.96 712.48 m -271.38589 712.99418 272.77993 713.60559 274.12454 714.29924 c S -274.12 714.30 m -275.73324 715.24381 277.04723 716.59074 278.37100 717.88463 c S -282.40 711.90 m -284.42511 711.68139 286.87452 711.71014 288.24351 713.48277 c S -288.24 713.48 m -289.77356 714.89601 291.29688 716.88360 290.76238 719.09920 c S -290.76 719.10 m -290.46995 720.66673 288.38862 721.80129 287.07511 720.65649 c S -287.08 720.66 m -284.83080 719.06805 284.85744 715.69051 286.16454 713.50810 c S -286.16 713.51 m -287.83794 710.78294 291.39981 709.93746 294.37610 710.58475 c S -294.38 710.58 m -298.19476 711.31369 301.75755 714.39307 302.21808 718.37987 c S -302.22 718.38 m -302.27384 720.70131 302.27291 723.02577 302.56760 725.33335 c S -302.57 725.33 m -302.84540 728.35509 303.27076 731.63068 305.33980 734.00518 c S -305.34 734.01 m -306.54888 735.31235 308.96093 735.90837 310.24950 734.39793 c S -310.25 734.40 m -311.28815 733.04105 310.46366 731.19605 309.49016 730.05151 c S -309.49 730.05 m -308.33498 728.27449 306.04620 727.99188 304.16152 727.48991 c S -304.16 727.49 m -302.28972 727.08157 300.01717 727.29546 298.78181 728.93980 c S -298.78 728.94 m -298.09957 729.69710 297.33548 730.54928 297.31969 731.62981 c S -315.29 727.51 m -315.00973 727.44850 314.82299 727.12458 314.91766 726.85678 c S -314.92 726.86 m -315.00798 726.60006 315.22645 726.38678 315.49277 726.32089 c S -315.49 726.32 m -315.64178 726.31238 315.78365 726.43926 315.79232 726.58816 c S -315.79 726.59 m -315.84805 726.85217 315.81141 727.14788 315.64285 727.36550 c S -315.64 727.37 m -315.55476 727.46279 315.42043 727.53319 315.28659 727.50625 c S -313.47 724.12 m -311.35342 721.29454 309.30928 718.41152 307.38263 715.45503 c S -307.38 715.46 m -306.99823 714.64637 306.89333 713.52880 307.56739 712.84376 c S -307.57 712.84 m -308.38275 712.24289 309.44839 712.56426 310.33569 712.79924 c S -310.34 712.80 m -312.59541 713.39748 314.80881 714.34466 316.57502 715.90806 c S -316.58 715.91 m -317.65017 716.79085 318.63346 717.78496 319.50832 718.86643 c S -332.40 721.78 m -332.16589 723.13908 330.67278 723.93843 329.37515 723.80245 c S -329.38 723.80 m -326.61691 723.90645 324.09629 722.51390 321.87411 721.02639 c S -321.87 721.03 m -319.93298 719.66330 318.13021 717.83625 317.49119 715.49099 c S -317.49 715.49 m -317.28543 713.79420 318.81139 712.02572 320.56032 712.19858 c S -320.56 712.20 m -323.48689 712.23348 326.10902 713.86336 328.21679 715.76982 c S -328.22 715.77 m -330.09114 717.35188 331.95005 719.26950 332.40123 721.77838 c S -334.38 720.14 m -330.96442 718.38670 327.63686 716.04994 325.75985 712.60194 c S -325.76 712.60 m -323.03491 708.51169 319.74605 704.83793 316.51659 701.14850 c S -316.52 701.15 m -315.50279 700.17328 314.26549 699.11349 312.78273 699.14168 c S -312.78 699.14 m -311.19787 699.55260 311.35870 701.64714 312.51702 702.45870 c S -312.52 702.46 m -313.81397 703.91905 315.32759 705.17809 316.85560 706.38598 c S -316.86 706.39 m -319.49294 708.29575 322.10541 710.29857 325.09624 711.63306 c S -325.10 711.63 m -328.33960 713.13687 331.64025 714.56306 334.52982 716.70648 c S -337.67 723.68 m -336.84252 720.88107 335.42446 718.30079 333.84347 715.86491 c S -333.84 715.86 m -333.03995 714.64381 332.17889 713.45902 331.24079 712.33748 c S -331.29 712.48 m -334.07649 716.36828 337.24670 720.17732 341.48414 722.53221 c S -341.48 722.53 m -342.93013 723.27663 344.57172 723.46456 346.15836 723.68073 c S -346.16 723.68 m -347.24751 723.83157 348.64372 723.05150 348.52428 721.82540 c S -348.52 721.83 m -348.31569 720.66770 347.52332 719.72346 346.89869 718.76111 c S -346.90 718.76 m -345.95837 717.41785 344.73958 716.16963 344.31068 714.54926 c S -344.31 714.55 m -344.00261 713.24949 345.31058 712.08146 346.56954 712.49179 c S -346.57 712.49 m -347.75729 712.83364 348.76607 713.59466 349.84334 714.17881 c S -349.84 714.18 m -351.49437 715.18108 353.06331 716.34851 354.36212 717.78645 c S -364.77 716.61 m -366.35139 717.88369 367.85549 719.50385 368.24594 721.56699 c S -368.25 721.57 m -368.36326 722.74804 367.24454 723.80833 366.08950 723.78076 c S -366.09 723.78 m -363.36815 724.27267 360.64865 723.13638 358.45357 721.60052 c S -358.45 721.60 m -356.50210 720.25171 354.55170 718.66798 353.56001 716.45281 c S -353.56 716.45 m -353.05173 715.11390 353.41457 713.31400 354.78470 712.64113 c S -354.78 712.64 m -356.36791 711.74619 358.35987 712.10735 359.86286 712.99644 c S -359.86 713.00 m -361.65803 713.96816 363.16587 715.36503 364.76918 716.60830 c S -370.91 720.54 m -368.43366 718.81082 359.59578 713.85776 364.46275 712.67519 c S -364.46 712.68 m -367.96243 711.82485 372.99419 716.53166 377.06220 719.86793 c S -377.06 719.87 m -381.13021 723.20421 388.66532 729.50635 389.52279 734.40918 c S -389.52 734.41 m -390.38026 739.31201 386.99017 732.63924 385.44672 729.99800 c S -385.45 730.00 m -383.90327 727.35676 381.68734 721.89825 378.84260 717.57920 c S -378.84 717.58 m -374.88808 711.57520 379.84829 710.67284 384.40551 713.75693 c S -384.41 713.76 m -387.47762 715.83598 388.36739 716.53064 390.05047 718.32644 c S -377.09 724.61 m -380.71911 724.41189 384.35803 724.30792 387.98869 724.51177 c S -394.03 724.41 m -392.18491 721.66026 390.24889 718.97709 388.69800 716.01507 c S -388.70 716.02 m -388.11570 714.90294 387.78649 713.14830 389.14290 712.64677 c S -389.14 712.65 m -390.93520 712.19182 391.58604 712.85554 392.62746 713.16610 c S -392.63 713.17 m -396.02262 714.53123 398.83776 717.01922 401.31194 719.76695 c S -401.31 719.77 m -402.40197 721.24598 403.46885 722.74227 404.63016 724.16817 c S -404.78 724.22 m -402.55929 721.74558 400.57949 719.06249 398.76886 716.28285 c S -398.77 716.28 m -398.32437 715.32028 397.62621 714.21254 398.07187 713.13095 c S -398.07 713.13 m -398.57336 712.18240 399.85778 712.37483 400.73100 712.56985 c S -400.73 712.57 m -402.98443 713.25618 404.83854 714.79610 406.66011 716.22985 c S -406.66 716.23 m -408.11360 717.41183 409.36895 718.81778 410.44888 720.34308 c S -410.45 720.34 m -411.47726 721.59671 412.51414 722.88301 413.25375 724.32691 c S -413.25 724.33 m -413.60253 725.66655 411.26351 725.68421 412.00122 724.33574 c S -412.00 724.34 m -412.67563 723.07539 414.28726 723.02575 415.54291 722.95857 c S -415.54 722.96 m -416.69601 723.19698 417.19632 721.86044 416.45907 721.08440 c S -416.46 721.08 m -415.97330 720.51720 415.48724 719.96970 415.10474 719.31838 c S -415.10 719.32 m -413.91309 717.57253 412.50005 715.87703 411.94882 713.79691 c S -411.95 713.80 m -411.73164 712.43046 413.33326 711.41965 414.54890 711.86110 c S -414.55 711.86 m -417.07044 712.45069 419.35460 713.73436 421.56616 715.03742 c S -422.60 720.83 m -424.94264 719.25149 427.88660 718.31183 430.71325 718.88005 c S -430.71 718.88 m -431.82181 719.10667 432.85178 719.63723 433.76367 720.28974 c S -433.76 720.29 m -434.98835 721.29361 434.95979 723.45602 433.61045 724.33926 c S -433.61 724.34 m -432.65667 724.96769 431.44146 724.75467 430.38277 724.58403 c S -430.38 724.58 m -428.00929 724.08917 426.00610 722.58363 424.31063 720.91694 c S -424.31 720.92 m -422.51500 719.31015 421.33376 716.83779 421.70110 714.40116 c S -421.70 714.40 m -422.15276 713.11643 423.49103 712.39634 424.79016 712.29603 c S -424.79 712.30 m -426.65615 712.13320 428.52395 712.57632 430.27740 713.18297 c S -430.28 713.18 m -433.09197 714.20773 435.59332 715.92106 437.91309 717.78645 c S +172.56 729.26 m +176.12859 727.37498 181.56609 729.53330 183.32142 731.81151 c S +183.32 731.81 m +185.07675 734.08972 184.06110 735.50444 182.15553 735.93722 c S +182.16 735.94 m +180.24996 736.37000 179.15914 735.19163 178.05706 733.58309 c S +178.06 733.58 m +176.95498 731.97454 176.46998 730.05644 176.20638 727.23746 c S +176.21 727.24 m +175.94279 724.41849 176.02369 719.87193 175.02338 716.95784 c S +175.02 716.96 m +174.02307 714.04375 172.12550 712.69662 169.33366 711.87807 c S +169.33 711.88 m +166.54182 711.05951 162.47030 711.40359 160.35569 713.59754 c S +160.36 713.60 m +158.24107 715.79148 158.60137 719.60485 160.39973 721.20315 c S +160.40 721.20 m +162.19810 722.80145 163.94600 722.75520 164.19254 719.87147 c S +164.19 719.87 m +164.43909 716.98774 158.69748 712.26983 156.93491 712.58268 c S +156.93 712.58 m +155.17233 712.89554 156.28179 712.58268 155.95524 712.58268 c S +193.95 718.56 m +195.08449 719.52030 196.07583 720.78852 196.25558 722.31187 c S +196.26 722.31 m +196.36196 723.03967 196.11746 723.87942 195.42818 724.23980 c S +195.43 724.24 m +193.81831 725.25646 191.77825 724.92797 190.08066 724.31958 c S +190.08 724.32 m +187.97924 723.52390 186.05472 722.29614 184.33465 720.85985 c S +184.33 720.86 m +183.22868 719.90201 182.18108 718.82436 181.48048 717.52995 c S +181.48 717.53 m +180.73003 715.75096 181.90197 713.35245 183.87920 713.10017 c S +183.88 713.10 m +185.36948 712.83748 186.81411 713.46652 188.08186 714.18482 c S +188.08 714.18 m +189.76421 715.04235 191.30516 716.15183 192.70807 717.41191 c S +192.71 717.41 m +193.12425 717.76649 193.53644 718.12575 193.94585 718.48814 c S +198.90 721.49 m +196.07844 719.86201 192.49067 717.41507 191.04076 715.70047 c S +191.04 715.70 m +189.59085 713.98586 191.16483 713.41558 192.56916 713.28742 c S +192.57 713.29 m +193.97349 713.15927 195.42706 713.70036 197.10945 714.62576 c S +197.11 714.63 m +198.79183 715.55117 201.00848 717.40025 202.30205 718.90544 c S +202.30 718.91 m +203.59561 720.41064 204.99046 721.86732 205.41256 722.98803 c S +205.41 722.99 m +205.83467 724.10873 205.89658 724.43654 205.24884 724.83735 c S +196.88 713.26 m +201.10084 716.77447 204.72691 721.13719 209.74630 723.59484 c S +209.75 723.59 m +211.27784 724.62715 214.66356 725.75326 215.04082 723.01765 c S +215.04 723.02 m +215.19389 720.68236 213.26479 719.01302 212.10153 717.20225 c S +212.10 717.20 m +211.29633 716.14293 209.62517 713.84732 209.38097 713.57045 c S +209.38 713.57 m +212.10971 717.76734 216.05913 721.04696 220.24647 723.71153 c S +220.25 723.71 m +221.77628 724.71863 225.67048 724.97128 224.73220 722.11724 c S +224.73 722.12 m +224.27467 719.96397 222.63059 718.40854 221.08683 716.99257 c S +221.09 716.99 m +219.49883 715.55841 220.23858 713.02749 222.59385 713.51910 c S +222.59 713.52 m +224.58617 713.64200 226.13616 715.06819 227.82469 715.97121 c S +227.82 715.97 m +231.45136 718.80595 234.17092 722.87123 238.50263 724.75230 c S +238.50 724.75 m +240.68520 725.60660 243.51738 726.39642 245.48590 724.65392 c S +245.49 724.65 m +247.11333 723.13890 246.18620 720.65644 244.98380 719.18788 c S +244.98 719.19 m +243.69129 717.26999 241.80998 715.85148 239.66638 715.00035 c S +239.67 715.00 m +237.24675 713.55589 234.02746 713.68689 231.79430 715.42895 c S +231.79 715.43 m +231.71730 715.47845 231.63421 715.51660 231.55272 715.55773 c S +237.27 726.92 m +235.90135 723.45558 234.47942 719.94900 232.16828 716.99131 c S +232.17 716.99 m +230.14653 713.86528 228.86869 710.28936 226.50435 707.37901 c S +226.50 707.38 m +224.81470 705.03899 223.03727 702.72215 220.81975 700.85245 c S +220.82 700.85 m +219.43589 700.41254 219.39593 702.32962 219.77817 703.19069 c S +219.78 703.19 m +220.68977 705.76640 222.42249 707.92052 223.67913 710.32267 c S +223.68 710.32 m +225.24740 713.07182 227.51923 715.26460 229.77069 717.44462 c S +231.74 715.27 m +234.69994 712.59242 239.28654 712.36992 242.77351 714.10344 c S +242.77 714.10 m +248.43787 716.50509 253.26148 720.40501 258.10412 724.11451 c S +258.10 724.11 m +260.84422 726.33103 263.48972 728.84488 265.08772 732.03182 c S +265.09 732.03 m +265.46324 733.19273 265.88595 734.74508 264.92402 735.72530 c S +264.92 735.73 m +263.15802 736.39257 261.74510 734.36034 260.46863 733.41874 c S +260.47 733.42 m +257.47016 730.49463 255.07567 727.00002 252.95876 723.40371 c S +252.96 723.40 m +251.67051 720.99231 250.37674 719.11264 249.75463 715.88391 c S +249.75 715.88 m +249.40876 714.08889 250.98737 713.04144 252.48903 713.30901 c S +252.49 713.31 m +254.42413 713.39988 256.19624 714.30805 257.97817 714.97973 c S +257.98 714.98 m +259.41764 715.67396 260.68153 716.66733 261.93773 717.64196 c S +263.12 721.79 m +266.34484 719.26553 269.14228 719.14066 272.76476 719.99777 c S +272.76 720.00 m +273.82509 720.34358 274.59424 721.27465 274.90634 722.32374 c S +274.91 722.32 m +275.34714 723.24408 274.88574 724.30697 273.98781 724.73200 c S +273.99 724.73 m +272.60242 725.61067 270.81295 725.48194 269.37642 724.79774 c S +269.38 724.80 m +267.00336 723.77079 265.15391 721.88990 263.36875 720.07671 c S +263.37 720.08 m +262.37948 718.90029 261.75811 717.37273 261.73505 715.83210 c S +261.74 715.83 m +261.78864 714.92761 262.49826 714.22249 263.34023 713.98907 c S +263.34 713.99 m +265.37479 713.13940 267.72184 712.70635 269.86579 713.39452 c S +269.87 713.39 m +271.29714 713.91105 272.69816 714.52553 274.04952 715.22266 c S +274.05 715.22 m +275.66628 716.17196 276.98685 717.52565 278.31726 718.82602 c S +282.36 712.81 m +284.40171 712.59169 286.86340 712.62058 288.23925 714.40209 c S +288.24 714.40 m +289.77697 715.82242 291.30792 717.81997 290.77075 720.04668 c S +290.77 720.05 m +290.47686 721.62207 288.38509 722.76231 287.06499 721.61177 c S +287.06 721.61 m +284.80944 720.01538 284.83621 716.62090 286.14986 714.42755 c S +286.15 714.43 m +287.83165 711.68873 291.41137 710.83902 294.40258 711.48955 c S +294.40 711.49 m +298.24039 712.22214 301.82103 715.31696 302.28387 719.32375 c S +302.28 719.32 m +302.33991 721.65682 302.33898 723.99293 302.63515 726.31208 c S +302.64 726.31 m +302.91434 729.34896 303.34183 732.64097 305.42124 735.02737 c S +305.42 735.03 m +306.63637 736.34109 309.06052 736.94011 310.35555 735.42209 c S +310.36 735.42 m +311.39940 734.05841 310.57078 732.20417 309.59241 731.05389 c S +309.59 731.05 m +308.43144 729.26796 306.13118 728.98393 304.23705 728.47945 c S +304.24 728.48 m +302.35587 728.06906 300.07192 728.28403 298.83038 729.93660 c S +298.83 729.94 m +298.14472 730.69770 297.37680 731.55415 297.36093 732.64010 c S +315.42 728.50 m +315.13964 728.43783 314.95197 728.11229 315.04711 727.84314 c S +315.05 727.84 m +315.13788 727.58513 315.35744 727.37078 315.62510 727.30456 c S +315.63 727.30 m +315.77486 727.29601 315.91744 727.42353 315.92615 727.57317 c S +315.93 727.57 m +315.98217 727.83851 315.94534 728.13571 315.77593 728.35441 c S +315.78 728.35 m +315.68741 728.45219 315.55240 728.52295 315.41789 728.49587 c S +313.59 725.09 m +311.46500 722.25303 309.41062 719.35555 307.47431 716.38424 c S +307.47 716.38 m +307.08799 715.57153 306.98256 714.44836 307.65999 713.75988 c S +307.66 713.76 m +308.47944 713.15600 309.55042 713.47898 310.44217 713.71514 c S +310.44 713.72 m +312.71322 714.31638 314.93772 715.26830 316.71277 716.83954 c S +316.71 716.84 m +317.79331 717.72675 318.78154 718.72585 319.66078 719.81274 c S +332.62 722.74 m +332.38180 724.10681 330.88121 724.91016 329.57707 724.77351 c S +329.58 724.77 m +326.80500 724.87803 324.27175 723.47849 322.03843 721.98353 c S +322.04 721.98 m +320.08756 720.61361 318.27576 718.77740 317.63354 716.42039 c S +317.63 716.42 m +317.42675 714.71509 318.96036 712.93774 320.71805 713.11147 c S +320.72 713.11 m +323.65930 713.14654 326.29456 714.78460 328.41290 716.70061 c S +328.41 716.70 m +330.29665 718.29060 332.16487 720.21783 332.61832 722.73929 c S +334.61 721.10 m +331.17430 719.33060 327.83007 716.98214 325.94364 713.51685 c S +325.94 713.52 m +323.20505 709.40609 319.89970 705.71392 316.65405 702.00600 c S +316.65 702.01 m +315.63517 701.02589 314.39167 699.96079 312.90148 699.98912 c S +312.90 699.99 m +311.30867 700.40210 311.47030 702.50713 312.63443 703.32277 c S +312.63 703.32 m +313.93789 704.79043 315.45909 706.05578 316.99476 707.26973 c S +316.99 707.27 m +319.64532 709.18907 322.27089 711.20194 325.27671 712.54311 c S +325.28 712.54 m +328.53633 714.05446 331.85352 715.48780 334.75757 717.64196 c S +337.92 724.65 m +337.08187 721.83748 335.65670 719.24427 334.06779 716.79618 c S +334.07 716.80 m +333.26023 715.56896 332.39486 714.37823 331.45206 713.25106 c S +331.50 713.40 m +334.30197 717.30207 337.48807 721.13020 341.74676 723.49689 c S +341.75 723.50 m +343.19999 724.24505 344.84981 724.43392 346.44440 724.65118 c S +346.44 724.65 m +347.53901 724.80277 348.94222 724.01879 348.82218 722.78655 c S +348.82 722.79 m +348.61255 721.62304 347.81620 720.67407 347.18845 719.70690 c S +347.19 719.71 m +346.24341 718.35690 345.01851 717.10243 344.58746 715.47393 c S +344.59 715.47 m +344.27785 714.16765 345.59237 712.99376 346.85764 713.40615 c S +346.86 713.41 m +348.05134 713.74971 349.06519 714.51454 350.14786 715.10162 c S +350.15 715.10 m +351.80716 716.10892 353.38397 717.28220 354.68929 718.72735 c S +365.15 717.54 m +366.73865 718.82508 368.25029 720.45336 368.64270 722.52684 c S +368.64 722.53 m +368.76060 723.71381 367.63628 724.77942 366.47545 724.75170 c S +366.48 724.75 m +363.74046 725.24608 361.00733 724.10410 358.80124 722.56053 c S +358.80 722.56 m +356.83999 721.20497 354.87981 719.61329 353.88315 717.38702 c S +353.88 717.39 m +353.37233 716.04140 353.73699 714.23248 355.11399 713.55624 c S +355.11 713.56 m +356.70513 712.65681 358.70707 713.01978 360.21760 713.91333 c S +360.22 713.91 m +362.02177 714.88992 363.53716 716.29379 365.14851 717.54329 c S +371.32 721.49 m +368.83136 719.75686 359.94918 714.77896 364.84054 713.59047 c S +364.84 713.59 m +368.35776 712.73586 373.41474 717.46627 377.50315 720.81926 c S +377.50 720.82 m +381.59155 724.17226 389.16443 730.50600 390.02620 735.43340 c S +390.03 735.43 m +390.88797 740.36081 387.48089 733.65459 385.92970 731.00011 c S +385.93 731.00 m +384.37851 728.34563 382.15147 722.85976 379.29248 718.51906 c S +379.29 718.52 m +375.31813 712.48497 380.30320 711.57808 384.88327 714.67763 c S +384.88 714.68 m +387.97078 716.76710 388.86501 717.46525 390.55652 719.27005 c S +377.53 725.59 m +381.17839 725.38600 384.83555 725.28150 388.48441 725.48638 c S +394.55 725.39 m +392.70166 722.62057 390.75594 719.92396 389.19727 716.94708 c S +389.20 716.95 m +388.61205 715.82939 388.28120 714.06595 389.64440 713.56191 c S +389.64 713.56 m +391.44568 713.10468 392.09979 713.77172 393.14644 714.08384 c S +393.15 714.08 m +396.55861 715.45581 399.38786 717.95628 401.87444 720.71777 c S +401.87 720.72 m +402.96994 722.20422 404.04216 723.70801 405.20929 725.14105 c S +405.36 725.19 m +403.12805 722.70632 401.13832 720.00978 399.31862 717.21621 c S +399.32 717.22 m +398.87189 716.24881 398.17024 715.13552 398.61813 714.04852 c S +398.62 714.05 m +399.12213 713.09521 400.41300 713.28861 401.29059 713.48460 c S +401.29 713.48 m +403.55531 714.17437 405.41872 715.72201 407.24942 717.16295 c S +407.25 717.16 m +408.71020 718.35085 409.97184 719.76385 411.05718 721.29680 c S +411.06 721.30 m +412.09071 722.55670 413.13279 723.84946 413.87611 725.30059 c S +413.88 725.30 m +414.22664 726.64694 411.87589 726.66470 412.61730 725.30947 c S +412.62 725.31 m +413.29510 724.04280 414.91480 723.99291 416.17675 723.92540 c S +416.18 723.93 m +417.33562 724.16500 417.83844 722.82176 417.09749 722.04183 c S +417.10 722.04 m +416.60929 721.47179 416.12080 720.92154 415.73638 720.26695 c S +415.74 720.27 m +414.53875 718.51235 413.11863 716.80835 412.56464 714.71781 c S +412.56 714.72 m +412.34637 713.34451 413.95602 712.32863 415.17776 712.77230 c S +415.18 712.77 m +417.71193 713.36484 420.00754 714.65494 422.23019 715.96454 c S +423.27 721.79 m +425.62360 720.19973 428.58231 719.25536 431.42312 719.82643 c S +431.42 719.83 m +432.53724 720.05419 433.57238 720.58741 434.48883 721.24319 c S +434.49 721.24 m +435.71965 722.25209 435.69096 724.42534 434.33485 725.31300 c S +434.33 725.31 m +433.37629 725.94459 432.15499 725.73050 431.09100 725.55900 c S +431.09 725.56 m +428.70561 725.06166 426.69238 723.54857 424.98842 721.87353 c S +424.99 721.87 m +423.18378 720.25869 421.99662 717.77394 422.36580 715.32509 c S +422.37 715.33 m +422.81973 714.03392 424.16471 713.31022 425.47035 713.20941 c S +425.47 713.21 m +427.34569 713.04576 429.22286 713.49111 430.98509 714.10079 c S +430.99 714.10 m +433.81377 715.13069 436.32766 716.85261 438.65906 718.72735 c S +165.00 666.86 m +162.81903 666.86099 160.67485 667.46404 v S +160.67 667.46 m +158.56417 668.10060 157.15705 669.13919 v S +157.16 669.14 m 158.06 674.50 l S +158.06 674.50 m 158.26 674.50 l S +158.26 674.50 m +159.73677 673.42756 161.44541 672.82450 v S +161.45 672.82 m +163.15406 672.22145 164.76220 672.22145 v S +164.76 672.22 m +167.91147 672.22145 167.91147 674.49965 v S +167.91 674.50 m +167.91147 675.37072 167.44243 675.94027 v S +167.44 675.94 m +167.00689 676.54332 165.86779 677.04587 v S +165.87 677.05 m 162.38 678.62 l S +162.38 678.62 m +160.00479 679.69259 158.69818 681.53525 v S +158.70 681.54 m +157.42507 683.37791 157.42507 685.82362 v S +157.43 685.82 m +157.42507 688.06831 158.46366 689.70996 v S +158.46 689.71 m +159.53575 691.38510 161.44541 692.28968 v S +161.45 692.29 m +163.38858 693.19425 165.96830 693.19425 v S +165.97 693.19 m +167.87797 693.19425 169.75413 692.69171 v S +169.75 692.69 m +171.63029 692.18917 172.80289 691.38510 v S +172.80 691.39 m 171.93 686.33 l S +171.93 686.33 m 171.73 686.33 l S +171.73 686.33 m +170.69221 687.06323 169.25158 687.46526 v S +169.25 687.47 m +167.84446 687.90080 166.47085 687.90080 v S +166.47 687.90 m +163.52259 687.90080 163.52259 685.89063 v S +163.52 685.89 m +163.52259 685.08656 163.99163 684.51701 v S +163.99 684.52 m +164.49418 683.94746 165.56627 683.47842 v S +165.57 683.48 m 168.58 682.10 l S +168.58 682.10 m +171.46278 680.79819 172.73588 679.05604 v S +172.74 679.06 m +174.00899 677.34739 174.00899 674.80117 v S +174.01 674.80 m +174.00899 672.38897 172.86990 670.57981 v S +172.87 670.58 m +171.76430 668.80416 169.75413 667.83258 v S +169.75 667.83 m +167.74396 666.86099 164.99672 666.86099 v S +165.00 666.86 m 165.00 666.86 l S +181.18 667.20 m +178.76635 667.19602 177.35922 668.53614 v S +177.36 668.54 m +175.95210 669.87625 175.95210 672.12094 v S +175.95 672.12 m +175.95210 676.87835 182.28415 677.44790 v S +182.28 677.45 m 186.41 677.82 l S +186.41 677.82 m 186.41 677.98 l S +186.41 677.98 m +186.40500 679.15655 185.70144 679.65909 v S +185.70 679.66 m +185.03138 680.19514 183.55726 680.19514 v S +183.56 680.20 m +182.08313 680.19514 180.44149 679.82661 v S +180.44 679.83 m +178.79985 679.49158 177.82827 678.92203 v S +177.83 678.92 m 177.59 678.92 l S +177.59 678.92 m 178.46 683.68 l S +178.46 683.68 m +181.41307 684.88554 184.69636 684.88554 v S +184.70 684.89 m +192.23450 684.88554 192.23450 677.54841 v S +192.23 677.55 m 192.23 672.32 l S +192.23 672.32 m +192.23450 670.91484 192.43552 669.67523 v S +192.44 669.68 m +192.67004 668.43563 193.03857 667.73207 v S +193.04 667.73 m 193.04 667.46 l S +193.04 667.46 m 187.61 667.46 l S +187.61 667.46 m +187.10856 668.60314 187.00805 669.97676 v S +187.01 669.98 m 186.77 669.98 l S +186.77 669.98 m +186.13698 668.70365 184.62935 667.93308 v S +184.63 667.93 m +183.12172 667.19602 181.17855 667.19602 v S +181.18 667.20 m 181.18 667.20 l S +181.61 672.66 m +181.61409 671.28337 183.25573 671.28337 v S +183.26 671.28 m +184.66285 671.28337 185.53393 672.08744 v S +185.53 672.09 m +186.40500 672.89151 186.40500 674.13112 v S +186.41 674.13 m 186.41 674.53 l S +186.41 674.53 m 183.69 674.30 l S +183.69 674.30 m +181.61409 674.09761 181.61409 672.65699 v S +181.61 672.66 m 181.61 672.66 l S +196.09 667.46 m 196.09 684.48 l S +196.09 684.48 m 201.51 684.48 l S +201.51 684.48 m 201.51 681.50 l S +201.51 681.50 m 201.75 681.50 l S +201.75 681.50 m +202.35234 683.10989 203.65895 683.98096 v S +203.66 683.98 m +204.99907 684.88554 206.74121 684.88554 v S +206.74 684.89 m +210.39303 684.88554 211.73314 681.73627 v S +211.73 681.74 m 211.87 681.74 l S +211.87 681.74 m +212.63772 683.31091 214.01134 684.08147 v S +214.01 684.08 m +215.38496 684.88554 217.22762 684.88554 v S +217.23 684.89 m +220.17587 684.88554 221.71700 682.94237 v S +221.72 682.94 m +223.29164 681.03271 223.29164 677.54841 v S +223.29 677.55 m 223.29 667.46 l S +223.29 667.46 m 217.26 667.46 l S +217.26 667.46 m 217.26 677.01 l S +217.26 677.01 m +217.26112 679.79310 215.11693 679.79310 v S +215.12 679.79 m +214.01134 679.79310 213.34128 678.95553 v S +213.34 678.96 m +212.70473 678.15146 212.70473 676.77784 v S +212.70 676.78 m 212.70 667.46 l S +212.70 667.46 m 206.67 667.46 l S +206.67 667.46 m 206.67 676.98 l S +206.67 676.98 m +206.67421 679.79310 204.53002 679.79310 v S +204.53 679.79 m +203.42443 679.79310 202.75437 678.95553 v S +202.75 678.96 m +202.11782 678.11796 202.11782 676.64383 v S +202.12 676.64 m 202.12 667.46 l S +202.12 667.46 m 196.09 667.46 l S +227.08 659.09 m 227.08 684.48 l S +227.08 684.48 m 232.81 684.48 l S +232.81 684.48 m 232.81 681.97 l S +232.81 681.97 m 233.07 681.97 l S +233.07 681.97 m +234.64908 684.88554 238.06638 684.88554 v S +238.07 684.89 m +240.27757 684.88554 241.91921 683.77995 v S +241.92 683.78 m +243.56085 682.67435 244.46543 680.66418 v S +244.47 680.66 m +245.37001 678.68751 245.37001 675.97377 v S +245.37 675.97 m +245.37001 673.29354 244.46543 671.28337 v S +244.47 671.28 m +243.56085 669.27320 241.91921 668.16760 v S +241.92 668.17 m +240.27757 667.06201 238.06638 667.06201 v S +238.07 667.06 m +235.01762 667.06201 233.37598 669.40721 v S +233.38 669.41 m 233.11 669.41 l S +233.11 669.41 m 233.11 659.09 l S +233.11 659.09 m 227.08 659.09 l S +242.05 672.15 m +243.56085 672.15445 244.43192 673.15953 v S +244.43 673.16 m +245.30300 674.19812 245.30300 675.94027 v S +245.30 675.94 m +245.30300 677.74943 244.43192 678.75451 v S +244.43 678.75 m +243.59435 679.79310 242.05322 679.79310 v S +242.05 679.79 m +240.57909 679.79310 239.70802 678.75451 v S +239.71 678.75 m +238.83694 677.74943 238.83694 675.97377 v S +238.84 675.97 m +238.83694 674.23162 239.70802 673.19304 v S +239.71 673.19 m +240.57909 672.15445 242.05322 672.15445 v S +242.05 672.15 m 242.05 672.15 l S +248.42 667.46 m 248.42 693.60 l S +248.42 693.60 m 254.45 693.60 l S +254.45 693.60 m 254.45 667.46 l S +254.45 667.46 m 248.42 667.46 l S +266.58 667.06 m +262.38939 667.06201 259.94368 669.44071 v S +259.94 669.44 m +257.53147 671.81942 257.53147 675.97377 v S +257.53 675.97 m +257.53147 678.78802 258.67057 680.76469 v S +258.67 680.76 m +259.84317 682.77486 261.85335 683.81345 v S +261.85 683.81 m +263.89702 684.88554 266.47674 684.88554 v S +266.48 684.89 m +270.43008 684.88554 272.47376 682.54034 v S +272.47 682.54 m +274.55093 680.22864 274.55093 675.94027 v S +274.55 675.94 m 274.55 675.04 l S +274.55 675.04 m 263.63 673.96 l S +263.63 673.96 m +264.03103 672.75750 265.03612 672.25496 v S +265.04 672.25 m +266.07470 671.75241 267.58234 671.75241 v S +267.58 671.75 m +269.29098 671.75241 270.86562 672.15445 v S +270.87 672.15 m +272.47376 672.58998 273.27783 673.02552 v S +273.28 673.03 m 273.51 673.03 l S +273.51 673.03 m 272.64 668.27 l S +272.64 668.27 m +271.63619 667.83258 269.96104 667.46404 v S +269.96 667.46 m +268.28590 667.06201 266.57725 667.06201 v S +266.58 667.06 m 266.58 667.06 l S +266.38 680.46 m +265.27064 680.46316 264.46657 679.79310 v S +264.47 679.79 m +263.69600 679.12305 263.42798 677.51491 v S +263.43 677.51 m 269.06 678.05 l S +269.06 678.05 m +268.82195 679.32406 268.11838 679.89361 v S +268.12 679.89 m +267.41482 680.46316 266.37624 680.46316 v S +266.38 680.46 m 266.38 680.46 l S +291.77 666.86 m +289.59362 666.86099 287.44943 667.46404 v S +287.45 667.46 m +285.33875 668.10060 283.93163 669.13919 v S +283.93 669.14 m 284.84 674.50 l S +284.84 674.50 m 285.04 674.50 l S +285.04 674.50 m +286.51135 673.42756 288.22000 672.82450 v S +288.22 672.82 m +289.92865 672.22145 291.53679 672.22145 v S +291.54 672.22 m +294.68606 672.22145 294.68606 674.49965 v S +294.69 674.50 m +294.68606 675.37072 294.21701 675.94027 v S +294.22 675.94 m +293.78148 676.54332 292.64238 677.04587 v S +292.64 677.05 m 289.16 678.62 l S +289.16 678.62 m +286.77938 679.69259 285.47276 681.53525 v S +285.47 681.54 m +284.19965 683.37791 284.19965 685.82362 v S +284.20 685.82 m +284.19965 688.06831 285.23825 689.70996 v S +285.24 689.71 m +286.31033 691.38510 288.22000 692.28968 v S +288.22 692.29 m +290.16317 693.19425 292.74289 693.19425 v S +292.74 693.19 m +294.65255 693.19425 296.52871 692.69171 v S +296.53 692.69 m +298.40488 692.18917 299.57747 691.38510 v S +299.58 691.39 m 298.71 686.33 l S +298.71 686.33 m 298.51 686.33 l S +298.51 686.33 m +297.46679 687.06323 296.02617 687.46526 v S +296.03 687.47 m +294.61905 687.90080 293.24543 687.90080 v S +293.25 687.90 m +290.29718 687.90080 290.29718 685.89063 v S +290.30 685.89 m +290.29718 685.08656 290.76622 684.51701 v S +290.77 684.52 m +291.26876 683.94746 292.34085 683.47842 v S +292.34 683.48 m 295.36 682.10 l S +295.36 682.10 m +298.23736 680.79819 299.51047 679.05604 v S +299.51 679.06 m +300.78358 677.34739 300.78358 674.80117 v S +300.78 674.80 m +300.78358 672.38897 299.64448 670.57981 v S +299.64 670.58 m +298.53889 668.80416 296.52871 667.83258 v S +296.53 667.83 m +294.51854 666.86099 291.77130 666.86099 v S +291.77 666.86 m 291.77 666.86 l S +306.85 686.46 m +305.20589 686.46018 304.20081 687.43176 v S +304.20 687.43 m +303.19573 688.43685 303.19573 689.94448 v S +303.20 689.94 m +303.19573 691.45210 304.20081 692.42369 v S +304.20 692.42 m +305.20589 693.42877 306.84754 693.42877 v S +306.85 693.43 m +308.48918 693.42877 309.49427 692.42369 v S +309.49 692.42 m +310.49935 691.45210 310.49935 689.94448 v S +310.50 689.94 m +310.49935 688.43685 309.49427 687.43176 v S +309.49 687.43 m +308.48918 686.46018 306.84754 686.46018 v S +306.85 686.46 m 306.85 686.46 l S +303.83 667.46 m 303.83 684.48 l S +303.83 684.48 m 309.86 684.48 l S +309.86 684.48 m 309.86 667.46 l S +309.86 667.46 m 303.83 667.46 l S +321.42 658.69 m +319.44458 658.68629 317.60192 659.15533 v S +317.60 659.16 m +315.75926 659.59087 314.62016 660.32793 v S +314.62 660.33 m 315.63 665.05 l S +315.63 665.05 m 315.86 665.05 l S +315.86 665.05 m +316.79785 664.48229 318.03745 664.14726 v S +318.04 664.15 m +319.31057 663.77873 320.51667 663.77873 v S +320.52 663.78 m +322.76136 663.77873 323.96747 665.01834 v S +323.97 665.02 m +325.17357 666.25794 325.17357 668.56964 v S +325.17 668.57 m 325.17 669.81 l S +325.17 669.81 m 324.91 669.81 l S +324.91 669.81 m +323.26391 667.46404 320.21514 667.46404 v S +320.22 667.46 m +318.00396 667.46404 316.36231 668.53614 v S +316.36 668.54 m +314.72067 669.64173 313.81609 671.58490 v S +313.82 671.58 m +312.91152 673.56157 312.91152 676.17479 v S +312.91 676.17 m +312.91152 678.82152 313.81609 680.76469 v S +313.82 680.76 m +314.72067 682.70785 316.36231 683.77995 v S +316.36 683.78 m +318.00396 684.88554 320.21514 684.88554 v S +320.22 684.89 m +321.99080 684.88554 323.39792 684.08147 v S +323.40 684.08 m +324.80504 683.27740 325.47510 681.90378 v S +325.48 681.90 m 325.71 681.90 l S +325.71 681.90 m +325.77662 682.64085 325.94413 683.34441 v S +325.94 683.34 m +326.11165 684.04797 326.31267 684.48351 v S +326.31 684.48 m 332.01 684.48 l S +332.01 684.48 m 332.01 684.22 l S +332.01 684.22 m +331.57262 683.41141 331.37160 682.10480 v S +331.37 682.10 m +331.20409 680.79819 331.20409 679.62559 v S +331.20 679.63 m 331.20 668.64 l S +331.20 668.64 m +331.20409 663.84573 328.65787 661.26601 v S +328.66 661.27 m +326.14515 658.68629 321.42125 658.68629 v S +321.42 658.69 m 321.42 658.69 l S +322.26 672.49 m +323.73295 672.48948 324.60402 673.49456 v S +324.60 673.49 m +325.47510 674.49965 325.47510 676.17479 v S +325.48 676.17 m +325.47510 677.84994 324.60402 678.85502 v S +324.60 678.86 m +323.73295 679.86011 322.25882 679.86011 v S +322.26 679.86 m +320.71769 679.86011 319.84661 678.85502 v S +319.85 678.86 m +319.00904 677.88344 319.00904 676.14129 v S +319.01 676.14 m +319.00904 674.46615 319.88012 673.46106 v S +319.88 673.46 m +320.75119 672.48948 322.25882 672.48948 v S +322.26 672.49 m 322.26 672.49 l S +335.16 667.46 m 335.16 684.48 l S +335.16 684.48 m 340.58 684.48 l S +340.58 684.48 m 340.58 681.50 l S +340.58 681.50 m 340.82 681.50 l S +340.82 681.50 m +341.42244 683.10989 342.79606 683.98096 v S +342.80 683.98 m +344.16968 684.88554 346.11284 684.88554 v S +346.11 684.89 m +348.99409 684.88554 350.63574 682.94237 v S +350.64 682.94 m +352.31088 680.99921 352.31088 677.54841 v S +352.31 677.55 m 352.31 667.46 l S +352.31 667.46 m 346.28 667.46 l S +346.28 667.46 m 346.28 676.84 l S +346.28 676.84 m +346.28036 679.79310 343.86815 679.79310 v S +343.87 679.79 m +342.62855 679.79310 341.89148 678.92203 v S +341.89 678.92 m +341.18792 678.05095 341.18792 676.50982 v S +341.19 676.51 m 341.19 667.46 l S +341.19 667.46 m 335.16 667.46 l S +360.22 667.20 m +357.80528 667.19602 356.39816 668.53614 v S +356.40 668.54 m +354.99104 669.87625 354.99104 672.12094 v S +354.99 672.12 m +354.99104 676.87835 361.32308 677.44790 v S +361.32 677.45 m 365.44 677.82 l S +365.44 677.82 m 365.44 677.98 l S +365.44 677.98 m +365.44393 679.15655 364.74037 679.65909 v S +364.74 679.66 m +364.07032 680.19514 362.59619 680.19514 v S +362.60 680.20 m +361.12207 680.19514 359.48042 679.82661 v S +359.48 679.83 m +357.83878 679.49158 356.86720 678.92203 v S +356.87 678.92 m 356.63 678.92 l S +356.63 678.92 m 357.50 683.68 l S +357.50 683.68 m +360.45200 684.88554 363.73529 684.88554 v S +363.74 684.89 m +371.27344 684.88554 371.27344 677.54841 v S +371.27 677.55 m 371.27 672.32 l S +371.27 672.32 m +371.27344 670.91484 371.47445 669.67523 v S +371.47 669.68 m +371.70897 668.43563 372.07750 667.73207 v S +372.08 667.73 m 372.08 667.46 l S +372.08 667.46 m 366.65 667.46 l S +366.65 667.46 m +366.14749 668.60314 366.04699 669.97676 v S +366.05 669.98 m 365.81 669.98 l S +365.81 669.98 m +365.17591 668.70365 363.66828 667.93308 v S +363.67 667.93 m +362.16065 667.19602 360.21749 667.19602 v S +360.22 667.20 m 360.22 667.20 l S +360.65 672.66 m +360.65302 671.28337 362.29466 671.28337 v S +362.29 671.28 m +363.70178 671.28337 364.57286 672.08744 v S +364.57 672.09 m +365.44393 672.89151 365.44393 674.13112 v S +365.44 674.13 m 365.44 674.53 l S +365.44 674.53 m 362.73 674.30 l S +362.73 674.30 m +360.65302 674.09761 360.65302 672.65699 v S +360.65 672.66 m 360.65 672.66 l S +373.35 679.79 m 373.35 684.48 l S +373.35 684.48 m 376.23 684.48 l S +376.23 684.48 m 376.23 689.31 l S +376.23 689.31 m 382.26 689.31 l S +382.26 689.31 m 382.26 684.48 l S +382.26 684.48 m 386.45 684.48 l S +386.45 684.48 m 385.68 679.79 l S +385.68 679.79 m 382.26 679.79 l S +382.26 679.79 m 382.26 675.87 l S +382.26 675.87 m +382.26234 672.25496 385.44512 672.25496 v S +385.45 672.25 m 386.45 672.25 l S +386.45 672.25 m 385.68 667.36 l S +385.68 667.36 m 383.17 667.36 l S +383.17 667.36 m +379.91714 667.36353 378.07448 669.27320 v S +378.07 669.27 m +376.23182 671.18286 376.23182 674.60016 v S +376.23 674.60 m 376.23 679.79 l S +376.23 679.79 m 373.35 679.79 l S +397.04 667.06 m +393.15074 667.06201 390.93955 669.23970 v S +390.94 669.24 m +388.72836 671.45089 388.72836 675.40423 v S +388.73 675.40 m 388.73 684.48 l S +388.73 684.48 m 394.76 684.48 l S +394.76 684.48 m 394.76 675.27 l S +394.76 675.27 m +394.75888 673.76258 395.36193 672.95852 v S +395.36 672.96 m +395.96498 672.15445 397.03708 672.15445 v S +397.04 672.15 m +398.10916 672.15445 398.71222 672.95852 v S +398.71 672.96 m +399.31527 673.76258 399.31527 675.27021 v S +399.32 675.27 m 399.32 684.48 l S +399.32 684.48 m 405.35 684.48 l S +405.35 684.48 m 405.35 675.40 l S +405.35 675.40 m +405.34578 671.45089 403.13460 669.23970 v S +403.13 669.24 m +400.92340 667.06201 397.03708 667.06201 v S +397.04 667.06 m 397.04 667.06 l S +409.00 667.46 m 409.00 684.48 l S +409.00 684.48 m 414.43 684.48 l S +414.43 684.48 m 414.43 681.17 l S +414.43 681.17 m 414.66 681.17 l S +414.66 681.17 m +415.83215 684.88554 419.28295 684.88554 v S +419.28 684.89 m +420.28804 684.88554 420.92459 684.48351 v S +420.92 684.48 m 420.92 678.52 l S +420.92 678.52 m 420.69 678.52 l S +420.69 678.52 m +419.78549 678.88853 418.71340 678.88853 v S +418.71 678.89 m +416.93775 678.88853 415.96616 677.71592 v S +415.97 677.72 m +415.02809 676.54332 415.02809 674.56665 v S +415.03 674.57 m 415.03 667.46 l S +415.03 667.46 m 409.00 667.46 l S +431.34 667.06 m +427.15607 667.06201 424.71036 669.44071 v S +424.71 669.44 m +422.29816 671.81942 422.29816 675.97377 v S +422.30 675.97 m +422.29816 678.78802 423.43726 680.76469 v S +423.44 680.76 m +424.60986 682.77486 426.62003 683.81345 v S +426.62 683.81 m +428.66371 684.88554 431.24343 684.88554 v S +431.24 684.89 m +435.19677 684.88554 437.24044 682.54034 v S +437.24 682.54 m +439.31762 680.22864 439.31762 675.94027 v S +439.32 675.94 m 439.32 675.04 l S +439.32 675.04 m 428.40 673.96 l S +428.40 673.96 m +428.79772 672.75750 429.80280 672.25496 v S +429.80 672.25 m +430.84139 671.75241 432.34902 671.75241 v S +432.35 671.75 m +434.05767 671.75241 435.63230 672.15445 v S +435.63 672.15 m +437.24044 672.58998 438.04451 673.02552 v S +438.04 673.03 m 438.28 673.03 l S +438.28 673.03 m 437.41 668.27 l S +437.41 668.27 m +436.40287 667.83258 434.72772 667.46404 v S +434.73 667.46 m +433.05258 667.06201 431.34394 667.06201 v S +431.34 667.06 m 431.34 667.06 l S +431.14 680.46 m +430.03732 680.46316 429.23326 679.79310 v S +429.23 679.79 m +428.46269 679.12305 428.19466 677.51491 v S +428.19 677.51 m 433.82 678.05 l S +433.82 678.05 m +433.58863 679.32406 432.88507 679.89361 v S +432.89 679.89 m +432.18151 680.46316 431.14292 680.46316 v S +431.14 680.46 m 431.14 680.46 l S endstream endobj @@ -357,15 +906,17 @@ endobj << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] /Font << -/F0 5 0 R +/Fd08375f64eb9861c6eae4dfcfdbd3500fbdbe33e 5 0 R >> /XObject << >> +/ColorSpace << +>> >> endobj 6 0 obj << -/Producer (FPDF 1.7) +/Producer (�F�P�D�F� �1�.�7) /CreationDate (D:20000101000000) >> endobj @@ -378,13 +929,13 @@ endobj xref 0 8 0000000000 65535 f -0000013550 00000 n -0000013735 00000 n +0000030711 00000 n +0000030896 00000 n 0000000009 00000 n 0000000384 00000 n -0000013637 00000 n -0000013839 00000 n -0000013914 00000 n +0000030798 00000 n +0000031057 00000 n +0000031142 00000 n trailer << /Size 8 @@ -392,5 +943,5 @@ trailer /Info 6 0 R >> startxref -13963 +31191 %%EOF -- cgit v1.2.1-24-ge1ad From a915207ea990b8fe8a380595d6eeeeb26022604b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20St=C3=B6ckl?= Date: Wed, 28 Aug 2019 20:38:00 +0200 Subject: set new coordinates on z instruction --- svgwrite.go | 1 + 1 file changed, 1 insertion(+) diff --git a/svgwrite.go b/svgwrite.go index 7045199..398a6da 100644 --- a/svgwrite.go +++ b/svgwrite.go @@ -76,6 +76,7 @@ func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { y = newY case 'Z': f.Line(x, y, startX, startY) + x, y = startX, startY default: f.SetErrorf("Unexpected path command '%c'", seg.Cmd) } -- cgit v1.2.1-24-ge1ad From e27b17d1defd471e6f0c0c422d2fa8ce9b9c3bb6 Mon Sep 17 00:00:00 2001 From: Joe Westcott Date: Fri, 30 Aug 2019 14:31:30 +0100 Subject: comments for ImageInfoType --- def.go | 28 ++++++++++++++-------------- fpdf.go | 1 + 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/def.go b/def.go index 7fddc82..47e5135 100644 --- a/def.go +++ b/def.go @@ -165,20 +165,20 @@ func (p PointType) XY() (float64, float64) { // Changes to this structure should be reflected in its GobEncode and GobDecode // methods. type ImageInfoType struct { - data []byte - smask []byte - n int - w float64 - h float64 - cs string - pal []byte - bpc int - f string - dp string - trns []int - scale float64 // document scaling factor - dpi float64 - i string + data []byte // Raw image data + smask []byte // Soft Mask, an 8bit per-pixel transparency mask + n int // Image object number + w float64 // Width + h float64 // Height + cs string // Color space + pal []byte // Image color palette + bpc int // Bits Per Component + f string // Image filter + dp string // DecodeParms + trns []int // Transparency mask + scale float64 // Document scale factor + dpi float64 // Dots-per-inch found from image file (png only) + i string // SHA-1 checksum of the above values. } func generateImageID(info *ImageInfoType) (string, error) { diff --git a/fpdf.go b/fpdf.go index f77717f..24e79bc 100644 --- a/fpdf.go +++ b/fpdf.go @@ -4215,6 +4215,7 @@ func implode(sep string, arr []int) string { return s.String() } +// arrayCountValues counts the occurrences of each item in the $mp array. func arrayCountValues(mp []int) map[int]int { answer := make(map[int]int) for _, v := range mp { -- cgit v1.2.1-24-ge1ad From f8eb4ab245f4dfe947b595efb0b2e2c3b3a37625 Mon Sep 17 00:00:00 2001 From: Joe Westcott Date: Fri, 30 Aug 2019 14:32:24 +0100 Subject: Prevent inserting duplicate images --- fpdf.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/fpdf.go b/fpdf.go index 24e79bc..620e742 100644 --- a/fpdf.go +++ b/fpdf.go @@ -4244,11 +4244,31 @@ func (f *Fpdf) putimages() { for key = range f.images { keyList = append(keyList, key) } + + // Sort the keyList []string by the corrosponding image's width. if f.catalogSort { sort.SliceStable(keyList, func(i, j int) bool { return f.images[keyList[i]].w < f.images[keyList[j]].w }) } + + // Maintain a list of inserted image SHA-1 hashes, with their + // corresponding object ID number. + insertedImages := map[string]int{} + for _, key = range keyList { - f.putimage(f.images[key]) + image := f.images[key] + + // Check if this image has already been inserted using it's SHA-1 hash. + insertedImageObjN, isFound := insertedImages[image.i] + + // If found, skip inserting the image as a new object, and + // use the object ID from the insertedImages map. + // If not, insert the image into the PDF and store the object ID. + if isFound { + image.n = insertedImageObjN + } else { + f.putimage(image) + insertedImages[image.i] = image.n + } } } -- cgit v1.2.1-24-ge1ad From f9ddde9937c7b2c043599459877e5a695d667f0e Mon Sep 17 00:00:00 2001 From: Joe Westcott Date: Wed, 4 Sep 2019 15:33:02 +0100 Subject: Initialize derived template with parent images --- template.go | 11 +++++++++++ template_impl.go | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/template.go b/template.go index 31204c2..c0d3933 100644 --- a/template.go +++ b/template.go @@ -84,7 +84,18 @@ func (f *Fpdf) UseTemplateScaled(t Template, corner PointType, size SizeType) { for _, tt := range t.Templates() { f.templates[tt.ID()] = tt } + + // Create a list of existing image SHA-1 hashes. + existingImages := map[string]bool{} + for _, image := range f.images { + existingImages[image.i] = true + } + + // Add each template image to $f, unless already present. for name, ti := range t.Images() { + if _, found := existingImages[ti.i]; found { + continue + } name = sprintf("t%s-%s", t.ID(), name) f.images[name] = ti } diff --git a/template_impl.go b/template_impl.go index c5d7be8..c1e2dff 100644 --- a/template_impl.go +++ b/template_impl.go @@ -296,4 +296,8 @@ func (t *Tpl) loadParamsFromFpdf(f *Fpdf) { t.Fpdf.fontSizePt = f.fontSizePt t.Fpdf.fontStyle = f.fontStyle t.Fpdf.ws = f.ws + + for key, value := range f.images { + t.Fpdf.images[key] = value + } } -- cgit v1.2.1-24-ge1ad From 5d0bba740b8c3f5619d5a39b724f4d59e99fe4b4 Mon Sep 17 00:00:00 2001 From: Franz Fangmeyer Date: Sat, 7 Sep 2019 12:14:28 +0200 Subject: Strikeout: use "S" as styleStr --- def.go | 1 + fpdf.go | 28 +++++++++++++++++++++++++--- fpdf_test.go | 26 ++++++++++++++++++++++---- internal/example/example.go | 3 +-- ttfparser_test.go | 5 ++--- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/def.go b/def.go index 7fddc82..bff23e7 100644 --- a/def.go +++ b/def.go @@ -542,6 +542,7 @@ type Fpdf struct { fontFamily string // current font family fontStyle string // current font style underline bool // underlining flag + strikeout bool // strike out flag currentFont fontDefType // current font info fontSizePt float64 // current font size in points fontSize float64 // current font size in user unit diff --git a/fpdf.go b/fpdf.go index f77717f..1ef2b1f 100644 --- a/fpdf.go +++ b/fpdf.go @@ -102,6 +102,7 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) f.fontStyle = "" f.SetFontSize(12) f.underline = false + f.strikeout = false f.setDrawColor(0, 0, 0) f.setFillColor(0, 0, 0) f.setTextColor(0, 0, 0) @@ -726,6 +727,9 @@ func (f *Fpdf) AddPageFormat(orientationStr string, size SizeType) { if f.underline { style += "U" } + if f.strikeout { + style += "S" + } fontsize := f.fontSizePt lw := f.lineWidth dc := f.color.draw @@ -2004,9 +2008,9 @@ func (f *Fpdf) GetFontDesc(familyStr, styleStr string) FontDescType { // insensitive): "Courier" for fixed-width, "Helvetica" or "Arial" for sans // serif, "Times" for serif, "Symbol" or "ZapfDingbats" for symbolic. // -// styleStr can be "B" (bold), "I" (italic), "U" (underscore) or any -// combination. The default value (specified with an empty string) is regular. -// Bold and italic styles do not apply to Symbol and ZapfDingbats. +// styleStr can be "B" (bold), "I" (italic), "U" (underscore), "S" (strike-out) +// or any combination. The default value (specified with an empty string) is +// regular. Bold and italic styles do not apply to Symbol and ZapfDingbats. // // size is the font size measured in points. The default value is the current // size. If no size has been specified since the beginning of the document, the @@ -2029,6 +2033,10 @@ func (f *Fpdf) SetFont(familyStr, styleStr string, size float64) { if f.underline { styleStr = strings.Replace(styleStr, "U", "", -1) } + f.strikeout = strings.Contains(styleStr, "S") + if f.strikeout { + styleStr = strings.Replace(styleStr, "S", "", -1) + } if styleStr == "IB" { styleStr = "BI" } @@ -2198,6 +2206,9 @@ func (f *Fpdf) Text(x, y float64, txtStr string) { if f.underline && txtStr != "" { s += " " + f.dounderline(x, y, txtStr) } + if f.strikeout && txtStr != "" { + s += " " + f.dostrikeout(x, y, txtStr) + } if f.colorFlag { s = sprintf("q %s %s Q", f.color.text.str, s) } @@ -2422,6 +2433,9 @@ func (f *Fpdf) CellFormat(w, h float64, txtStr, borderStr string, ln int, if f.underline { s.printf(" %s", f.dounderline(f.x+dx, f.y+dy+.5*h+.3*f.fontSize, txtStr)) } + if f.strikeout { + s.printf(" %s", f.dostrikeout(f.x+dx, f.y+dy+.5*h+.3*f.fontSize, txtStr)) + } if f.colorFlag { s.printf(" Q") } @@ -3554,6 +3568,14 @@ func (f *Fpdf) dounderline(x, y float64, txt string) string { (f.h-(y-up/1000*f.fontSize))*f.k, w*f.k, -ut/1000*f.fontSizePt) } +func (f *Fpdf) dostrikeout(x, y float64, txt string) string { + up := float64(f.currentFont.Up) + ut := float64(f.currentFont.Ut) + w := f.GetStringWidth(txt) + f.ws*float64(blankCount(txt)) + return sprintf("%.2f %.2f %.2f %.2f re f", x*f.k, + (f.h-(y+4*up/1000*f.fontSize))*f.k, w*f.k, -ut/1000*f.fontSizePt) +} + func bufEqual(buf []byte, str string) bool { return string(buf[0:len(str)]) == str } diff --git a/fpdf_test.go b/fpdf_test.go index 43cea30..267bc6c 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -20,6 +20,9 @@ import ( "bufio" "bytes" "fmt" + "gofpdf" + "gofpdf/internal/example" + "gofpdf/internal/files" "io" "io/ioutil" "math" @@ -31,10 +34,6 @@ import ( "strings" "testing" "time" - - "github.com/jung-kurt/gofpdf" - "github.com/jung-kurt/gofpdf/internal/example" - "github.com/jung-kurt/gofpdf/internal/files" ) func init() { @@ -2711,3 +2710,22 @@ func ExampleFpdf_SetUnderlineThickness() { // Output: // Successfully generated pdf/Fpdf_UnderlineThickness.pdf } + +// ExampleFpdf_strikeout demonstrates striked-out text +func ExampleFpdf_strikeout() { + + pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm + pdf.AddPage() + + for fontSize := 4; fontSize < 40; fontSize += 10 { + pdf.SetFont("Arial", "S", float64(fontSize)) + pdf.SetXY(0, float64(fontSize)) + pdf.Cell(40, 10, "Hello World\n") + } + + fileStr := example.Filename("Fpdf_strikeout") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_strikeout.pdf +} diff --git a/internal/example/example.go b/internal/example/example.go index 05e4827..3365931 100644 --- a/internal/example/example.go +++ b/internal/example/example.go @@ -19,12 +19,11 @@ package example import ( "fmt" + "gofpdf" "os" "path/filepath" "strings" "time" - - "github.com/jung-kurt/gofpdf" ) var gofpdfDir string diff --git a/ttfparser_test.go b/ttfparser_test.go index 3286db2..b157d98 100644 --- a/ttfparser_test.go +++ b/ttfparser_test.go @@ -19,9 +19,8 @@ package gofpdf_test import ( "bytes" "fmt" - - "github.com/jung-kurt/gofpdf" - "github.com/jung-kurt/gofpdf/internal/example" + "gofpdf" + "gofpdf/internal/example" ) func ExampleTtfParse() { -- cgit v1.2.1-24-ge1ad From 29a8ebcc82176b98972f23e915f2afdf8a192bac Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 7 Sep 2019 09:17:06 -0400 Subject: Correct misspelled word --- fpdf.go | 2 +- go.mod | 6 +++++- go.sum | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/fpdf.go b/fpdf.go index 620e742..c482cb7 100644 --- a/fpdf.go +++ b/fpdf.go @@ -4245,7 +4245,7 @@ func (f *Fpdf) putimages() { keyList = append(keyList, key) } - // Sort the keyList []string by the corrosponding image's width. + // Sort the keyList []string by the corresponding image's width. if f.catalogSort { sort.SliceStable(keyList, func(i, j int) bool { return f.images[keyList[i]].w < f.images[keyList[j]].w }) } diff --git a/go.mod b/go.mod index 6af14f1..cbb6a8c 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,13 @@ go 1.12 require ( github.com/boombuler/barcode v1.0.0 + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/pretty v0.1.0 // indirect github.com/phpdave11/gofpdi v1.0.7 github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 - golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec + github.com/stretchr/testify v1.4.0 // indirect + golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) replace github.com/jung-kurt/gopdf => ./ diff --git a/go.sum b/go.sum index f642b76..7f20736 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,14 @@ github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDd github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/phpdave11/gofpdi v1.0.7 h1:k2oy4yhkQopCK+qW8KjCla0iU2RpDow+QUDmH9DDt44= github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -11,8 +18,17 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 h1:nlG4Wa5+minh3S9LVFtNoY+GVRiudA2e3EVfcCi3RCA= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec h1:arXJwtMuk5vqI1NHX0UTnNw977rYk5Sl4jQqHj+hun4= -golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 h1:4dQcAORh9oYBwVSBVIkP489LUPC+f1HBkTYXgmqfR+o= +golang.org/x/image v0.0.0-20190902063713-cb417be4ba39/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -- cgit v1.2.1-24-ge1ad From 225d875579b542d345946a136d24f8add53b4dc3 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 7 Sep 2019 09:21:33 -0400 Subject: Acknowledge Joe Westcott's contributions --- README.md | 3 ++- doc.go | 3 ++- doc/document.md | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 38ef38d..b402678 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,8 @@ independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added support for imported objects and templates. Brigham Thompson added -support for rounded rectangles. +support for rounded rectangles. Joe Westcott added underline +functionality and optimized image storage. ## Roadmap diff --git a/doc.go b/doc.go index b3721e7..16cf4ba 100644 --- a/doc.go +++ b/doc.go @@ -257,7 +257,8 @@ independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added support for imported objects and templates. Brigham Thompson added -support for rounded rectangles. +support for rounded rectangles. Joe Westcott added underline +functionality and optimized image storage. Roadmap diff --git a/doc/document.md b/doc/document.md index d7d84cd..b2289ce 100644 --- a/doc/document.md +++ b/doc/document.md @@ -228,7 +228,8 @@ templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added support for imported objects and templates. -Brigham Thompson added support for rounded rectangles. +Brigham Thompson added support for rounded rectangles. Joe Westcott added +underline functionality and optimized image storage. ## Roadmap -- cgit v1.2.1-24-ge1ad From e123b55aba2106cced7941e31391fff7e59d200d Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 7 Sep 2019 13:01:30 -0400 Subject: Adjust various import paths, rename example function --- fpdf.go | 2 +- fpdf_test.go | 17 +++++++++-------- go.mod | 7 ++----- internal/example/example.go | 3 ++- ttfparser_test.go | 5 +++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/fpdf.go b/fpdf.go index 2cad2e9..7be0117 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2472,7 +2472,7 @@ func reverseText(text string) string { } // Cell is a simpler version of CellFormat with no fill, border, links or -// special alignment. +// special alignment. The Cell_strikeout() example demonstrates this method. func (f *Fpdf) Cell(w, h float64, txtStr string) { f.CellFormat(w, h, txtStr, "", 0, "L", false, 0, "") } diff --git a/fpdf_test.go b/fpdf_test.go index 267bc6c..5035bd8 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -20,9 +20,6 @@ import ( "bufio" "bytes" "fmt" - "gofpdf" - "gofpdf/internal/example" - "gofpdf/internal/files" "io" "io/ioutil" "math" @@ -34,6 +31,10 @@ import ( "strings" "testing" "time" + + "github.com/jung-kurt/gofpdf" + "github.com/jung-kurt/gofpdf/internal/example" + "github.com/jung-kurt/gofpdf/internal/files" ) func init() { @@ -2711,8 +2712,8 @@ func ExampleFpdf_SetUnderlineThickness() { // Successfully generated pdf/Fpdf_UnderlineThickness.pdf } -// ExampleFpdf_strikeout demonstrates striked-out text -func ExampleFpdf_strikeout() { +// ExampleFpdf_Cell_strikeout demonstrates striked-out text +func ExampleFpdf_Cell_strikeout() { pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm pdf.AddPage() @@ -2720,12 +2721,12 @@ func ExampleFpdf_strikeout() { for fontSize := 4; fontSize < 40; fontSize += 10 { pdf.SetFont("Arial", "S", float64(fontSize)) pdf.SetXY(0, float64(fontSize)) - pdf.Cell(40, 10, "Hello World\n") + pdf.Cell(40, 10, "Hello World") } - fileStr := example.Filename("Fpdf_strikeout") + fileStr := example.Filename("Fpdf_Cell_strikeout") err := pdf.OutputFileAndClose(fileStr) example.Summary(err, fileStr) // Output: - // Successfully generated pdf/Fpdf_strikeout.pdf + // Successfully generated pdf/Fpdf_Cell_strikeout.pdf } diff --git a/go.mod b/go.mod index cbb6a8c..f11d98c 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,10 @@ go 1.12 require ( github.com/boombuler/barcode v1.0.0 - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.1.0 // indirect github.com/phpdave11/gofpdi v1.0.7 github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 - github.com/stretchr/testify v1.4.0 // indirect + gofpdf v0.0.0-00010101000000-000000000000 golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) -replace github.com/jung-kurt/gopdf => ./ +replace gofpdf => ./ diff --git a/internal/example/example.go b/internal/example/example.go index 3365931..05e4827 100644 --- a/internal/example/example.go +++ b/internal/example/example.go @@ -19,11 +19,12 @@ package example import ( "fmt" - "gofpdf" "os" "path/filepath" "strings" "time" + + "github.com/jung-kurt/gofpdf" ) var gofpdfDir string diff --git a/ttfparser_test.go b/ttfparser_test.go index b157d98..3286db2 100644 --- a/ttfparser_test.go +++ b/ttfparser_test.go @@ -19,8 +19,9 @@ package gofpdf_test import ( "bytes" "fmt" - "gofpdf" - "gofpdf/internal/example" + + "github.com/jung-kurt/gofpdf" + "github.com/jung-kurt/gofpdf/internal/example" ) func ExampleTtfParse() { -- cgit v1.2.1-24-ge1ad From 98f563f5df154c2662ca0743b0f33785e1930396 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 7 Sep 2019 13:08:24 -0400 Subject: Tidy module file --- font/calligra.json | 2 +- font/calligra.z | Bin 25609 -> 25812 bytes go.mod | 7 ++++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/font/calligra.json b/font/calligra.json index b968074..e49c9bd 100644 --- a/font/calligra.json +++ b/font/calligra.json @@ -1 +1 @@ -{"Tp":"TrueType","Name":"CalligrapherRegular","Desc":{"Ascent":899,"Descent":-234,"CapHeight":899,"Flags":32,"FontBBox":{"Xmin":-173,"Ymin":-234,"Xmax":1328,"Ymax":899},"ItalicAngle":0,"StemV":70,"MissingWidth":800},"Up":-200,"Ut":20,"Cw":[800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,282,324,405,584,632,980,776,259,299,299,377,600,259,432,254,597,529,298,451,359,525,423,464,417,457,479,275,282,600,600,600,501,800,743,636,598,712,608,562,680,756,308,314,676,552,1041,817,729,569,698,674,618,673,805,753,1238,716,754,599,315,463,315,600,547,278,581,564,440,571,450,347,628,611,283,283,560,252,976,595,508,549,540,395,441,307,614,556,915,559,597,452,315,222,315,600,800,800,800,0,0,0,780,0,0,278,0,0,0,1064,800,0,800,800,259,259,470,470,500,300,600,278,990,0,0,790,800,800,754,282,324,450,640,518,603,0,519,254,800,349,0,0,432,800,278,0,0,0,0,278,614,0,254,278,0,305,0,0,0,0,501,743,743,743,743,743,743,1060,598,608,608,608,608,308,308,308,308,0,817,729,729,729,729,729,0,729,805,805,805,805,0,0,688,581,581,581,581,581,581,792,440,450,450,450,450,283,283,283,283,0,595,508,508,508,508,508,0,508,614,614,614,614,0,0,597],"Enc":"cp1252","Diff":"","File":"calligra.z","Size1":0,"Size2":0,"OriginalSize":40120,"I":0,"N":0,"DiffN":0} \ No newline at end of file +{"Tp":"TrueType","Name":"CalligrapherRegular","Desc":{"Ascent":899,"Descent":-234,"CapHeight":899,"Flags":32,"FontBBox":{"Xmin":-173,"Ymin":-234,"Xmax":1328,"Ymax":899},"ItalicAngle":0,"StemV":70,"MissingWidth":800},"Up":-200,"Ut":20,"Cw":[800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,282,324,405,584,632,980,776,259,299,299,377,600,259,432,254,597,529,298,451,359,525,423,464,417,457,479,275,282,600,600,600,501,800,743,636,598,712,608,562,680,756,308,314,676,552,1041,817,729,569,698,674,618,673,805,753,1238,716,754,599,315,463,315,600,547,278,581,564,440,571,450,347,628,611,283,283,560,252,976,595,508,549,540,395,441,307,614,556,915,559,597,452,315,222,315,600,800,800,800,0,0,0,780,0,0,278,0,0,0,1064,800,0,800,800,259,259,470,470,500,300,600,278,990,0,0,790,800,800,754,282,324,450,640,518,603,0,519,254,800,349,0,0,432,800,278,0,0,0,0,278,614,0,254,278,0,305,0,0,0,0,501,743,743,743,743,743,743,1060,598,608,608,608,608,308,308,308,308,0,817,729,729,729,729,729,0,729,805,805,805,805,0,0,688,581,581,581,581,581,581,792,440,450,450,450,450,283,283,283,283,0,595,508,508,508,508,508,0,508,614,614,614,614,0,0,597],"Enc":"cp1252","Diff":"","File":"calligra.z","Size1":0,"Size2":0,"OriginalSize":40120,"N":0,"DiffN":0} \ No newline at end of file diff --git a/font/calligra.z b/font/calligra.z index c64353f..b6c5c07 100644 Binary files a/font/calligra.z and b/font/calligra.z differ diff --git a/go.mod b/go.mod index f11d98c..509ba82 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,11 @@ go 1.12 require ( github.com/boombuler/barcode v1.0.0 + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/pretty v0.1.0 // indirect github.com/phpdave11/gofpdi v1.0.7 github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 - gofpdf v0.0.0-00010101000000-000000000000 + github.com/stretchr/testify v1.4.0 // indirect golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) - -replace gofpdf => ./ -- cgit v1.2.1-24-ge1ad From 07f2797b1523f4a406a919883c018ca52233a8a0 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 8 Sep 2019 06:50:34 -0400 Subject: Restore go.mod replace directive --- go.mod | 6 ++---- go.sum | 16 ---------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 509ba82..dee309c 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,9 @@ go 1.12 require ( github.com/boombuler/barcode v1.0.0 - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.1.0 // indirect github.com/phpdave11/gofpdi v1.0.7 github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 - github.com/stretchr/testify v1.4.0 // indirect golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) + +replace gofpdf => ./ diff --git a/go.sum b/go.sum index 7f20736..a6b40f3 100644 --- a/go.sum +++ b/go.sum @@ -2,14 +2,7 @@ github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDd github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/phpdave11/gofpdi v1.0.7 h1:k2oy4yhkQopCK+qW8KjCla0iU2RpDow+QUDmH9DDt44= github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -18,17 +11,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 h1:nlG4Wa5+minh3S9LVFtNoY+GVRiudA2e3EVfcCi3RCA= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 h1:4dQcAORh9oYBwVSBVIkP489LUPC+f1HBkTYXgmqfR+o= golang.org/x/image v0.0.0-20190902063713-cb417be4ba39/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -- cgit v1.2.1-24-ge1ad From cae7d4739e815a170819d84c5361b05306b2f019 Mon Sep 17 00:00:00 2001 From: Kurt Date: Wed, 25 Sep 2019 08:16:44 -0400 Subject: Merge from v2: Escape spaces in font family string to comply with PDF standard --- fpdf.go | 12 +++++++----- util.go | 8 ++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/fpdf.go b/fpdf.go index 7be0117..b6861b6 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1629,7 +1629,7 @@ func (f *Fpdf) ClipEnd() { // definition file to be added. The file will be loaded from the font directory // specified in the call to New() or SetFontLocation(). func (f *Fpdf) AddFont(familyStr, styleStr, fileStr string) { - f.addFont(familyStr, styleStr, fileStr, false) + f.addFont(fontFamilyEscape(familyStr), styleStr, fileStr, false) } // AddUTF8Font imports a TrueType font with utf-8 symbols and makes it available. @@ -1653,7 +1653,7 @@ func (f *Fpdf) AddFont(familyStr, styleStr, fileStr string) { // definition file to be added. The file will be loaded from the font directory // specified in the call to New() or SetFontLocation(). func (f *Fpdf) AddUTF8Font(familyStr, styleStr, fileStr string) { - f.addFont(familyStr, styleStr, fileStr, true) + f.addFont(fontFamilyEscape(familyStr), styleStr, fileStr, true) } func (f *Fpdf) addFont(familyStr, styleStr, fileStr string, isUTF8 bool) { @@ -1779,7 +1779,7 @@ func makeSubsetRange(end int) map[int]int { // // zFileBytes contain all bytes of Z file. func (f *Fpdf) AddFontFromBytes(familyStr, styleStr string, jsonFileBytes, zFileBytes []byte) { - f.addFontFromBytes(familyStr, styleStr, jsonFileBytes, zFileBytes, nil) + f.addFontFromBytes(fontFamilyEscape(familyStr), styleStr, jsonFileBytes, zFileBytes, nil) } // AddUTF8FontFromBytes imports a TrueType font with utf-8 symbols from static @@ -1798,7 +1798,7 @@ func (f *Fpdf) AddFontFromBytes(familyStr, styleStr string, jsonFileBytes, zFile // // zFileBytes contain all bytes of Z file. func (f *Fpdf) AddUTF8FontFromBytes(familyStr, styleStr string, utf8Bytes []byte) { - f.addFontFromBytes(familyStr, styleStr, nil, nil, utf8Bytes) + f.addFontFromBytes(fontFamilyEscape(familyStr), styleStr, nil, nil, utf8Bytes) } func (f *Fpdf) addFontFromBytes(familyStr, styleStr string, jsonFileBytes, zFileBytes, utf8Bytes []byte) { @@ -1937,6 +1937,7 @@ func (f *Fpdf) AddFontFromReader(familyStr, styleStr string, r io.Reader) { return } // dbg("Adding family [%s], style [%s]", familyStr, styleStr) + familyStr = fontFamilyEscape(familyStr) var ok bool fontkey := getFontKey(familyStr, styleStr) _, ok = f.fonts[fontkey] @@ -1985,7 +1986,7 @@ func (f *Fpdf) GetFontDesc(familyStr, styleStr string) FontDescType { if familyStr == "" { return f.currentFont.Desc } - return f.fonts[getFontKey(familyStr, styleStr)].Desc + return f.fonts[getFontKey(fontFamilyEscape(familyStr), styleStr)].Desc } // SetFont sets the font used to print character strings. It is mandatory to @@ -2022,6 +2023,7 @@ func (f *Fpdf) SetFont(familyStr, styleStr string, size float64) { return } // dbg("SetFont") + familyStr = fontFamilyEscape(familyStr) var ok bool if familyStr == "" { familyStr = f.fontFamily diff --git a/util.go b/util.go index 99a1ba5..22e5f36 100644 --- a/util.go +++ b/util.go @@ -452,3 +452,11 @@ func isChinese(rune2 rune) bool { } return false } + +// Condition font family string to PDF name compliance. See section 5.3 (Names) +// in https://resources.infosecinstitute.com/pdf-file-format-basic-structure/ +func fontFamilyEscape(familyStr string) (escStr string) { + escStr = strings.ReplaceAll(familyStr, " ", "#20") + // Additional replacements can take place here + return +} -- cgit v1.2.1-24-ge1ad From 648efaf66fc0b2c166ecb8b51fe68bcb0395c840 Mon Sep 17 00:00:00 2001 From: Kurt Date: Wed, 25 Sep 2019 21:45:01 -0400 Subject: Use strings.Replace instead of strings.ReplaceAll for older library support --- util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.go b/util.go index 22e5f36..351d319 100644 --- a/util.go +++ b/util.go @@ -456,7 +456,7 @@ func isChinese(rune2 rune) bool { // Condition font family string to PDF name compliance. See section 5.3 (Names) // in https://resources.infosecinstitute.com/pdf-file-format-basic-structure/ func fontFamilyEscape(familyStr string) (escStr string) { - escStr = strings.ReplaceAll(familyStr, " ", "#20") + escStr = strings.Replace(familyStr, " ", "#20", -1) // Additional replacements can take place here return } -- cgit v1.2.1-24-ge1ad From 25404723570af4f2038e916c75a5296ed694f486 Mon Sep 17 00:00:00 2001 From: Artem Date: Sun, 29 Sep 2019 01:23:08 +0300 Subject: fix utf16 in bookmarks --- fpdf.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fpdf.go b/fpdf.go index b6861b6..f5062cc 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2183,6 +2183,9 @@ func (f *Fpdf) Bookmark(txtStr string, level int, y float64) { if y == -1 { y = f.y } + if f.isCurrentUTF8 { + txtStr = utf8toutf16(txtStr) + } f.outlines = append(f.outlines, outlineType{text: txtStr, level: level, y: y, p: f.PageNo(), prev: -1, last: -1, next: -1, first: -1}) } -- cgit v1.2.1-24-ge1ad