8000 Release v3.0.1 by gunnsth · Pull Request #70 · unidoc/unipdf · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Release v3.0.1 #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 42 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,62 @@
# UniPDF - PDF for Go

[UniDoc](http://unidoc.io)'s UniPDF is a powerful PDF library for Go (golang) with capabilities for
creating and processing PDF files. The library is written and supported by
the [FoxyUtils.com](https://foxyutils.com) website, where the library is used to power
many of the PDF services offered.
[UniDoc](http://unidoc.io)'s UniPDF (formerly unidoc) is a PDF library for Go (golang) with capabilities for
creating and reading, processing PDF files. The library is written and supported by
[FoxyUtils.com](https://foxyutils.com), where the library is used to power many of its services.

[![Build Status](https://app.wercker.com/status/22b50db125a6d376080f3f0c80d085fa/s/master "wercker status")](https://app.wercker.com/project/bykey/22b50db125a6d376080f3f0c80d085fa)
[![GitHub (pre-)release](https://img.shields.io/github/release/unidoc/unipdf/all.svg)](https://github.com/unidoc/unipdf/releases)
[![License: AGPL v3](https://img.shields.io/badge/License-Dual%20AGPL%20v3/Commercial-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
[![Go Report Card](https://goreportcard.com/badge/github.com/unidoc/unipdf)](https://goreportcard.com/report/github.com/unidoc/unipdf)
[![GoDoc](https://godoc.org/github.com/unidoc/unipdf?status.svg)](https://godoc.org/github.com/unidoc/unipdf)

## News
- unidoc is being renamed to unipdf and will be maintained under https://github.com/unidoc/unipdf
- The old repository will remain under https://github.com/unidoc/unidoc for backwards compatibility and will be read-only.
All development will be under the unipdf repository.
- The initial release of unipdf v3.0.0 will be compliant with Go modules from the start.
## Features

- [Create PDF reports](https://github.com/unidoc/unipdf-examples/blob/v3/report/pdf_report.go)
- [Invoice creation](https://unidoc.io/news/simple-invoices)
- Advanced table generation in the creator with subtable support
- Paragraph in creator handling multiple styles within the same paragraph
- [Merge PDF pages](https://github.com/unidoc/unipdf-examples/blob/v3/pages/pdf_merge.go)
- [Split PDF pages](https://github.com/unidoc/unipdf-examples/blob/v3/pages/pdf_split.go) and change page order
- [Rotate pages](https://github.com/unidoc/unipdf-examples/blob/v3/pages/pdf_rotate.go)
- [Extract text from PDF files](https://github.com/unidoc/unipdf-examples/blob/v3/text/pdf_extract_text.go)
- [Extract images](https://github.com/unidoc/unipdf-examples/blob/v3/image/pdf_extract_images.go) with coordinates
- [Images to PDF](https://github.com/unidoc/unipdf-examples/blob/v3/image/pdf_images_to_pdf.go)
- [Add images to pages](https://github.com/unidoc/unipdf-examples/blob/v3/image/pdf_add_image_to_page.go)
- [Compress and optimize PDF](https://github.com/unidoc/unipdf-examples/blob/v3/compress/pdf_optimize.go)
- [Watermark PDF files](https://github.com/unidoc/unipdf-examples/blob/v3/image/pdf_watermark_image.go)
- Advanced page manipulation (blocks/templates)
- Load PDF templates and modify
- [Form creation](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_add.go)
- [Fill and flatten forms](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_flatten.go)
- [Fill out forms](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_fill_json.go) and [FDF merging](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_fill_fdf_merge.go)
- [Unlock PDF files / remove password](https://github.com/unidoc/unipdf-examples/blob/v3/security/pdf_unlock.go)
- [Protect PDF files with a password](https://github.com/unidoc/unipdf-examples/blob/v3/security/pdf_protect.go)
- [Digital signing validation and signing](https://github.com/unidoc/unipdf-examples/tree/v3/signatures)
- CCITTFaxDecode decoding and encoding support

## Features
unipdf has a powerful set of features both for reading, processing and writing PDF.
The following list describes some key features:

- [x] [Create PDF reports](https://github.com/unidoc/unipdf-examples/blob/v3/report/pdf_report.go)
- [x] [Create PDF invoices](https://unidoc.io/news/simple-invoices)
- [x] Advanced table generation in the creator with subtable support
- [x] Paragraph in creator handling multiple styles within the same paragraph
- [x] Table of contents automatically generated
- [x] Text extraction significantly improved in quality and foundation in place for vectorized (position-based) text extraction (XY)
- [x] Image extraction with coordinates
- [x] [Merge PDF pages](https://github.com/unidoc/unipdf-examples/blob/v3/pages/pdf_merge.go)
- [x] Merge page contents
- [x] [Split PDF pages and change page order](https://github.com/unidoc/unipdf-examples/blob/v3/pages/pdf_split.go)
- [x] [Rotate pages](https://github.com/unidoc/unipdf-examples/blob/v3/pages/pdf_rotate.go)
- [x] [Extract text from PDF files](https://github.com/unidoc/unipdf-examples/blob/v3/text/pdf_extract_text.go)
- [x] Extract images
- [x] Add images to pages
- [x] [Compress and optimize PDF output](https://github.com/unidoc/unipdf-examples/blob/v3/compress/pdf_optimize.g)
- [x] [Draw watermark on PDF files](https://github.com/unidoc/unipdf-examples/blob/v3/image/pdf_watermark_image.go)
- [x] Advanced page manipulation (blocks/templates)
- [x] Load PDF templates and modify
- [x] [Flatten forms and generate appearance streams](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_flatten.go)
- [x] [Fill out forms and FDF merging](https://github.com/unidoc/unipdf-examples/tree/v3/forms)
- [x] [FDF merge](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_fill_fdf_merge.go) and [form filling via JSON data](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_fill_json.go)
- [x] [Form creation](https://github.com/unidoc/unipdf-examples/blob/v3/forms/pdf_form_add.go)
- [x] [Unlock PDF files / remove password](https://github.com/unidoc/unipdf-examples/blob/v3/security/pdf_unlock.go)
- [x] [Protect PDF files with a password](https://github.com/unidoc/unipdf-examples/blob/v3/security/pdf_protect.go)
- [x] [Digital signing validation and signing](https://github.com/unidoc/unipdf-examples/tree/v3/signatures)
- [x] CCITTFaxDecode decoding and encoding support
- [x] Append mode
Multiple examples are provided in our example repository https://github.com/unidoc/unidoc-examples
as well as [documented examples](https://unidoc.io/examples) on our website.

Contact us if you need any specific examples.

## News
- unidoc has been renamed to unipdf and is maintained under https://github.com/unidoc/unipdf
- The old repository remains under https://github.com/unidoc/unidoc for backwards compatibility and will be read-only.
All development is under the unipdf repository.
- The initial release of unipdf v3.0.0 is compatible with Go modules from the start.

## Installation
With modules:
~~~
go get github.com/unidoc/unipdf/v3
~~~

With GOPATH:
~~~
go get github.com/unidoc/unipdf/...
~~~


## How can I convince myself and my boss to buy unipdf rather using a free alternative?

Expand All @@ -67,13 +69,6 @@ Security. We take security very seriously and we restrict access to github.com/
The profits are invested back into making unipdf better. We want to make the best possible product and in order to do that we need the best people to contribute. A large fraction of the profits made goes back into developing unipdf. That way we have been able to get many excellent people to work and contribute to unipdf that would not be able to contribute their work for free.


## Examples

Multiple examples are provided in our example repository https://github.com/unidoc/unidoc-examples
as well as [documented examples](https://unidoc.io/examples) on our website.

Contact us if you need any specific examples.

## Contributing

[![CLA assistant](https://cla-assistant.io/readme/badge/unidoc/unipdf)](https://cla-assistant.io/unidoc/unipdf)
Expand Down
8 changes: 4 additions & 4 deletions common/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (
)

const releaseYear = 2019
const releaseMonth = 4
const releaseDay = 20
const releaseHour = 23
const releaseMonth = 6
const releaseDay = 2
const releaseHour = 11
const releaseMin = 30

// Version holds version information, when bumping this make sure to bump the released at stamp also.
const Version = "3.0.0-rc.1"
const Version = "3.0.1"

var ReleasedAt = time.Date(releaseYear, releaseMonth, releaseDay, releaseHour, releaseMin, 0, 0, time.UTC)
5 changes: 4 additions & 1 deletion core/primitives.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,13 +605,16 @@ func (array *PdfObjectArray) GetAsFloat64Slice() ([]float64, error) {
}

// Merge merges in key/values from another dictionary. Overwriting if has same keys.
func (d *PdfObjectDictionary) Merge(another *PdfObjectDictionary) {
// The mutated dictionary (d) is returned in order to allow method chaining.
func (d *PdfObjectDictionary) Merge(another *PdfObjectDictionary) *PdfObjectDictionary {
if another != nil {
for _, key := range another.Keys() {
val := another.Get(key)
d.Set(key, val)
}
}

return d
}

// String returns a string describing `d`.
Expand Down
43 changes: 43 additions & 0 deletions creator/styled_paragraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,49 @@ func (p *StyledParagraph) Height() float64 {
return height
}

// getLineHeight returns both the capheight and the font size based height of
// the line with the specified index.
func (p *StyledParagraph) getLineHeight(idx int) (capHeight, height float64) {
if p.lines == nil || len(p.lines) == 0 {
p.wrapText()
}
if idx < 0 || idx > len(p.lines)-1 {
common.Log.Debug("ERROR: invalid paragraph line index %d. Returning 0, 0", idx)
return 0, 0
}

line := p.lines[idx]
for _, chunk := range line {
descriptor, err := chunk.Style.Font.GetFontDescriptor()
if err != nil {
common.Log.Debug("ERROR: Unable to get font descriptor")
}

var fontCapHeight float64
if descriptor != nil {
if fontCapHeight, err = descriptor.GetCapHeight(); err != nil {
common.Log.Debug("ERROR: Unable to get font CapHeight: %v", err)
}
}
if int(fontCapHeight) <= 0 {
common.Log.Debug("WARN: CapHeight not available - setting to 1000")
fontCapHeight = 1000
}

h := fontCapHeight / 1000.0 * chunk.Style.FontSize * p.lineHeight
if h > capHeight {
capHeight = h
}

h = p.lineHeight * chunk.Style.FontSize
if h > height {
height = h
}
}

return capHeight, height
}

// getTextWidth calculates the text width as if all in one line (not taking
// wrapping into account).
func (p *StyledParagraph) getTextWidth() float64 {
Expand Down
63 changes: 63 additions & 0 deletions creator/styled_paragraph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -798,3 +798,66 @@ func TestStyledLinkRotation(t *testing.T) {
t.Fatalf("Fail: %v\n", err)
}
}

func TestStyledParagraphTableVerticalAlignment(t *testing.T) {
c := New()

fontRegular := newStandard14Font(t, model.CourierName)

createTable := func(c *Creator, text string, align CellVerticalAlignment, fontSize float64) {
textStyle := c.NewTextStyle()
textStyle.Font = fontRegular
textStyle.FontSize = fontSize

table := c.NewTable(1)
table.SetMargins(0, 0, 5, 5)

cell := table.NewCell()
sp := c.NewStyledParagraph()
textChunk := sp.Append(text)
textChunk.Style = textStyle

cell.SetVerticalAlignment(align)
cell.SetContent(sp)
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)

if err := c.Draw(table); err != nil {
t.Fatalf("Error drawing: %v", err)
}
}

chunks := []string{
"TR",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt.",
}

alignments := []struct {
Label string
Alignment CellVerticalAlignment
}{
{"Top alignment", CellVerticalAlignmentTop},
{"Middle alignment", CellVerticalAlignmentMiddle},
{"Bottom alignment", CellVerticalAlignmentBottom},
}

for _, chunk := range chunks {
for _, alignment := range alignments {
c.NewPage()

sp := c.NewStyledParagraph()
sp.Append(alignment.Label).Style.FontSize = 16
sp.SetMargins(0, 0, 0, 5)

if err := c.Draw(sp); err != nil {
t.Fatalf("Error drawing: %v", err)
}

for i := 4; i <= 20; i += 2 {
createTable(c, chunk, alignment.Alignment, float64(i))
}
}
}

// Write output file.
testWriteAndRender(t, c, "styled_paragraph_table_vertical_align.pdf")
}
33 changes: 29 additions & 4 deletions creator/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,10 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
}

if cell.content != nil {
// content width.
cw := cell.content.Width()
cw := cell.content.Width() // content width.
ch := cell.content.Height() // content height.
vertOffset := 0.0

switch t := cell.content.(type) {
case *Paragraph:
if t.enableWrap {
Expand All @@ -527,6 +529,26 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
if t.enableWrap {
cw = t.getMaxLineWidth() / 1000.0
}

// Calculate the height of the paragraph.
lineCapHeight, lineHeight := t.getLineHeight(0)
if len(t.lines) == 1 {
ch = lineCapHeight
} else {
ch = ch - lineHeight + lineCapHeight
}

// Account for the top offset the paragraph adds.
vertOffset = lineCapHeight - t.defaultStyle.FontSize*t.lineHeight

switch cell.verticalAlignment {
case CellVerticalAlignmentTop:
// Add a bit of space from the top border of the cell.
vertOffset += lineCapHeight * 0.5
case CellVerticalAlignmentBottom:
// Add a bit of space from the bottom border of the cell.
vertOffset -= lineCapHeight * 0.5
}
case *Table:
cw = w
case *List:
Expand All @@ -553,8 +575,9 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
}
}

ctx.Y += vertOffset

// Account for vertical alignment.
ch := cell.content.Height() // content height.
switch cell.verticalAlignment {
case CellVerticalAlignmentTop:
// Default: do nothing.
Expand All @@ -567,14 +590,16 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
case CellVerticalAlignmentBottom:
if h > ch {
ctx.Y = ctx.Y + h - ch
ctx.Height = ch
ctx.Height = h
}
}

err := block.DrawWithContext(cell.content, ctx)
if err != nil {
common.Log.Debug("ERROR: %v", err)
}

ctx.Y -= vertOffset
}

ctx.Y += h
Expand Down
4 changes: 2 additions & 2 deletions internal/e2etest/split_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ var (
// knownHashes defines a list of known output hashes to ensure that the output is constant.
// If there is a change in hash need to find out why and update only if the change is accepted.
var knownHashes = map[string]string{
"bf7c9d5dabc7e7ec2fc0cf9db2d9c8e7aa456fca.pdf": "f7891d491fa9f20ed2975dd28961c205",
"371dce2c2720581a3eef3f123e5741dd3566ef87.pdf": "4a25934226b6b64e5d95d571260b1f01",
"bf7c9d5dabc7e7ec2fc0cf9db2d9c8e7aa456fca.pdf": "fdd638603c6f655babbc90358de66107",
"371dce2c2720581a3eef3f123e5741dd3566ef87.pdf": "4c5356ac623a96004d80315f24613fff",
"e815311526b50036db6e89c54af2b9626edecf30.pdf": "97dcfdde59a2f3a6eb105d0c31ebd3fb",
"3bf64014e0c9e4a56f1a9363f1b34fd707bd9fa0.pdf": "6f310c9fdd44d49766d3cc32d3053b89",
"004feecd47e2da4f2ed5cdbbf4791a77dd59ce20.pdf": "309a072a97d0566aa3f85edae504bb53",
Expand Down
4 changes: 3 additions & 1 deletion model/appender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ func TestAppenderNoop(t *testing.T) {
appender, err := model.NewPdfAppender(reader)
require.NoError(t, err)

model.SetPdfProducer("UniPDF")
model.SetPdfCreator("UniDoc UniPDF")
err = appender.WriteToFile(tempFile("appender_noop.pdf"))
if err != nil {
t.Errorf("Fail: %v\n", err)
Expand Down Expand Up @@ -123,7 +125,7 @@ func TestAppenderNoop(t *testing.T) {
3: core.XrefObject{ObjectNumber: 3, XType: 0, Offset: 178},
4: core.XrefObject{ObjectNumber: 4, XType: 0, Offset: 457},
5: core.XrefObject{ObjectNumber: 5, XType: 0, Offset: 740},
6: core.XrefObject{ObjectNumber: 6, XType: 0, Offset: 860},
6: core.XrefObject{ObjectNumber: 6, XType: 0, Offset: 802},
}
require.Equal(t, expected, xrefs.ObjectMap)
}
Expand Down
Loading
0