Skip to content

Commit d1c808d

Browse files
authored
Merge pull request #274 from gunnsth/release/v3.5.0
Prepare unipdf release v3.5.0
2 parents ea9988f + 4bdda0a commit d1c808d

File tree

26 files changed

+3498
-104
lines changed

26 files changed

+3498
-104
lines changed

common/license/key.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@ func (k *LicenseKey) Validate() error {
7979
}
8080

8181
if k.ExpiresAt == nil {
82-
k.ExpiresAt = &noLicenseExpiry
82+
expiresAt := k.CreatedAt.AddDate(1, 0, 0)
83+
if noLicenseExpiry.After(expiresAt) {
84+
expiresAt = noLicenseExpiry
85+
}
86+
k.ExpiresAt = &expiresAt
8387
}
8488

8589
if k.CreatedAt.After(*k.ExpiresAt) {

common/version.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import (
1111
)
1212

1313
const releaseYear = 2020
14-
const releaseMonth = 2
15-
const releaseDay = 10
16-
const releaseHour = 8
17-
const releaseMin = 50
14+
const releaseMonth = 3
15+
const releaseDay = 8
16+
const releaseHour = 23
17+
const releaseMin = 40
1818

1919
// Version holds version information, when bumping this make sure to bump the released at stamp also.
20-
const Version = "3.4.0"
20+
const Version = "3.5.0"
2121

2222
var ReleasedAt = time.Date(releaseYear, releaseMonth, releaseDay, releaseHour, releaseMin, 0, 0, time.UTC)

go.mod

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
module github.com/unidoc/unipdf/v3
22

33
require (
4+
github.com/adrg/sysfont v0.1.0
45
github.com/boombuler/barcode v1.0.0
6+
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
57
github.com/gunnsth/pkcs7 v0.0.0-20181213175627-3cffc6fbfe83
68
github.com/stretchr/testify v1.3.0
79
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5
810
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b
9-
golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect
10-
golang.org/x/net v0.0.0-20190606173856-1492cefac77f // indirect
11-
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 // indirect
1211
golang.org/x/text v0.3.2
13-
golang.org/x/tools v0.0.0-20190606174628-0139d5756a7d // indirect
1412
)

go.sum

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
github.com/adrg/strutil v0.1.0 h1:IOQnSOAjbE17+7l1lw4rXgX6JuSeJGdZa7BucTMV3Qg=
2+
github.com/adrg/strutil v0.1.0/go.mod h1:pXRr2+IyX5AEPAF5icj/EeTaiflPSD2hvGjnguilZgE=
3+
github.com/adrg/sysfont v0.1.0 h1:vOk13USVkciGOJj9sPT9Gl9zfHUT2HZgsBnwS1Je4Q8=
4+
github.com/adrg/sysfont v0.1.0/go.mod h1:DzISco90USPZJ+lmtpuz1SOTn1fih6YyB0KG2TEP/0U=
5+
github.com/adrg/xdg v0.2.1 h1:VSVdnH7cQ7V+B33qSJHTCRlNgra1607Q8PzEmnvb2Ic=
6+
github.com/adrg/xdg v0.2.1/go.mod h1:ZuOshBmzV4Ta+s23hdfFZnBsdzmoR3US0d7ErpqSbTQ=
17
github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc=
28
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
39
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
410
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
11+
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
512
github.com/gunnsth/pkcs7 v0.0.0-20181213175627-3cffc6fbfe83 h1:saj5dTV7eQ1wFg/gVZr1SfbkOmg8CYO9R8frHgQiyR4=
613
github.com/gunnsth/pkcs7 v0.0.0-20181213175627-3cffc6fbfe83/go.mod h1:xaGEIRenAiJcGgd9p62zbiP4993KaV3PdjczwGnP50I=
714
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -10,26 +17,15 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
1017
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
1118
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
1219
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
13-
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
14-
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
1520
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
1621
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
1722
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b h1:VHyIDlv3XkfCa5/a81uzaoDkHH4rr81Z62g+xlnO8uM=
1823
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
19-
golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI=
20-
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
21-
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
2224
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
23-
golang.org/x/net v0.0.0-20190606173856-1492cefac77f/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
24-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
2525
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
2626
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
27-
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2827
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
2928
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
3029
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
3130
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
3231
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
33-
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
34-
golang.org/x/tools v0.0.0-20190606174628-0139d5756a7d h1:CoaGYJ9a8IXms8Q/NUeypLWbStIszTH0IIwqBUkEB9g=
35-
golang.org/x/tools v0.0.0-20190606174628-0139d5756a7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=

internal/cmap/cmap.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,11 @@ func (cmap *CMap) Type() int {
366366
return cmap.ctype
367367
}
368368

369+
// Nbits returns 8 bits for simple font CMaps and 16 bits for CID font CMaps.
370+
func (cmap *CMap) NBits() int {
371+
return cmap.nbits
372+
}
373+
369374
// String returns a human readable description of `cmap`.
370375
func (cmap *CMap) String() string {
371376
si := cmap.systemInfo

internal/e2etest/extract_images_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
"testing"
1717

1818
"github.com/stretchr/testify/require"
19+
"github.com/stretchr/testify/assert"
20+
1921
"github.com/unidoc/unipdf/v3/common"
2022
"github.com/unidoc/unipdf/v3/extractor"
2123
"github.com/unidoc/unipdf/v3/model"
@@ -38,20 +40,21 @@ var knownExtrImgsHashes = map[string]string{
3840
"7eee345c983461d44ae939b3f800a97642817c8d.pdf": "5a4cd00537f8a1f39fff2d4c6dd5cc53",
3941
"52ab322c1697aca9bad37288f7c502e37fa657af.pdf": "2bddee02dff89a38c08322c9d2c779a6",
4042
"0edf09fd438db2f18c1bb08fccc1f81a7b280bf2.pdf": "583f755b3fb1bd5697036616442687ab",
41-
"cafe55316a45435c3817f4c1b6a19c9cd52db825.pdf": "b199badff0abb0311a2cbe35c7fce580",
43+
"cafe55316a45435c3817f4c1b6a19c9cd52db825.pdf": "8b8c2eaa9b3a64eb5941348280c9c2a0",
4244
"6773e6aa5d8a2d26362cf3fca2874b3a81025bae.pdf": "f052e3e333839508a8bdd8d1a3ba1973",
4345
"d11a3ca55664828b69d7c39d83d5c0a63fcea89d.pdf": "29287cd44f009dce5aa9c2a0dc9a3c83",
4446
"483933bf73cc4fcc264eb69214ff763ccf299e49.pdf": "627dcf88805786d03b2e76d367b42642",
4547
"da1c5c4c4fe36f676dbca6ea01673c9fdf77c7a9.pdf": "7ffe076d1c7c88e07dfba7545b622ec6",
4648
"f856baf7ffcd96003b6bda800171cb0e5680f78e.pdf": "a9505d8c22f1fd063fbe0b05aa33a5fc",
4749
"201c20676fe8da14a8130852c91ed58b48cba8fb.pdf": "ffcb78d126c04be9ca2497bb43b6e964",
4850
"f0152456494aa09e5cf82c4afe9ecd2fdc2e8d72.pdf": "d0e68157aaa7f9f4406807512db3e676",
49-
"d95643acea1ec3f6215bda35e4cd89dbd8898c44.pdf": "1739aed3e1cbfa5e98f8d7fef17a614b",
51+
"d95643acea1ec3f6215bda35e4cd89dbd8898c44.pdf": "b4c7c2ae9671af69f71e9965e9cf67e8",
5052
"110d793aeaa7accbe40b5ab9db249d5a103d3b50.pdf": "a57e347edddfd3f6032b85553b3537cd",
5153
"d15a0aa289524619a971188372dd05fb712f1b2c.pdf": "380907273bb8ea64943d986491d827ec",
5254
"932e0dfa52c20ffe83b8178fb98296a0dab177d1.pdf": "b44d8b073f99ac3db28d7951e3c7d970",
5355
"60a8c28da5c23081834adac4170755904d8c4166.pdf": "9167f381d5eed7a2e5fd10eca567c519",
5456
"e51296be2615b9389482c9c16505286619b6cf36.pdf": "ec6e1f6297dd1cbda6ccba39e0c7d3d2",
57+
"d3dd65300785dcf2114663397e475376bac88e75.pdf": "ea848ed888176368e697f577934f0452", // From unipdf#258.
5558
}
5659

5760
func TestExtractImages(t *testing.T) {
@@ -93,7 +96,7 @@ func TestExtractImages(t *testing.T) {
9396

9497
knownHash, has := knownExtrImgsHashes[file.Name()]
9598
if has {
96-
require.Equal(t, knownHash, hash)
99+
assert.Equal(t, knownHash, hash)
97100
matchcount++
98101
} else {
99102
t.Logf("%s - hash: %s not in the list of known hashes", file.Name(), hash)

internal/textencoding/cmap.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ func NewCMapEncoder(baseName string, codeToCID, cidToUnicode *cmap.CMap) CMapEnc
3232

3333
// Encode converts the Go unicode string to a PDF encoded string.
3434
func (enc CMapEncoder) Encode(str string) []byte {
35+
if enc.cidToUnicode == nil {
36+
return []byte{}
37+
}
38+
39+
if enc.cidToUnicode.NBits() == 8 {
40+
return encodeString8bit(enc, str)
41+
}
3542
return encodeString16bit(enc, str)
3643
}
3744

internal/transform/matrix.go

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,28 @@ func IdentityMatrix() Matrix {
2121
return NewMatrix(1, 0, 0, 1, 0, 0)
2222
}
2323

24-
// TranslationMatrix returns a matrix that translates by `tx`, `ty`.
24+
// TranslationMatrix returns a matrix that translates by `tx`,`ty`.
2525
func TranslationMatrix(tx, ty float64) Matrix {
2626
return NewMatrix(1, 0, 0, 1, tx, ty)
2727
}
2828

29+
// ScaleMatrix returns a matrix that scales by `x`,`y`.
30+
func ScaleMatrix(x, y float64) Matrix {
31+
return NewMatrix(x, 0, 0, y, 0, 0)
32+
}
33+
34+
// RotationMatrix returns a matrix that rotates by angle `angle`, specified in radians.
35+
func RotationMatrix(angle float64) Matrix {
36+
c := math.Cos(angle)
37+
s := math.Sin(angle)
38+
return NewMatrix(c, s, -s, c, 0, 0)
39+
}
40+
41+
// ShearMatrix returns a matrix that shears `x`,`y`.
42+
func ShearMatrix(x, y float64) Matrix {
43+
return NewMatrix(1, y, x, 1, 0, 0)
44+
}
45+
2946
// NewMatrix returns an affine transform matrix laid out in homogenous coordinates as
3047
// a b 0
3148
// c d 0
@@ -74,19 +91,37 @@ func (m Matrix) Mult(b Matrix) Matrix {
7491
return m
7592
}
7693

77-
// Translate appends a translation of `dx`,`dy` to `m`.
94+
// Translate appends a translation of `x`,`y` to `m`.
7895
// m.Translate(dx, dy) is equivalent to m.Concat(NewMatrix(1, 0, 0, 1, dx, dy))
79-
func (m *Matrix) Translate(dx, dy float64) {
80-
m[6] += dx
81-
m[7] += dy
82-
m.clampRange()
96+
func (m *Matrix) Translate(x, y float64) {
97+
m.Concat(TranslationMatrix(x, y))
8398
}
8499

85100
// Translation returns the translation part of `m`.
86101
func (m *Matrix) Translation() (float64, float64) {
87102
return m[6], m[7]
88103
}
89104

105+
// Scale scales the current matrix by `x`,`y`.
106+
func (m *Matrix) Scale(x, y float64) {
107+
m.Concat(ScaleMatrix(x, y))
108+
}
109+
110+
// Rotate rotates the current matrix by angle `angle`, specified in radians.
111+
func (m *Matrix) Rotate(angle float64) {
112+
m.Concat(RotationMatrix(angle))
113+
}
114+
115+
// Shear shears the current matrix by `x',`y`.
116+
func (m *Matrix) Shear(x, y float64) {
117+
m.Concat(ShearMatrix(x, y))
118+
}
119+
120+
// Clone returns a copy of the current matrix.
121+
func (m *Matrix) Clone() Matrix {
122+
return NewMatrix(m[0], m[1], m[3], m[4], m[6], m[7])
123+
}
124+
90125
// Transform returns coordinates `x`,`y` transformed by `m`.
91126
func (m *Matrix) Transform(x, y float64) (float64, float64) {
92127
xp := x*m[0] + y*m[1] + m[6]

internal/transform/point.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,25 @@ func (p Point) Rotate(theta float64) Point {
4747
return Point{r * cos, r * sin}
4848
}
4949

50-
// transformByMatrix mutates and transforms `p` by the affine transformation `m`.
51-
func (p *Point) transformByMatrix(m Matrix) {
52-
p.X, p.Y = m.Transform(p.X, p.Y)
50+
// Distance returns the distance between `a` and `b`.
51+
func (a Point) Distance(b Point) float64 {
52+
return math.Hypot(a.X-b.X, a.Y-b.Y)
53+
}
54+
55+
// Interpolate does linear interpolation between point `a` and `b` for value `t`.
56+
func (a Point) Interpolate(b Point, t float64) Point {
57+
return Point{
58+
X: (1-t)*a.X + t*b.X,
59+
Y: (1-t)*a.Y + t*b.Y,
60+
}
5361
}
5462

5563
// String returns a string describing `p`.
5664
func (p Point) String() string {
5765
return fmt.Sprintf("(%.2f,%.2f)", p.X, p.Y)
5866
}
67+
68+
// transformByMatrix mutates and transforms `p` by the affine transformation `m`.
69+
func (p *Point) transformByMatrix(m Matrix) {
70+
p.X, p.Y = m.Transform(p.X, p.Y)
71+
}

model/colorspace.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,8 +2217,9 @@ func (cs *PdfColorspaceSpecialPattern) ImageToRGB(img Image) (Image, error) {
22172217
return img, errors.New("invalid colorspace for image (pattern)")
22182218
}
22192219

2220-
// PdfColorspaceSpecialIndexed is an indexed color space is a lookup table, where the input element is an index to the
2221-
// lookup table and the output is a color defined in the lookup table in the Base colorspace.
2220+
// PdfColorspaceSpecialIndexed is an indexed color space is a lookup table, where the input element
2221+
// is an index to the lookup table and the output is a color defined in the lookup table in the Base
2222+
// colorspace.
22222223
// [/Indexed base hival lookup]
22232224
type PdfColorspaceSpecialIndexed struct {
22242225
Base PdfColorspace
@@ -2232,9 +2233,7 @@ type PdfColorspaceSpecialIndexed struct {
22322233

22332234
// NewPdfColorspaceSpecialIndexed returns a new Indexed color.
22342235
func NewPdfColorspaceSpecialIndexed() *PdfColorspaceSpecialIndexed {
2235-
cs := &PdfColorspaceSpecialIndexed{}
2236-
cs.HiVal = 255
2237-
return cs
2236+
return &PdfColorspaceSpecialIndexed{HiVal: 255}
22382237
}
22392238

22402239
func (cs *PdfColorspaceSpecialIndexed) String() string {
@@ -2401,32 +2400,38 @@ func (cs *PdfColorspaceSpecialIndexed) ImageToRGB(img Image) (Image, error) {
24012400
baseImage.Height = img.Height
24022401
baseImage.Width = img.Width
24032402
baseImage.alphaData = img.alphaData
2404-
baseImage.BitsPerComponent = img.BitsPerComponent
2403+
// TODO(peterwilliams97): Add support for other BitsPerComponent values.
2404+
// See https://github.com/unidoc/unipdf/issues/260
2405+
baseImage.BitsPerComponent = 8
24052406
baseImage.hasAlpha = img.hasAlpha
2406-
baseImage.ColorComponents = img.ColorComponents
2407+
baseImage.ColorComponents = cs.Base.GetNumComponents()
24072408

24082409
samples := img.GetSamples()
24092410
N := cs.Base.GetNumComponents()
24102411

2412+
if N < 1 {
2413+
return Image{}, fmt.Errorf("bad base colorspace NumComponents=%d", N)
2414+
}
2415+
24112416
var baseSamples []uint32
24122417
// Convert the indexed data to base color map data.
24132418
for i := 0; i < len(samples); i++ {
24142419
// Each data point represents an index location.
24152420
// For each entry there are N values.
2416-
index := int(samples[i]) * N
2421+
index := int(samples[i])
24172422
common.Log.Trace("Indexed: index=%d N=%d lut=%d", index, N, len(cs.colorLookup))
24182423
// Ensure does not go out of bounds.
2419-
if index+N-1 >= len(cs.colorLookup) {
2424+
if (index+1)*N > len(cs.colorLookup) {
24202425
// Clip to the end value.
2421-
index = len(cs.colorLookup) - N - 1
2426+
index = len(cs.colorLookup)/N - 1
24222427
common.Log.Trace("Clipping to index: %d", index)
24232428
if index < 0 {
24242429
common.Log.Debug("ERROR: Can't clip index. Is PDF file damaged?")
24252430
break
24262431
}
24272432
}
24282433

2429-
cvals := cs.colorLookup[index : index+N]
2434+
cvals := cs.colorLookup[index*N : (index+1)*N]
24302435
common.Log.Trace("C Vals: % d", cvals)
24312436
for _, val := range cvals {
24322437
baseSamples = append(baseSamples, uint32(val))

0 commit comments

Comments
 (0)