diff options
author | DarkFreedman <misterdark@mail.ru> | 2019-10-04 13:25:04 +0300 |
---|---|---|
committer | DarkFreedman <misterdark@mail.ru> | 2019-10-04 13:25:04 +0300 |
commit | 6b0f0dee0dd42aebd05ef612bc8069361d06e487 (patch) | |
tree | 6ab44fb49bf3359e3803181dcd3ab9e1df6a65e4 | |
parent | 2e803db13067e702208818c79d70bd0ad1b13370 (diff) | |
parent | 291a9758a2b6dad177c43ee435a68dcd46959496 (diff) |
Merge remote-tracking branch 'upstream/master'
Update to latest version
-rw-r--r-- | .gitignore | 8 | ||||
-rw-r--r-- | Makefile | 29 | ||||
-rw-r--r-- | contrib/gofpdi/gofpdi.go | 143 | ||||
-rw-r--r-- | contrib/gofpdi/gofpdi_test.go | 76 | ||||
-rw-r--r-- | doc/document.md | 264 | ||||
-rw-r--r-- | doc/go.awk | 13 | ||||
-rw-r--r-- | doc/html.txt | 68 | ||||
-rw-r--r-- | go.sum | 18 | ||||
-rw-r--r-- | pdf/reference/Fpdf_SplitLines_tables.pdf | 159 | ||||
-rw-r--r-- | pdf/reference/Fpdf_UnderlineThickness.pdf | bin | 0 -> 1156 bytes | |||
-rw-r--r-- | splittext.go | 53 |
11 files changed, 831 insertions, 0 deletions
@@ -15,3 +15,11 @@ private *.swp **/*.test .idea/ +doc/body.html +doc/body.md +doc/index.html +doc/index.html.ok +coverage.html + +# macOS +.DS_Store
\ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..90624c5 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +all : documentation + +documentation : doc/index.html doc.go README.md + +cov : all + go test -v -coverprofile=coverage && go tool cover -html=coverage -o=coverage.html + +check : + golint . + go vet -all . + gofmt -s -l . + goreportcard-cli -v | grep -v cyclomatic + +README.md : doc/document.md + pandoc --read=markdown --write=gfm < $< > $@ + +doc/index.html : doc/document.md doc/html.txt + pandoc --read=markdown --write=html --template=doc/html.txt \ + --metadata pagetitle="GoFPDF Document Generator" < $< > $@ + +doc.go : doc/document.md doc/go.awk + pandoc --read=markdown --write=plain $< | awk --assign=package_name=gofpdf --file=doc/go.awk > $@ + gofmt -s -w $@ + +build : + go build -v + +clean : + rm -f coverage.html coverage doc/index.html doc.go README.md diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go new file mode 100644 index 0000000..7b9c822 --- /dev/null +++ b/contrib/gofpdi/gofpdi.go @@ -0,0 +1,143 @@ +/* +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 ( + realgofpdi "github.com/phpdave11/gofpdi" + "io" +) + +// 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) +} + +// 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 (i *Importer) ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int { + // Set source file for fpdi + i.fpdi.SetSourceFile(sourceFile) + // return template id + 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 (i *Importer) ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int { + // Set source stream for fpdi + i.fpdi.SetSourceStream(rs) + // return template id + return i.getTemplateID(f, pageno, box) +} + +func (i *Importer) getTemplateID(f gofpdiPdf, pageno int, box string) int { + // Import page + 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 := 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 := 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 := i.fpdi.GetImportedObjHashPos() + + // Import gofpdi object hashes and their positions into gopdf + f.ImportObjPos(importedObjPos) + + return tpl +} + +// 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 (i *Importer) UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) { + // Get values from fpdi + tplName, scaleX, scaleY, tX, tY := i.fpdi.UseTemplate(tplid, x, y, w, h) + + f.UseImportedTemplate(tplName, scaleX, scaleY, tX, tY) +} + +// GetPageSizes returns page dimensions for all pages of the imported pdf. +// Result consists of map[<page number>]map[<box>]map[<dimension>]<value>. +// <page number>: page number, note that page numbers start at 1 +// <box>: box identifier, e.g. "/MediaBox" +// <dimension>: 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[<page number>]map[<box>]map[<dimension>]<value>. +// <page number>: page number, note that page numbers start at 1 +// <box>: box identifier, e.g. "/MediaBox" +// <dimension>: 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() +} diff --git a/contrib/gofpdi/gofpdi_test.go b/contrib/gofpdi/gofpdi_test.go new file mode 100644 index 0000000..70ef6cc --- /dev/null +++ b/contrib/gofpdi/gofpdi_test.go @@ -0,0 +1,76 @@ +package gofpdi + +import ( + "bytes" + "github.com/jung-kurt/gofpdf" + "github.com/jung-kurt/gofpdf/internal/example" + "io" + "sync" + "testing" +) + +func ExampleNewImporter() { + // 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 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", "") + pdf.AddPage() + rs, _ := getTemplatePdf() + imp := NewImporter() + 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() + 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 +} diff --git a/doc/document.md b/doc/document.md new file mode 100644 index 0000000..b2289ce --- /dev/null +++ b/doc/document.md @@ -0,0 +1,264 @@ +# 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 + +* UTF-8 support +* 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 +* Import PDFs as templates + +gofpdf has no dependencies other than the Go standard library. All tests pass +on Linux, Mac and Windows platforms. + +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. + +## 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()`. + +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 +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. Artem Korotkiy added support of +UTF-8 fonts. Dave Barnes added support for imported objects and templates. +Brigham Thompson added support for rounded rectangles. Joe Westcott added +underline functionality and optimized image storage. + +## Roadmap + +* 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 +[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 +[test]: https://github.com/jung-kurt/gofpdf/blob/master/fpdf_test.go +[vet]: https://golang.org/cmd/vet/ diff --git a/doc/go.awk b/doc/go.awk new file mode 100644 index 0000000..bcd4a7c --- /dev/null +++ b/doc/go.awk @@ -0,0 +1,13 @@ +BEGIN { show = 0 ; print "/*" } + +/^\-/ { trim = 1 ; print "" } + +/^Package/ { show = 1 } + +!NF { trim = 0 } + +trim { sub("^ +", "", $0) } + +show { print $0 } + +END { print "*/\npackage " package_name } 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 @@ +<!doctype html> + +<html lang="en"> + +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width initial-scale=1 maximum-scale=1 minimum-scale=1 user-scalable=0" /> + <title>GoFPDF Document Generator</title> + <style> + body { + max-width: 800px; + font-family: sans-serif; + padding: 1em; + } + + img { + max-width: 800px; + } + + h1, + h2, + h3 { + color: #345; + } + + .syntax { + display: block; + white-space: pre; + font-family: monospace; + background-color: #efe; + border: 1px solid #474; + margin: 1em 0; + padding: 0.25em 1.5em; + } + + .warning { + background-color: #ffd; + border: 1px solid #665; + margin: 1em 0; + padding: 0 1em; + } + + .key { + color: #131; + font-weight: bold; + } + + .subkey { + font-style: italic; + } + + pre { + margin: 1.5em 0; + background-color: #eee; + padding: 1em; + overflow-x: scroll; + } +$if(highlighting-css)$ +$highlighting-css$ +$endif$ + </style> +</head> + +<body> +$body$ +</body> + +</html> @@ -0,0 +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.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-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= 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 +<</Type /Page +/Parent 1 0 R +/Resources 2 0 R +/Contents 4 0 R>> +endobj +4 0 obj +<</Length 4847>> +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 +<</Type /Pages +/Kids [3 0 R ] +/Count 1 +/MediaBox [0 0 595.28 841.89] +>> +endobj +5 0 obj +<</Type /Font +/BaseFont /Helvetica +/Subtype /Type1 +/Encoding /WinAnsiEncoding +>> +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 diff --git a/pdf/reference/Fpdf_UnderlineThickness.pdf b/pdf/reference/Fpdf_UnderlineThickness.pdf Binary files differnew file mode 100644 index 0000000..49ad9b1 --- /dev/null +++ b/pdf/reference/Fpdf_UnderlineThickness.pdf diff --git a/splittext.go b/splittext.go new file mode 100644 index 0000000..525f93b --- /dev/null +++ b/splittext.go @@ -0,0 +1,53 @@ +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) || isChinese(c) { + 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 +} |