Skip to content

Commit d0f9c13

Browse files
authored
Merge pull request #218 from gunnsth/release/v3.3.1
Prepare unipdf release v3.3.1
2 parents 76a1225 + 673a9d2 commit d0f9c13

File tree

20 files changed

+219
-110
lines changed

20 files changed

+219
-110
lines changed

common/version.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import (
1010
"time"
1111
)
1212

13-
const releaseYear = 2019
14-
const releaseMonth = 9
15-
const releaseDay = 7
16-
const releaseHour = 13
17-
const releaseMin = 10
13+
const releaseYear = 2020
14+
const releaseMonth = 1
15+
const releaseDay = 4
16+
const releaseHour = 19
17+
const releaseMin = 5
1818

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

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

contentstream/encoding.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func newFlateEncoderFromInlineImage(inlineImage *ContentStreamInlineImage, decod
8888
if decodeParams == nil {
8989
obj := inlineImage.DecodeParms
9090
if obj != nil {
91-
dp, isDict := obj.(*core.PdfObjectDictionary)
91+
dp, isDict := core.GetDict(obj)
9292
if !isDict {
9393
common.Log.Debug("Error: DecodeParms not a dictionary (%T)", obj)
9494
return nil, fmt.Errorf("invalid DecodeParms")
@@ -163,7 +163,7 @@ func newLZWEncoderFromInlineImage(inlineImage *ContentStreamInlineImage, decodeP
163163
// If decodeParams not provided, see if we can get from the inline image directly.
164164
if decodeParams == nil {
165165
if inlineImage.DecodeParms != nil {
166-
dp, isDict := inlineImage.DecodeParms.(*core.PdfObjectDictionary)
166+
dp, isDict := core.GetDict(inlineImage.DecodeParms)
167167
if !isDict {
168168
common.Log.Debug("Error: DecodeParms not a dictionary (%T)", inlineImage.DecodeParms)
169169
return nil, fmt.Errorf("invalid DecodeParms")

contentstream/inline-image.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ func (csp *ContentStreamParser) ParseInlineImage() (*ContentStreamInlineImage, e
316316

317317
if !isOperand {
318318
// Not an operand.. Read key value properties..
319-
param, ok := obj.(*core.PdfObjectName)
319+
param, ok := core.GetName(obj)
320320
if !ok {
321321
common.Log.Debug("Invalid inline image property (expecting name) - %T", obj)
322322
return nil, fmt.Errorf("invalid inline image property (expecting name) - %T", obj)

contentstream/processor.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package contentstream
77

88
import (
99
"errors"
10+
"fmt"
1011

1112
"github.com/unidoc/unipdf/v3/common"
1213
"github.com/unidoc/unipdf/v3/core"
@@ -141,7 +142,7 @@ func (proc *ContentStreamProcessor) getColorspace(name string, resources *model.
141142

142143
// Otherwise unsupported.
143144
common.Log.Debug("Unknown colorspace requested: %s", name)
144-
return nil, errors.New("unsupported colorspace")
145+
return nil, fmt.Errorf("unsupported colorspace: %s", name)
145146
}
146147

147148
// Get initial color for a given colorspace.

core/encoding.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ func (enc *FlateEncoder) EncodeBytes(data []byte) ([]byte, error) {
443443
rowLength := int(enc.Columns)
444444
rows := len(data) / rowLength
445445
if len(data)%rowLength != 0 {
446-
common.Log.Error("Invalid column length")
446+
common.Log.Error("Invalid row length")
447447
return nil, errors.New("invalid row length")
448448
}
449449

@@ -590,7 +590,7 @@ func newLZWEncoderFromStream(streamObj *PdfObjectStream, decodeParams *PdfObject
590590

591591
// If decodeParams not provided, see if we can get from the stream.
592592
if decodeParams == nil {
593-
obj := encDict.Get("DecodeParms")
593+
obj := TraceToDirectObject(encDict.Get("DecodeParms"))
594594
if obj != nil {
595595
if dp, isDict := obj.(*PdfObjectDictionary); isDict {
596596
decodeParams = dp
@@ -1751,7 +1751,7 @@ func newCCITTFaxEncoderFromStream(streamObj *PdfObjectStream, decodeParams *PdfO
17511751

17521752
// If decodeParams not provided, see if we can get from the stream.
17531753
if decodeParams == nil {
1754-
obj := encDict.Get("DecodeParms")
1754+
obj := TraceToDirectObject(encDict.Get("DecodeParms"))
17551755
if obj != nil {
17561756
switch t := obj.(type) {
17571757
case *PdfObjectDictionary:
@@ -2061,7 +2061,7 @@ func newJBIG2EncoderFromStream(streamObj *PdfObjectStream, decodeParams *PdfObje
20612061

20622062
if decodeParams != nil {
20632063
if globals := decodeParams.Get("JBIG2Globals"); globals != nil {
2064-
globalsStream, ok := globals.(*PdfObjectStream)
2064+
globalsStream, ok := GetStream(globals)
20652065
if !ok {
20662066
err := errors.New("the Globals stream should be an Object Stream")
20672067
common.Log.Debug("ERROR: %s", err.Error())

core/symbols.go

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,52 +22,26 @@ func IsFloatDigit(c byte) bool {
2222

2323
// IsDecimalDigit checks if the character is a part of a decimal number string.
2424
func IsDecimalDigit(c byte) bool {
25-
if c >= '0' && c <= '9' {
26-
return true
27-
}
28-
29-
return false
25+
return '0' <= c && c <= '9'
3026
}
3127

3228
// IsOctalDigit checks if a character can be part of an octal digit string.
3329
func IsOctalDigit(c byte) bool {
34-
if c >= '0' && c <= '7' {
35-
return true
36-
}
37-
38-
return false
30+
return '0' <= c && c <= '7'
3931
}
4032

4133
// IsPrintable checks if a character is printable.
4234
// Regular characters that are outside the range EXCLAMATION MARK(21h)
4335
// (!) to TILDE (7Eh) (~) should be written using the hexadecimal notation.
44-
func IsPrintable(char byte) bool {
45-
if char < 0x21 || char > 0x7E {
46-
return false
47-
}
48-
return true
36+
func IsPrintable(c byte) bool {
37+
return 0x21 <= c && c <= 0x7E
4938
}
5039

5140
// IsDelimiter checks if a character represents a delimiter.
52-
func IsDelimiter(char byte) bool {
53-
if char == '(' || char == ')' {
54-
return true
55-
}
56-
if char == '<' || char == '>' {
57-
return true
58-
}
59-
if char == '[' || char == ']' {
60-
return true
61-
}
62-
if char == '{' || char == '}' {
63-
return true
64-
}
65-
if char == '/' {
66-
return true
67-
}
68-
if char == '%' {
69-
return true
70-
}
71-
72-
return false
41+
func IsDelimiter(c byte) bool {
42+
return c == '(' || c == ')' ||
43+
c == '<' || c == '>' ||
44+
c == '[' || c == ']' ||
45+
c == '{' || c == '}' ||
46+
c == '/' || c == '%'
7347
}

creator/creator.go

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,25 @@ func (c *Creator) Context() DrawContext {
346346
return c.context
347347
}
348348

349-
// Call before writing out. Takes care of adding headers and footers, as well
350-
// as generating front Page and table of contents.
351-
func (c *Creator) finalize() error {
349+
// Finalize renders all blocks to the creator pages. In addition, it takes care
350+
// of adding headers and footers, as well as generating the front page,
351+
// table of contents and outlines.
352+
// Finalize is automatically called before writing the document out. Calling the
353+
// method manually can be useful when adding external pages to the creator,
354+
// using the AddPage method, as it renders all creator blocks to the added
355+
// pages, without having to write the document out.
356+
// NOTE: TOC and outlines are generated only if the AddTOC and AddOutlines
357+
// fields of the creator are set to true (enabled by default). Furthermore, TOCs
358+
// and outlines without content are skipped. TOC and outline content is
359+
// added automatically when using the chapter component. TOCs and outlines can
360+
// also be set externally, using the SetTOC and SetOutlineTree methods.
361+
// Finalize should only be called once, after all draw calls have taken place,
362+
// as it will return immediately if the creator instance has been finalized.
363+
func (c *Creator) Finalize() error {
364+
if c.finalized {
365+
return nil
366+
}
367+
352368
totPages := len(c.pages)
353369

354370
// Estimate number of additional generated pages and update TOC.
@@ -563,8 +579,12 @@ func (c *Creator) MoveDown(dy float64) {
563579
c.context.Y += dy
564580
}
565581

566-
// Draw draws the Drawable widget to the document. This can span over 1 or more pages. Additional
567-
// pages are added if the contents go over the current Page.
582+
// Draw processes the specified Drawable widget and generates blocks that can
583+
// be rendered to the output document. The generated blocks can span over one
584+
// or more pages. Additional pages are added if the contents go over the current
585+
// page. Each generated block is assigned to the creator page it will be
586+
// rendered to. In order to render the generated blocks to the creator pages,
587+
// call Finalize, Write or WriteToFile.
568588
func (c *Creator) Draw(d Drawable) error {
569589
if c.getActivePage() == nil {
570590
// Add a new Page if none added already.
@@ -604,10 +624,8 @@ func (c *Creator) Draw(d Drawable) error {
604624

605625
// Write output of creator to io.Writer interface.
606626
func (c *Creator) Write(ws io.Writer) error {
607-
if !c.finalized {
608-
if err := c.finalize(); err != nil {
609-
return err
610-
}
627+
if err := c.Finalize(); err != nil {
628+
return err
611629
}
612630

613631
pdfWriter := model.NewPdfWriter()

creator/creator_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ func TestSubchaptersSimple(t *testing.T) {
822822
c.AddTOC = true
823823

824824
lineStyle := c.NewTextStyle()
825-
lineStyle.Font = model.NewStandard14FontMustCompile(model.HelveticaBoldName)
825+
lineStyle.Font = model.NewStandard14FontMustCompile(model.HelveticaName)
826826

827827
toc := c.TOC()
828828
toc.SetLineStyle(lineStyle)
@@ -898,9 +898,6 @@ func TestSubchaptersSimple(t *testing.T) {
898898
toc.SetHeading("Table of Contents", style)
899899

900900
// Set style of TOC lines just before render.
901-
lineStyle := c.NewTextStyle()
902-
lineStyle.FontSize = 14
903-
904901
helveticaBold := model.NewStandard14FontMustCompile(model.HelveticaBoldName)
905902

906903
lines := toc.Lines()
@@ -923,7 +920,6 @@ func TestSubchapters(t *testing.T) {
923920

924921
lineStyle := c.NewTextStyle()
925922
lineStyle.Font = model.NewStandard14FontMustCompile(model.HelveticaName)
926-
lineStyle.FontSize = 14
927923
lineStyle.Color = ColorRGBFromArithmetic(0.5, 0.5, 0.5)
928924

929925
toc := c.TOC()

creator/toc_line.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,12 @@ func (tl *TOCLine) SetLink(page int64, x, y float64) {
155155
tl.linkY = y
156156
tl.linkPage = page
157157

158-
tl.SetStyle(tl.sp.defaultLinkStyle)
158+
// Set the color of the line components to the default link color.
159+
linkColor := tl.sp.defaultLinkStyle.Color
160+
tl.Number.Style.Color = linkColor
161+
tl.Title.Style.Color = linkColor
162+
tl.Separator.Style.Color = linkColor
163+
tl.Page.Style.Color = linkColor
159164
}
160165

161166
// getLineLink returns a new annotation if the line has a link set.

extractor/text.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ func (e *Extractor) extractPageText(contents string, resources *model.PdfPageRes
6161
pageText := &PageText{}
6262
state := newTextState()
6363
fontStack := fontStacker{}
64-
var to *textObject
64+
to := newTextObject(e, resources, contentstream.GraphicsState{}, &state, &fontStack)
65+
var inTextObj bool
6566

6667
cstreamParser := contentstream.NewContentStreamParser(contents)
6768
operations, err := cstreamParser.Parse()
@@ -102,16 +103,31 @@ func (e *Extractor) extractPageText(contents string, resources *model.PdfPageRes
102103
state.tfont = fontStack.pop()
103104
}
104105
case "BT": // Begin text
105-
// Begin a text object, initializing the text matrix, Tm, and the text line matrix,
106-
// Tlm, to the identity matrix. Text objects shall not be nested; a second BT shall
107-
// not appear before an ET.
108-
if to != nil {
106+
// Begin a text object, initializing the text matrix, Tm, and
107+
// the text line matrix, Tlm, to the identity matrix. Text
108+
// objects shall not be nested. A second BT shall not appear
109+
// before an ET. However, if that happens, all existing marks
110+
// are added to the page marks, in order to avoid losing content.
111+
if inTextObj {
109112
common.Log.Debug("BT called while in a text object")
113+
pageText.marks = append(pageText.marks, to.marks...)
110114
}
115+
inTextObj = true
111116
to = newTextObject(e, resources, gs, &state, &fontStack)
112117
case "ET": // End Text
118+
// End text object, discarding text matrix. If the current
119+
// text object contains text marks, they are added to the
120+
// page text marks collection.
121+
// The ET operator should always have a matching BT operator.
122+
// However, if ET appears outside of a text object, the behavior
123+
// does not change: the text matrices are discarded and all
124+
// existing marks in the text object are added to the page marks.
125+
if !inTextObj {
126+
common.Log.Debug("ET called outside of a text object")
127+
}
128+
inTextObj = false
113129
pageText.marks = append(pageText.marks, to.marks...)
114-
to = nil
130+
to.reset()
115131
case "T*": // Move to start of next text line
116132
to.nextLine()
117133
case "Td": // Move text location
@@ -202,10 +218,6 @@ func (e *Extractor) extractPageText(contents string, resources *model.PdfPageRes
202218
}
203219
to.setCharSpacing(y)
204220
case "Tf": // Set font.
205-
if to == nil {
206-
// This is needed for 26-Hazard-Thermal-environment.pdf
207-
to = newTextObject(e, resources, gs, &state, &fontStack)
208-
}
209221
if ok, err := to.checkOp(op, 2, true); !ok {
210222
common.Log.Debug("ERROR: Tf err=%v", err)
211223
return err
@@ -659,6 +671,14 @@ func newTextObject(e *Extractor, resources *model.PdfPageResources, gs contentst
659671
}
660672
}
661673

674+
// reset sets the text matrix `Tm` and the text line matrix `Tlm` of the text
675+
// object to the identity matrix. In addition, the marks collection is cleared.
676+
func (to *textObject) reset() {
677+
to.tm = transform.IdentityMatrix()
678+
to.tlm = transform.IdentityMatrix()
679+
to.marks = nil
680+
}
681+
662682
// renderText processes and renders byte array `data` for extraction purposes.
663683
func (to *textObject) renderText(data []byte) error {
664684
font := to.getCurrentFont()
@@ -1205,7 +1225,7 @@ func (pt *PageText) sortPosition(tol float64) {
12051225
if pt.marks[i-1].orient != pt.marks[i].orient {
12061226
cluster++
12071227
} else {
1208-
if pt.marks[i-1].orientedStart.Y - pt.marks[i].orientedStart.Y > tol {
1228+
if pt.marks[i-1].orientedStart.Y-pt.marks[i].orientedStart.Y > tol {
12091229
cluster++
12101230
}
12111231
}

0 commit comments

Comments
 (0)