Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

Commit

Permalink
Merge pull request #85 from juruen/juruen/unipdf-annotations
Browse files Browse the repository at this point in the history
Use unipdf to generate overlay annotations on top of original PDF docs
  • Loading branch information
juruen authored Feb 1, 2020
2 parents a049105 + 543c6a8 commit 690f648
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 37 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

* Change license to AGPL

* Initial support for PDF annotations with UniPDF

## rmapi 0.0.8 (January 06, 2020)

* Add support for v5 annotations
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ docker run -v $HOME/.rmapi/:/home/user/.rmapi/ rmapi help

# Annotations

- Initial support to generate a PDF with annotations from `Quick Sheet` and notebooks.
- Initial support to generate a PDF with annotations.

# Shell ergonomics

Expand Down Expand Up @@ -136,7 +136,7 @@ mget .

## Download a file and generate a PDF with its annoations

Use `geta` to download either a `Quick Sheets` or `notebook` file and generate a PDF document
Use `geta` to download a file and generate a PDF document
with its annotations.

Please note that its support is very basic for now and only supports one type of pen for now, but
Expand Down
86 changes: 59 additions & 27 deletions annotations/pdf.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,41 @@
package annotations

import (
"fmt"
"bytes"
"os"

"github.com/jung-kurt/gofpdf"
"github.com/juruen/rmapi/archive"
"github.com/juruen/rmapi/encoding/rm"
"github.com/unidoc/unipdf/v3/creator"
pdf "github.com/unidoc/unipdf/v3/model"
)

const (
RmX = rm.Width
RmY = rm.Height
A4X = 210
A4Y = 297
ratioA4X = float32(A4X) / float32(RmX)
ratioA4Y = float32(A4Y) / float32(RmY)
ratioA4X = float32(0.443)
ratioA4Y = float32(0.443)
)

type PdfGenerator struct {
zipName string
outputFilePath string
options PdfGeneratorOptions
pdfReader *pdf.PdfReader
template bool
}

type PdfGeneratorOptions struct {
AddPageNumbers bool
}

func CreatePdfGenerator(zipName, outputFilePath string, options PdfGeneratorOptions) PdfGenerator {
return PdfGenerator{zipName: zipName, outputFilePath: outputFilePath, options: options}
func CreatePdfGenerator(zipName, outputFilePath string, options PdfGeneratorOptions) *PdfGenerator {
return &PdfGenerator{zipName: zipName, outputFilePath: outputFilePath, options: options}
}

func (p PdfGenerator) Generate() error {
func (p *PdfGenerator) Generate() error {
file, err := os.Open(p.zipName)
if err != nil {
return err
}
defer file.Close()
defer func() { _ = file.Close() }()

zip := archive.NewZip()

Expand All @@ -51,22 +49,18 @@ func (p PdfGenerator) Generate() error {
return err
}

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

pdf.SetFont("Arial", "", 10)
for i, page := range zip.Pages {
if page.Data == nil {
continue
}
if err = p.initBackgroundPages(zip.Pdf); err != nil {
return err
}

pdf.AddPage()
if p.options.AddPageNumbers {
pdf.Cell(0, 0, fmt.Sprintf("%d", i+1))
c := creator.New()
for i, pageAnnotations := range zip.Pages {
if err := p.addBackgroundPage(c, i+1); err != nil {
return err
}

for _, layer := range page.Data.Layers {
for _, layer := range pageAnnotations.Data.Layers {
for _, line := range layer.Lines {

if len(line.Points) < 1 {
continue
}
Expand All @@ -80,11 +74,49 @@ func (p PdfGenerator) Generate() error {
x2 := s.X * ratioA4X
y2 := s.Y * ratioA4Y

pdf.Line(float64(x1), float64(y1), float64(x2), float64(y2))
line := c.NewLine(float64(x1), float64(y1), float64(x2), float64(y2))
line.SetLineWidth(0.6)
black := creator.ColorRGBFromHex("#000000")
line.SetColor(black)
c.Draw(line)
}
}
}
}

return pdf.OutputFileAndClose(p.outputFilePath)
return c.WriteToFile(p.outputFilePath)
}

func (p *PdfGenerator) initBackgroundPages(pdfArr []byte) error {
if len(pdfArr) > 0 {
pdfReader, err := pdf.NewPdfReader(bytes.NewReader(pdfArr))
if err != nil {
return err
}

p.pdfReader = pdfReader
p.template = false
return nil
}

p.template = true
return nil
}

func (p *PdfGenerator) addBackgroundPage(c *creator.Creator, pageNum int) error {
if p.template == false {
page, err := p.pdfReader.GetPage(pageNum)
if err != nil {
return err
}

if err = c.AddPage(page); err != nil {
return err
}
return nil
}

c.NewPage()
c.SetPageSize(creator.PageSizeA4)
return nil
}
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/juruen/rmapi

go 1.12
go 1.13

require (
github.com/abiosoft/ishell v0.0.0-20180125194311-42a9bbfa0017
Expand All @@ -11,14 +11,15 @@ require (
github.com/fatih/color v0.0.0-20170926111411-5df930a27be2 // indirect
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
github.com/google/uuid v1.1.1
github.com/jung-kurt/gofpdf v0.0.0-20181227150023-8baf016b4b80
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/pkg/errors v0.8.1
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5
github.com/stretchr/testify v0.0.0-20171231124224-87b1dfb5b2fa
github.com/stretchr/testify v1.3.0
github.com/unidoc/unipdf/v3 v3.3.1
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.0.0
)

replace github.com/unidoc/unipdf/v3 => github.com/juruen/unipdf/v3 v3.3.1
35 changes: 31 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
github.com/abiosoft/ishell v0.0.0-20180125194311-42a9bbfa0017 h1:OI0WxLr8BwNwiJqQHpxZpOxcKre7x0YODdFW/9bhQOo=
github.com/abiosoft/ishell v0.0.0-20180125194311-42a9bbfa0017/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3 h1:T7Bw4H6z3WAZ2khw+gfKdYmbKHyy5xiHtk9IHfZqm7g=
github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
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/fatih/color v0.0.0-20170926111411-5df930a27be2 h1:40J76vs1Y7oiHFqTrQHQ6A5u8vbXJdLaMkC9iHU/uMw=
Expand All @@ -14,8 +17,10 @@ github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWT
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jung-kurt/gofpdf v0.0.0-20181227150023-8baf016b4b80 h1:hdnUCulfKEa2JswLcITu0KYqb/PIbuXzSspQrVYc9FA=
github.com/jung-kurt/gofpdf v0.0.0-20181227150023-8baf016b4b80/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/gunnsth/pkcs7 v0.0.0-20181213175627-3cffc6fbfe83 h1:saj5dTV7eQ1wFg/gVZr1SfbkOmg8CYO9R8frHgQiyR4=
github.com/gunnsth/pkcs7 v0.0.0-20181213175627-3cffc6fbfe83/go.mod h1:xaGEIRenAiJcGgd9p62zbiP4993KaV3PdjczwGnP50I=
github.com/juruen/unipdf/v3 v3.3.1 h1:0qjWIdpS896/tqmoyQFvST5j+XPXSyIiOsyC4e4FStI=
github.com/juruen/unipdf/v3 v3.3.1/go.mod h1:deHLROTLv9UDHIcWQFbjcrEZ4aTwyhPXX0fvpyoZyAM=
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=
Expand All @@ -32,11 +37,33 @@ 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/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5 h1:tfcGHuraNSEY9xRb9ckCMqMD7xAjzrYI1WpD7DA+nz8=
github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/stretchr/testify v0.0.0-20171231124224-87b1dfb5b2fa h1:ws/U/9eA/uVBX3BckIHVlYLtQLuWodrnpPBuL8Q0N1E=
github.com/stretchr/testify v0.0.0-20171231124224-87b1dfb5b2fa/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/unidoc/unipdf/v3 v3.3.1 h1:nhYPhFDVkfNNkvmh/Mq4ZMyo1b+a3ol1/7fV0zx/XsM=
github.com/unidoc/unipdf/v3 v3.3.1/go.mod h1:deHLROTLv9UDHIcWQFbjcrEZ4aTwyhPXX0fvpyoZyAM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b h1:VHyIDlv3XkfCa5/a81uzaoDkHH4rr81Z62g+xlnO8uM=
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190606173856-1492cefac77f/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190606174628-0139d5756a7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
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.0.0 h1:uUkhRGrsEyx/laRdeS6YIQKIys8pg+lRSRdVMTYjivs=
Expand Down

0 comments on commit 690f648

Please sign in to comment.