Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix stamp transform calc
  • Loading branch information
hhrutter committed Feb 24, 2019
1 parent be6b07a commit 6e1af9e
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 24 deletions.
12 changes: 8 additions & 4 deletions pkg/pdfcpu/context.go
Expand Up @@ -30,9 +30,11 @@ import (
type Context struct {
*Configuration
*XRefTable
Read *ReadContext
Optimize *OptimizationContext
Write *WriteContext
Read *ReadContext
Optimize *OptimizationContext
Write *WriteContext
writingPages bool // true, when writing page dicts.
dest bool // true when writing a destination within a page.
}

// NewContext initializes a new Context.
Expand All @@ -48,6 +50,8 @@ func NewContext(rs io.ReadSeeker, fileName string, fileSize int64, config *Confi
newReadContext(rs, fileName, fileSize),
newOptimizationContext(),
NewWriteContext(config.Eol),
false,
false,
}

return ctx, nil
Expand Down Expand Up @@ -572,7 +576,7 @@ func (wc *WriteContext) HasWriteOffset(objNumber int) bool {
return found
}

// ReducedFeatureSet returns true for Split,Trim,Merge,ExtractPages.
// ReducedFeatureSet returns true for some operations.
// Don't confuse with pdfcpu commands, these are internal triggers.
func (wc *WriteContext) ReducedFeatureSet() bool {
switch wc.Command {
Expand Down
2 changes: 1 addition & 1 deletion pkg/pdfcpu/crypto.go
Expand Up @@ -340,7 +340,7 @@ func validateOwnerPassword(ctx *Context) (ok bool, k []byte, err error) {
ownerpw := ctx.OwnerPW
userpw := ctx.UserPW

//fmt.Printf("ValidateOwnerPassword: ownerpw=ctx.OwnerPW=%s userpw=ctx.UserPW=%s\n", ownerpw, userpw)
//fmt.Printf("ValidateOwnerPassword: ownerpw=ctx.OwnerPW:<%s> userpw=ctx.UserPW:<%s>\n", ownerpw, userpw)

e := ctx.E

Expand Down
109 changes: 98 additions & 11 deletions pkg/pdfcpu/read.go
Expand Up @@ -19,6 +19,7 @@ package pdfcpu
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"sort"
Expand Down Expand Up @@ -780,6 +781,98 @@ func scanLine(s *bufio.Scanner) (string, error) {
return s.Text(), nil
}

func scanTrailer(s *bufio.Scanner, line string) (string, error) {

var buf bytes.Buffer
var err error
var i, j, k int

log.Read.Printf("line: <%s>\n", line)

// Scan for dict start tag "<<".
for {
i = strings.Index(line, "<<")
if i >= 0 {
break
}
line, err = scanLine(s)
log.Read.Printf("line: <%s>\n", line)
if err != nil {
return "", err
}
}

line = line[i:]
buf.WriteString(line)
buf.WriteString(" ")
log.Read.Printf("scanTrailer dictBuf after start tag: <%s>\n", line)

// Scan for dict end tag ">>" but account for inner dicts.
line = line[2:]

for {

if len(line) == 0 {
line, err = scanLine(s)
if err != nil {
return "", err
}
buf.WriteString(line)
buf.WriteString(" ")
log.Read.Printf("scanTrailer dictBuf next line: <%s>\n", line)
}

i = strings.Index(line, "<<")
if i < 0 {
// No <<
j = strings.Index(line, ">>")
if j >= 0 {
// Yes >>
if k == 0 {
return buf.String(), nil
}
k--
println(k)
line = line[j+2:]
continue
}
// No >>
line, err = scanLine(s)
if err != nil {
return "", err
}
buf.WriteString(line)
buf.WriteString(" ")
log.Read.Printf("scanTrailer dictBuf next line: <%s>\n", line)
} else {
// Yes <<
j = strings.Index(line, ">>")
if j < 0 {
// No >>
k++
println(k)
line = line[i+2:]
} else {
// Yes >>
if i < j {
// handle <<
k++
println(k)
line = line[i+2:]
} else {
// handle >>
if k == 0 {
return buf.String(), nil
}
k--
println(k)
line = line[j+2:]
}
}
}
}
}

func scanTrailerDict(s *bufio.Scanner, startTag bool) (string, error) {

var buf bytes.Buffer
Expand Down Expand Up @@ -864,16 +957,9 @@ func parseXRefSection(s *bufio.Scanner, ctx *Context) (*int64, error) {
log.Read.Printf("line (len %d) <%s>\n", len(line), line)
}

// Unless trailerDict already scanned into trailerString
if strings.Index(trailerString, ">>") == -1 {

// scan lines until we have the complete trailer dict: << ... >>
trailerDictString, err := scanTrailerDict(s, strings.Index(trailerString, "<<") > 0)
if err != nil {
return nil, err
}

trailerString += trailerDictString
trailerString, err = scanTrailer(s, trailerString)
if err != nil {
return nil, err
}

log.Read.Printf("parseXRefSection: trailerString: (len:%d) <%s>\n", len(trailerString), trailerString)
Expand Down Expand Up @@ -2179,6 +2265,7 @@ func setupEncryptionKey(ctx *Context, encryptDictObjNr int) error {
if err != nil {
return err
}
fmt.Printf("read: id = %0X\n", enc.ID)

var ok bool

Expand All @@ -2189,7 +2276,7 @@ func setupEncryptionKey(ctx *Context, encryptDictObjNr int) error {
}

// If the owner password does not match we generally move on if the user password is correct
// unless we need to insist on a correct owner password.
// unless we need to insist on a correct owner password due to the specific command in progress.
if !ok && needsOwnerAndUserPassword(ctx.Mode) {
return errors.New("owner password authentication error")
}
Expand Down
18 changes: 14 additions & 4 deletions pkg/pdfcpu/stamp.go
Expand Up @@ -150,6 +150,16 @@ func (wm Watermark) String() string {
sc = "absolute"
}

bbox := ""
if wm.bb != nil {
bbox = (*wm.bb).String()
}

vp := ""
if wm.vp != nil {
vp = (*wm.vp).String()
}

return fmt.Sprintf("Watermark: <%s> is %son top, typ:%s\n"+
"%s %d points\n"+
"PDFpage#: %d\n"+
Expand All @@ -171,8 +181,8 @@ func (wm Watermark) String() string {
wm.diagonal,
wm.opacity,
wm.renderMode,
*wm.bb,
*wm.vp,
bbox,
vp,
wm.pageRot,
)
}
Expand Down Expand Up @@ -287,8 +297,8 @@ func (wm *Watermark) calcTransformMatrix() *matrix {
dy = wm.bb.LL.Y
}

m2[2][0] = wm.vp.Width()/2 + sin*(wm.bb.Height()/2+dy) - cos*wm.bb.Width()/2
m2[2][1] = wm.vp.Height()/2 - cos*(wm.bb.Height()/2+dy) - sin*wm.bb.Width()/2
m2[2][0] = wm.vp.LL.X + wm.vp.Width()/2 + sin*(wm.bb.Height()/2+dy) - cos*wm.bb.Width()/2
m2[2][1] = wm.vp.LL.Y + wm.vp.Height()/2 - cos*(wm.bb.Height()/2+dy) - sin*wm.bb.Width()/2

m := m1.multiply(m2)
return &m
Expand Down
5 changes: 5 additions & 0 deletions pkg/pdfcpu/validate/info.go
Expand Up @@ -93,6 +93,11 @@ func validateDocumentInfoDict(xRefTable *pdf.XRefTable, obj pdf.Object) (hasModD
// name, optional, since V1.3
case "Trapped":
validate := func(s string) bool { return pdf.MemberOf(s, []string{"True", "False", "Unknown"}) }
if xRefTable.ValidationMode == pdf.ValidationRelaxed {
validate = func(s string) bool {
return pdf.MemberOf(s, []string{"True", "False", "Unknown", "true", "false", "unknown"})
}
}
_, err = xRefTable.DereferenceName(v, pdf.V13, validate)

// text string, optional
Expand Down
22 changes: 18 additions & 4 deletions pkg/pdfcpu/writeObjects.go
Expand Up @@ -523,16 +523,23 @@ func writeDirectObject(ctx *Context, o Object) error {
switch o := o.(type) {

case Dict:
for _, v := range o {
for k, v := range o {
if ctx.writingPages && (k == "Dest" || k == "D") {
ctx.dest = true
}
_, _, err := writeDeepObject(ctx, v)
if err != nil {
return err
}
ctx.dest = false
}
log.Write.Printf("writeDirectObject: end offset=%d\n", ctx.Write.Offset)

case Array:
for _, v := range o {
for i, v := range o {
if ctx.dest && i == 0 {
continue
}
_, _, err := writeDeepObject(ctx, v)
if err != nil {
return err
Expand Down Expand Up @@ -568,11 +575,15 @@ func writeDeepDict(ctx *Context, d Dict, objNr, genNr int) error {
return err
}

for _, v := range d {
for k, v := range d {
if ctx.writingPages && (k == "Dest" || k == "D") {
ctx.dest = true
}
_, _, err = writeDeepObject(ctx, v)
if err != nil {
return err
}
ctx.dest = false
}

return nil
Expand Down Expand Up @@ -609,7 +620,10 @@ func writeDeepArray(ctx *Context, a Array, objNr, genNr int) error {
return err
}

for _, v := range a {
for i, v := range a {
if ctx.dest && i == 0 {
continue
}
_, _, err = writeDeepObject(ctx, v)
if err != nil {
return err
Expand Down
5 changes: 5 additions & 0 deletions pkg/pdfcpu/writePages.go
Expand Up @@ -61,6 +61,8 @@ func writePageDict(ctx *Context, ir *IndirectRef, pageDict Dict, pageNr int) err
return errors.New("writePageDict: missing parent")
}

ctx.writingPages = true

for _, e := range []struct {
entryName string
statsAttr int
Expand Down Expand Up @@ -100,6 +102,8 @@ func writePageDict(ctx *Context, ir *IndirectRef, pageDict Dict, pageNr int) err
}
}

ctx.writingPages = false

log.Write.Printf("*** writePageDict end: obj#%d offset=%d ***\n", objNr, ctx.Write.Offset)

return nil
Expand Down Expand Up @@ -253,6 +257,7 @@ func writePagesDict(ctx *Context, ir *IndirectRef, pageNr *int) (skip bool, writ
d.Update("Kids", kidsNew)
d.Update("Count", Integer(countNew))
log.Write.Printf("writePagesDict: writing pageDict for obj=%d page=%d\n%s", objNr, *pageNr, d)

err = writeDictObject(ctx, objNr, genNr, d)
if err != nil {
return false, 0, err
Expand Down

0 comments on commit 6e1af9e

Please sign in to comment.