Merge pull request #218 from gunnsth/release/v3.3.1

Prepare unipdf release v3.3.1
This commit is contained in:
Gunnsteinn Hall 2020-01-04 21:25:59 +00:00 committed by GitHub
commit d0f9c139ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 219 additions and 110 deletions

View File

@ -10,13 +10,13 @@ import (
"time"
)
const releaseYear = 2019
const releaseMonth = 9
const releaseDay = 7
const releaseHour = 13
const releaseMin = 10
const releaseYear = 2020
const releaseMonth = 1
const releaseDay = 4
const releaseHour = 19
const releaseMin = 5
// Version holds version information, when bumping this make sure to bump the released at stamp also.
const Version = "3.2.0"
const Version = "3.3.1"
var ReleasedAt = time.Date(releaseYear, releaseMonth, releaseDay, releaseHour, releaseMin, 0, 0, time.UTC)

View File

@ -88,7 +88,7 @@ func newFlateEncoderFromInlineImage(inlineImage *ContentStreamInlineImage, decod
if decodeParams == nil {
obj := inlineImage.DecodeParms
if obj != nil {
dp, isDict := obj.(*core.PdfObjectDictionary)
dp, isDict := core.GetDict(obj)
if !isDict {
common.Log.Debug("Error: DecodeParms not a dictionary (%T)", obj)
return nil, fmt.Errorf("invalid DecodeParms")
@ -163,7 +163,7 @@ func newLZWEncoderFromInlineImage(inlineImage *ContentStreamInlineImage, decodeP
// If decodeParams not provided, see if we can get from the inline image directly.
if decodeParams == nil {
if inlineImage.DecodeParms != nil {
dp, isDict := inlineImage.DecodeParms.(*core.PdfObjectDictionary)
dp, isDict := core.GetDict(inlineImage.DecodeParms)
if !isDict {
common.Log.Debug("Error: DecodeParms not a dictionary (%T)", inlineImage.DecodeParms)
return nil, fmt.Errorf("invalid DecodeParms")

View File

@ -316,7 +316,7 @@ func (csp *ContentStreamParser) ParseInlineImage() (*ContentStreamInlineImage, e
if !isOperand {
// Not an operand.. Read key value properties..
param, ok := obj.(*core.PdfObjectName)
param, ok := core.GetName(obj)
if !ok {
common.Log.Debug("Invalid inline image property (expecting name) - %T", obj)
return nil, fmt.Errorf("invalid inline image property (expecting name) - %T", obj)

View File

@ -7,6 +7,7 @@ package contentstream
import (
"errors"
"fmt"
"github.com/unidoc/unipdf/v3/common"
"github.com/unidoc/unipdf/v3/core"
@ -141,7 +142,7 @@ func (proc *ContentStreamProcessor) getColorspace(name string, resources *model.
// Otherwise unsupported.
common.Log.Debug("Unknown colorspace requested: %s", name)
return nil, errors.New("unsupported colorspace")
return nil, fmt.Errorf("unsupported colorspace: %s", name)
}
// Get initial color for a given colorspace.

View File

@ -443,7 +443,7 @@ func (enc *FlateEncoder) EncodeBytes(data []byte) ([]byte, error) {
rowLength := int(enc.Columns)
rows := len(data) / rowLength
if len(data)%rowLength != 0 {
common.Log.Error("Invalid column length")
common.Log.Error("Invalid row length")
return nil, errors.New("invalid row length")
}
@ -590,7 +590,7 @@ func newLZWEncoderFromStream(streamObj *PdfObjectStream, decodeParams *PdfObject
// If decodeParams not provided, see if we can get from the stream.
if decodeParams == nil {
obj := encDict.Get("DecodeParms")
obj := TraceToDirectObject(encDict.Get("DecodeParms"))
if obj != nil {
if dp, isDict := obj.(*PdfObjectDictionary); isDict {
decodeParams = dp
@ -1751,7 +1751,7 @@ func newCCITTFaxEncoderFromStream(streamObj *PdfObjectStream, decodeParams *PdfO
// If decodeParams not provided, see if we can get from the stream.
if decodeParams == nil {
obj := encDict.Get("DecodeParms")
obj := TraceToDirectObject(encDict.Get("DecodeParms"))
if obj != nil {
switch t := obj.(type) {
case *PdfObjectDictionary:
@ -2061,7 +2061,7 @@ func newJBIG2EncoderFromStream(streamObj *PdfObjectStream, decodeParams *PdfObje
if decodeParams != nil {
if globals := decodeParams.Get("JBIG2Globals"); globals != nil {
globalsStream, ok := globals.(*PdfObjectStream)
globalsStream, ok := GetStream(globals)
if !ok {
err := errors.New("the Globals stream should be an Object Stream")
common.Log.Debug("ERROR: %s", err.Error())

View File

@ -22,52 +22,26 @@ func IsFloatDigit(c byte) bool {
// IsDecimalDigit checks if the character is a part of a decimal number string.
func IsDecimalDigit(c byte) bool {
if c >= '0' && c <= '9' {
return true
}
return false
return '0' <= c && c <= '9'
}
// IsOctalDigit checks if a character can be part of an octal digit string.
func IsOctalDigit(c byte) bool {
if c >= '0' && c <= '7' {
return true
}
return false
return '0' <= c && c <= '7'
}
// IsPrintable checks if a character is printable.
// Regular characters that are outside the range EXCLAMATION MARK(21h)
// (!) to TILDE (7Eh) (~) should be written using the hexadecimal notation.
func IsPrintable(char byte) bool {
if char < 0x21 || char > 0x7E {
return false
}
return true
func IsPrintable(c byte) bool {
return 0x21 <= c && c <= 0x7E
}
// IsDelimiter checks if a character represents a delimiter.
func IsDelimiter(char byte) bool {
if char == '(' || char == ')' {
return true
}
if char == '<' || char == '>' {
return true
}
if char == '[' || char == ']' {
return true
}
if char == '{' || char == '}' {
return true
}
if char == '/' {
return true
}
if char == '%' {
return true
}
return false
func IsDelimiter(c byte) bool {
return c == '(' || c == ')' ||
c == '<' || c == '>' ||
c == '[' || c == ']' ||
c == '{' || c == '}' ||
c == '/' || c == '%'
}

View File

@ -346,9 +346,25 @@ func (c *Creator) Context() DrawContext {
return c.context
}
// Call before writing out. Takes care of adding headers and footers, as well
// as generating front Page and table of contents.
func (c *Creator) finalize() error {
// Finalize renders all blocks to the creator pages. In addition, it takes care
// of adding headers and footers, as well as generating the front page,
// table of contents and outlines.
// Finalize is automatically called before writing the document out. Calling the
// method manually can be useful when adding external pages to the creator,
// using the AddPage method, as it renders all creator blocks to the added
// pages, without having to write the document out.
// NOTE: TOC and outlines are generated only if the AddTOC and AddOutlines
// fields of the creator are set to true (enabled by default). Furthermore, TOCs
// and outlines without content are skipped. TOC and outline content is
// added automatically when using the chapter component. TOCs and outlines can
// also be set externally, using the SetTOC and SetOutlineTree methods.
// Finalize should only be called once, after all draw calls have taken place,
// as it will return immediately if the creator instance has been finalized.
func (c *Creator) Finalize() error {
if c.finalized {
return nil
}
totPages := len(c.pages)
// Estimate number of additional generated pages and update TOC.
@ -563,8 +579,12 @@ func (c *Creator) MoveDown(dy float64) {
c.context.Y += dy
}
// Draw draws the Drawable widget to the document. This can span over 1 or more pages. Additional
// pages are added if the contents go over the current Page.
// Draw processes the specified Drawable widget and generates blocks that can
// be rendered to the output document. The generated blocks can span over one
// or more pages. Additional pages are added if the contents go over the current
// page. Each generated block is assigned to the creator page it will be
// rendered to. In order to render the generated blocks to the creator pages,
// call Finalize, Write or WriteToFile.
func (c *Creator) Draw(d Drawable) error {
if c.getActivePage() == nil {
// Add a new Page if none added already.
@ -604,10 +624,8 @@ func (c *Creator) Draw(d Drawable) error {
// Write output of creator to io.Writer interface.
func (c *Creator) Write(ws io.Writer) error {
if !c.finalized {
if err := c.finalize(); err != nil {
return err
}
if err := c.Finalize(); err != nil {
return err
}
pdfWriter := model.NewPdfWriter()

View File

@ -822,7 +822,7 @@ func TestSubchaptersSimple(t *testing.T) {
c.AddTOC = true
lineStyle := c.NewTextStyle()
lineStyle.Font = model.NewStandard14FontMustCompile(model.HelveticaBoldName)
lineStyle.Font = model.NewStandard14FontMustCompile(model.HelveticaName)
toc := c.TOC()
toc.SetLineStyle(lineStyle)
@ -898,9 +898,6 @@ func TestSubchaptersSimple(t *testing.T) {
toc.SetHeading("Table of Contents", style)
// Set style of TOC lines just before render.
lineStyle := c.NewTextStyle()
lineStyle.FontSize = 14
helveticaBold := model.NewStandard14FontMustCompile(model.HelveticaBoldName)
lines := toc.Lines()
@ -923,7 +920,6 @@ func TestSubchapters(t *testing.T) {
lineStyle := c.NewTextStyle()
lineStyle.Font = model.NewStandard14FontMustCompile(model.HelveticaName)
lineStyle.FontSize = 14
lineStyle.Color = ColorRGBFromArithmetic(0.5, 0.5, 0.5)
toc := c.TOC()

View File

@ -155,7 +155,12 @@ func (tl *TOCLine) SetLink(page int64, x, y float64) {
tl.linkY = y
tl.linkPage = page
tl.SetStyle(tl.sp.defaultLinkStyle)
// Set the color of the line components to the default link color.
linkColor := tl.sp.defaultLinkStyle.Color
tl.Number.Style.Color = linkColor
tl.Title.Style.Color = linkColor
tl.Separator.Style.Color = linkColor
tl.Page.Style.Color = linkColor
}
// getLineLink returns a new annotation if the line has a link set.

View File

@ -61,7 +61,8 @@ func (e *Extractor) extractPageText(contents string, resources *model.PdfPageRes
pageText := &PageText{}
state := newTextState()
fontStack := fontStacker{}
var to *textObject
to := newTextObject(e, resources, contentstream.GraphicsState{}, &state, &fontStack)
var inTextObj bool
cstreamParser := contentstream.NewContentStreamParser(contents)
operations, err := cstreamParser.Parse()
@ -102,16 +103,31 @@ func (e *Extractor) extractPageText(contents string, resources *model.PdfPageRes
state.tfont = fontStack.pop()
}
case "BT": // Begin text
// Begin a text object, initializing the text matrix, Tm, and the text line matrix,
// Tlm, to the identity matrix. Text objects shall not be nested; a second BT shall
// not appear before an ET.
if to != nil {
// Begin a text object, initializing the text matrix, Tm, and
// the text line matrix, Tlm, to the identity matrix. Text
// objects shall not be nested. A second BT shall not appear
// before an ET. However, if that happens, all existing marks
// are added to the page marks, in order to avoid losing content.
if inTextObj {
common.Log.Debug("BT called while in a text object")
pageText.marks = append(pageText.marks, to.marks...)
}
inTextObj = true
to = newTextObject(e, resources, gs, &state, &fontStack)
case "ET": // End Text
// End text object, discarding text matrix. If the current
// text object contains text marks, they are added to the
// page text marks collection.
// The ET operator should always have a matching BT operator.
// However, if ET appears outside of a text object, the behavior
// does not change: the text matrices are discarded and all
// existing marks in the text object are added to the page marks.
if !inTextObj {
common.Log.Debug("ET called outside of a text object")
}
inTextObj = false
pageText.marks = append(pageText.marks, to.marks...)
to = nil
to.reset()
case "T*": // Move to start of next text line
to.nextLine()
case "Td": // Move text location
@ -202,10 +218,6 @@ func (e *Extractor) extractPageText(contents string, resources *model.PdfPageRes
}
to.setCharSpacing(y)
case "Tf": // Set font.
if to == nil {
// This is needed for 26-Hazard-Thermal-environment.pdf
to = newTextObject(e, resources, gs, &state, &fontStack)
}
if ok, err := to.checkOp(op, 2, true); !ok {
common.Log.Debug("ERROR: Tf err=%v", err)
return err
@ -659,6 +671,14 @@ func newTextObject(e *Extractor, resources *model.PdfPageResources, gs contentst
}
}
// reset sets the text matrix `Tm` and the text line matrix `Tlm` of the text
// object to the identity matrix. In addition, the marks collection is cleared.
func (to *textObject) reset() {
to.tm = transform.IdentityMatrix()
to.tlm = transform.IdentityMatrix()
to.marks = nil
}
// renderText processes and renders byte array `data` for extraction purposes.
func (to *textObject) renderText(data []byte) error {
font := to.getCurrentFont()
@ -1205,7 +1225,7 @@ func (pt *PageText) sortPosition(tol float64) {
if pt.marks[i-1].orient != pt.marks[i].orient {
cluster++
} else {
if pt.marks[i-1].orientedStart.Y - pt.marks[i].orientedStart.Y > tol {
if pt.marks[i-1].orientedStart.Y-pt.marks[i].orientedStart.Y > tol {
cluster++
}
}

View File

@ -0,0 +1,57 @@
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.md', which is part of this source code package.
*/
package textencoding
import (
"github.com/unidoc/unipdf/v3/core"
"github.com/unidoc/unipdf/v3/internal/strutils"
)
// UTF16Encoder represents UTF-16 encoding.
type UTF16Encoder struct {
baseName string
}
// NewUTF16TextEncoder returns a new UTF16Encoder based on the predefined
// encoding `baseName`.
func NewUTF16TextEncoder(baseName string) UTF16Encoder {
return UTF16Encoder{baseName}
}
// String returns a string that describes `enc`.
func (enc UTF16Encoder) String() string {
return enc.baseName
}
// Encode converts the Go unicode string to a PDF encoded string.
func (enc UTF16Encoder) Encode(str string) []byte {
return []byte(strutils.StringToUTF16(str))
}
// Decode converts PDF encoded string to a Go unicode string.
func (enc UTF16Encoder) Decode(raw []byte) string {
return strutils.UTF16ToString(raw)
}
// RuneToCharcode converts rune `r` to a PDF character code.
// The bool return flag is true if there was a match, and false otherwise.
func (enc UTF16Encoder) RuneToCharcode(r rune) (CharCode, bool) {
return CharCode(r), true
}
// CharcodeToRune converts PDF character code `code` to a rune.
// The bool return flag is true if there was a match, and false otherwise.
func (enc UTF16Encoder) CharcodeToRune(code CharCode) (rune, bool) {
return rune(code), true
}
// ToPdfObject returns a PDF Object that represents the encoding.
func (enc UTF16Encoder) ToPdfObject() core.PdfObject {
if enc.baseName != "" {
return core.MakeName(enc.baseName)
}
return core.MakeNull()
}

View File

@ -194,9 +194,23 @@ func newPdfFontType0FromPdfObject(d *core.PdfObjectDictionary, base *fontCommon)
encoderName, ok := core.GetNameVal(d.Get("Encoding"))
if ok {
if encoderName == "Identity-H" || encoderName == "Identity-V" {
switch encoderName {
case "Identity-H", "Identity-V":
font.encoder = textencoding.NewIdentityTextEncoder(encoderName)
} else {
case
// Reference: https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5094.CJK_CID.pdf
// Adobe-GB1-4, Adobe-GB1-5
"UniGB-UTF16-H", "UniGB-UTF16-V",
// Adobe-CNS1-4, Adobe-CNS1-5
"UniCNS-UTF16-H", "UniCNS-UTF16-V",
// Adobe-Japan1-4, Adobe-Japan1-5, Adobe-Japan1-6
"UniJIS-UTF16-H", "UniJIS-UTF16-V", "UniJIS2004-UTF16-H",
// Adobe-Japan2-0
"UniHojo-UTF16-H", "UniHojo-UTF16-V",
// Adobe-Korea1-2
"UniKS-UTF16-H", "UniKS-UTF16-V":
font.encoder = textencoding.NewUTF16TextEncoder(encoderName)
default:
common.Log.Debug("Unhandled cmap %q", encoderName)
}
}

View File

@ -6,8 +6,11 @@
package model
import (
"bytes"
"errors"
"io"
"io/ioutil"
"os"
"strings"
"github.com/unidoc/unipdf/v3/common"
@ -379,16 +382,35 @@ func (font *pdfFontSimple) ToPdfObject() core.PdfObject {
return font.container
}
// NewPdfFontFromTTFFile loads a TTF font and returns a PdfFont type that can be used in text
// styling functions.
// NewPdfFontFromTTFFile loads a TTF font file and returns a PdfFont type
// that can be used in text styling functions.
// Uses a WinAnsiTextEncoder and loads only character codes 32-255.
func NewPdfFontFromTTFFile(filePath string) (*PdfFont, error) {
f, err := os.Open(filePath)
if err != nil {
common.Log.Debug("ERROR: reading TTF font file: %v", err)
return nil, err
}
defer f.Close()
return NewPdfFontFromTTF(f)
}
// NewPdfFontFromTTF loads a TTF font and returns a PdfFont type that can be
// used in text styling functions.
// Uses a WinAnsiTextEncoder and loads only character codes 32-255.
func NewPdfFontFromTTF(r io.ReadSeeker) (*PdfFont, error) {
const minCode = textencoding.CharCode(32)
const maxCode = textencoding.CharCode(255)
ttf, err := fonts.TtfParseFile(filePath)
ttfBytes, err := ioutil.ReadAll(r)
if err != nil {
common.Log.Debug("ERROR: loading ttf font: %v", err)
common.Log.Debug("ERROR: Unable to read font contents: %v", err)
return nil, err
}
ttf, err := fonts.TtfParse(bytes.NewReader(ttfBytes))
if err != nil {
common.Log.Debug("ERROR: loading TTF font: %v", err)
return nil, err
}
@ -457,12 +479,6 @@ func NewPdfFontFromTTFFile(filePath string) (*PdfFont, error) {
descriptor.ItalicAngle = core.MakeFloat(float64(ttf.ItalicAngle))
descriptor.MissingWidth = core.MakeFloat(k * float64(ttf.Widths[0]))
ttfBytes, err := ioutil.ReadFile(filePath)
if err != nil {
common.Log.Debug("ERROR: Unable to read file contents: %v", err)
return nil, err
}
stream, err := core.MakeStream(ttfBytes, core.NewFlateEncoder())
if err != nil {
common.Log.Debug("ERROR: Unable to make stream: %v", err)

View File

@ -864,3 +864,10 @@ func newStandandTextEncoder(t *testing.T) textencoding.SimpleEncoder {
}
return enc
}
func TestNewFontFromFile(t *testing.T) {
_, err := model.NewPdfFontFromTTFFile("testdata/font/OpenSans-Regular.ttf")
if err != nil {
t.Fatalf("Failed to load font from file. err=%v", err)
}
}

View File

@ -905,7 +905,7 @@ func newPdfPageResourcesColorspacesFromPdfObject(obj core.PdfObject) (*PdfPageRe
obj = indObj.PdfObject
}
dict, ok := obj.(*core.PdfObjectDictionary)
dict, ok := core.GetDict(obj)
if !ok {
return nil, errors.New("CS attribute type error")
}

View File

@ -162,7 +162,7 @@ func newPdfPatternFromPdfObject(container core.PdfObject) (*PdfPattern, error) {
pattern := &PdfPattern{}
var dict *core.PdfObjectDictionary
if indObj, is := container.(*core.PdfIndirectObject); is {
if indObj, is := core.GetIndirect(container); is {
pattern.container = indObj
d, ok := indObj.PdfObject.(*core.PdfObjectDictionary)
if !ok {
@ -170,11 +170,11 @@ func newPdfPatternFromPdfObject(container core.PdfObject) (*PdfPattern, error) {
return nil, core.ErrTypeError
}
dict = d
} else if streamObj, is := container.(*core.PdfObjectStream); is {
} else if streamObj, is := core.GetStream(container); is {
pattern.container = streamObj
dict = streamObj.PdfObjectDictionary
} else {
common.Log.Debug("Pattern not an indirect object or stream")
common.Log.Debug("Pattern not an indirect object or stream. %T", container)
return nil, core.ErrTypeError
}

View File

@ -298,7 +298,7 @@ func (r *PdfReader) loadOutlines() (*PdfOutlineTreeNode, error) {
common.Log.Trace("Outline root dict: %v", dict)
outlineTree, _, err := r.buildOutlineTree(outlineRoot, nil, nil)
outlineTree, _, err := r.buildOutlineTree(outlineRoot, nil, nil, nil)
if err != nil {
return nil, err
}
@ -313,7 +313,12 @@ func (r *PdfReader) loadOutlines() (*PdfOutlineTreeNode, error) {
// Parent, Prev are the parent or previous node in the hierarchy.
// The function returns the corresponding tree node and the last node which is used
// for setting the Last pointer of the tree node structures.
func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeNode, prev *PdfOutlineTreeNode) (*PdfOutlineTreeNode, *PdfOutlineTreeNode, error) {
func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeNode, prev *PdfOutlineTreeNode, visited map[core.PdfObject]struct{}) (*PdfOutlineTreeNode, *PdfOutlineTreeNode, error) {
if visited == nil {
visited = map[core.PdfObject]struct{}{}
}
visited[obj] = struct{}{}
container, isInd := obj.(*core.PdfIndirectObject)
if !isInd {
return nil, nil, fmt.Errorf("outline container not an indirect object %T", obj)
@ -336,7 +341,7 @@ func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeN
if firstObj := dict.Get("First"); firstObj != nil {
firstObj = core.ResolveReference(firstObj)
if !core.IsNullObject(firstObj) {
first, last, err := r.buildOutlineTree(firstObj, &outlineItem.PdfOutlineTreeNode, nil)
first, last, err := r.buildOutlineTree(firstObj, &outlineItem.PdfOutlineTreeNode, nil, visited)
if err != nil {
common.Log.Debug("DEBUG: could not build outline item tree: %v. Skipping node children.", err)
} else {
@ -348,9 +353,9 @@ func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeN
// Resolve the reference to next
nextObj := core.ResolveReference(dict.Get("Next"))
if nextObj != nil && nextObj != container {
if _, processed := visited[nextObj]; nextObj != nil && nextObj != container && !processed {
if _, isNull := nextObj.(*core.PdfObjectNull); !isNull {
next, last, err := r.buildOutlineTree(nextObj, parent, &outlineItem.PdfOutlineTreeNode)
next, last, err := r.buildOutlineTree(nextObj, parent, &outlineItem.PdfOutlineTreeNode, visited)
if err != nil {
common.Log.Debug("DEBUG: could not build outline tree for Next node: %v. Skipping node.", err)
} else {
@ -375,7 +380,7 @@ func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeN
firstObj = core.ResolveReference(firstObj)
firstObjDirect := core.TraceToDirectObject(firstObj)
if _, isNull := firstObjDirect.(*core.PdfObjectNull); !isNull && firstObjDirect != nil {
first, last, err := r.buildOutlineTree(firstObj, &outline.PdfOutlineTreeNode, nil)
first, last, err := r.buildOutlineTree(firstObj, &outline.PdfOutlineTreeNode, nil, visited)
if err != nil {
common.Log.Debug("DEBUG: could not build outline tree: %v. Skipping node children.", err)
} else {

View File

@ -335,11 +335,7 @@ func (r *PdfPageResources) SetColorspaceByName(keyName core.PdfObjectName, cs Pd
// HasXObjectByName checks if an XObject with a specified keyName is defined.
func (r *PdfPageResources) HasXObjectByName(keyName core.PdfObjectName) bool {
obj, _ := r.GetXObjectByName(keyName)
if obj != nil {
return true
}
return false
return obj != nil
}
// GenerateXObjectName generates an unused XObject name that can be used for
@ -362,10 +358,10 @@ type XObjectType int
// XObject types.
const (
XObjectTypeUndefined XObjectType = iota
XObjectTypeImage XObjectType = iota
XObjectTypeForm XObjectType = iota
XObjectTypePS XObjectType = iota
XObjectTypeUnknown XObjectType = iota
XObjectTypeImage
XObjectTypeForm
XObjectTypePS
XObjectTypeUnknown
)
// GetXObjectByName returns the XObject with the specified keyName and the object type.

View File

@ -141,7 +141,7 @@ func newPdfShadingFromPdfObject(obj core.PdfObject) (*PdfShading, error) {
shading := &PdfShading{}
var dict *core.PdfObjectDictionary
if indObj, isInd := obj.(*core.PdfIndirectObject); isInd {
if indObj, isInd := core.GetIndirect(obj); isInd {
shading.container = indObj
d, ok := indObj.PdfObject.(*core.PdfObjectDictionary)
@ -151,10 +151,10 @@ func newPdfShadingFromPdfObject(obj core.PdfObject) (*PdfShading, error) {
}
dict = d
} else if streamObj, isStream := obj.(*core.PdfObjectStream); isStream {
} else if streamObj, isStream := core.GetStream(obj); isStream {
shading.container = streamObj
dict = streamObj.PdfObjectDictionary
} else if d, isDict := obj.(*core.PdfObjectDictionary); isDict {
} else if d, isDict := core.GetDict(obj); isDict {
shading.container = d
dict = d
} else {

BIN
model/testdata/font/OpenSans-Regular.ttf vendored Normal file

Binary file not shown.