Minor fixes, initial interface for creating new annotations.

This commit is contained in:
Gunnsteinn Hall 2017-03-24 11:31:20 +00:00
parent a40fc446bd
commit ec5ad27789
3 changed files with 224 additions and 2 deletions

View File

@ -148,7 +148,21 @@ func (csp *ContentStreamProcessor) getInitialColor(cs PdfColorspace) (PdfColor,
return NewPdfColorLab(l, a, b), nil
case *PdfColorspaceICCBased:
if cs.Alternate == nil {
return nil, errors.New("Alternate space not defined for ICC")
// Alternate not defined.
// Try to fall back to DeviceGray, DeviceRGB or DeviceCMYK.
common.Log.Trace("ICC Based not defined - attempting fall back (N = %d)", cs.N)
if cs.N == 1 {
common.Log.Trace("Falling back to DeviceGray")
return csp.getInitialColor(NewPdfColorspaceDeviceGray())
} else if cs.N == 3 {
common.Log.Trace("Falling back to DeviceRGB")
return csp.getInitialColor(NewPdfColorspaceDeviceRGB())
} else if cs.N == 4 {
common.Log.Trace("Falling back to DeviceCMYK")
return csp.getInitialColor(NewPdfColorspaceDeviceCMYK())
} else {
return nil, errors.New("Alternate space not defined for ICC")
}
}
return csp.getInitialColor(cs.Alternate)
case *PdfColorspaceSpecialIndexed:

View File

@ -67,6 +67,22 @@ func MakeArray(objects ...PdfObject) *PdfObjectArray {
return &array
}
func MakeArrayFromIntegers(vals []int) *PdfObjectArray {
array := PdfObjectArray{}
for _, val := range vals {
array = append(array, MakeInteger(int64(val)))
}
return &array
}
func MakeArrayFromFloats(vals []float64) *PdfObjectArray {
array := PdfObjectArray{}
for _, val := range vals {
array = append(array, MakeFloat(val))
}
return &array
}
func MakeFloat(val float64) *PdfObjectFloat {
num := PdfObjectFloat(val)
return &num

View File

@ -8,6 +8,7 @@ package model
import (
"fmt"
"github.com/kardianos/govendor/vendor/github.com/pkg/errors"
"github.com/unidoc/unidoc/common"
. "github.com/unidoc/unidoc/pdf/core"
)
@ -334,6 +335,22 @@ func NewPdfAnnotation() *PdfAnnotation {
return annot
}
// Create a new square annotation.
func NewPdfAnnotationSquare() *PdfAnnotationSquare {
annotation := NewPdfAnnotation()
rectAnnotation := &PdfAnnotationSquare{PdfAnnotation: annotation}
annotation.SetContext(rectAnnotation)
return rectAnnotation
}
// Create a new text annotation.
func NewPdfAnnotationText() *PdfAnnotationText {
annotation := NewPdfAnnotation()
textAnnotation := &PdfAnnotationText{PdfAnnotation: annotation}
annotation.SetContext(textAnnotation)
return textAnnotation
}
// Used for PDF parsing. Loads a PDF annotation model from a PDF primitive dictionary object.
// Loads the common PDF annotation dictionary, and anything needed for the annotation subtype.
func (r *PdfReader) newPdfAnnotationFromIndirectObject(container *PdfIndirectObject) (*PdfAnnotation, error) {
@ -1450,7 +1467,9 @@ func (this *PdfAnnotationSquare) ToPdfObject() PdfObject {
this.PdfAnnotation.ToPdfObject()
container := this.primitive
d := container.PdfObject.(*PdfObjectDictionary)
this.PdfAnnotationMarkup.appendToPdfDictionary(d)
if this.PdfAnnotationMarkup != nil {
this.PdfAnnotationMarkup.appendToPdfDictionary(d)
}
d.SetIfNotNil("Subtype", MakeName("Square"))
d.SetIfNotNil("BS", this.BS)
@ -1745,3 +1764,176 @@ func (this *PdfAnnotationRedact) ToPdfObject() PdfObject {
d.SetIfNotNil("Q", this.Q)
return container
}
// Border definitions.
type BorderStyle int
const (
BorderStyleSolid BorderStyle = iota
BorderStyleDashed BorderStyle = iota
BorderStyleBeveled BorderStyle = iota
BorderStyleInset BorderStyle = iota
BorderStyleUnderline BorderStyle = iota
)
func (this *BorderStyle) GetPdfName() string {
switch *this {
case BorderStyleSolid:
return "S"
case BorderStyleDashed:
return "D"
case BorderStyleBeveled:
return "B"
case BorderStyleInset:
return "I"
case BorderStyleUnderline:
return "U"
}
return "" // Should not happen.
}
// Border style
type PdfBorderStyle struct {
W *float64 // Border width
S *BorderStyle // Border style
D *[]int // Dash array.
container PdfObject
}
func NewBorderStyle() *PdfBorderStyle {
bs := &PdfBorderStyle{}
return bs
}
func (this *PdfBorderStyle) SetBorderWidth(width float64) {
this.W = &width
}
func (this *PdfBorderStyle) GetBorderWidth() float64 {
if this.W == nil {
return 1 // Default.
}
return *this.W
}
func newPdfBorderStyleFromPdfObject(obj PdfObject) (*PdfBorderStyle, error) {
bs := &PdfBorderStyle{}
bs.container = obj
var d *PdfObjectDictionary
obj = TraceToDirectObject(obj)
d, ok := obj.(*PdfObjectDictionary)
if !ok {
return nil, errors.New("Type check")
}
// Type.
if obj, has := (*d)["Type"]; has {
name, ok := obj.(*PdfObjectName)
if !ok {
common.Log.Debug("Incompatibility with Type not a name object: %T", obj)
} else {
if *name != "Border" {
common.Log.Debug("Warning, Type != Border: %s", *name)
}
}
}
// Border width.
if obj, has := (*d)["W"]; has {
val, err := getNumberAsFloat(obj)
if err != nil {
common.Log.Debug("Error retrieving W: %v", err)
return nil, err
}
bs.W = &val
}
// Border style.
if obj, has := (*d)["S"]; has {
name, ok := obj.(*PdfObjectName)
if !ok {
return nil, errors.New("Border S not a name object")
}
var style BorderStyle
switch *name {
case "S":
style = BorderStyleSolid
case "D":
style = BorderStyleDashed
case "B":
style = BorderStyleBeveled
case "I":
style = BorderStyleInset
case "U":
style = BorderStyleUnderline
default:
common.Log.Debug("Invalid style name %s", *name)
return nil, errors.New("Style type range check")
}
bs.S = &style
}
// Dash array.
if obj, has := (*d)["D"]; has {
vec, ok := obj.(*PdfObjectArray)
if !ok {
common.Log.Debug("Border D dash not an array: %T", obj)
return nil, errors.New("Border D type check error")
}
vals, err := vec.ToIntegerArray()
if err != nil {
common.Log.Debug("Border D Problem converting to integer array: %v", err)
return nil, err
}
bs.D = &vals
}
return bs, nil
}
func (this *PdfBorderStyle) ToPdfObject() PdfObject {
d := &PdfObjectDictionary{}
if this.container != nil {
if indObj, is := this.container.(*PdfIndirectObject); is {
indObj.PdfObject = d
}
}
d.Set("Subtype", MakeName("Border"))
if this.W != nil {
d.Set("W", MakeFloat(*this.W))
}
if this.S != nil {
d.Set("S", MakeName(this.S.GetPdfName()))
}
if this.D != nil {
d.Set("D", MakeArrayFromIntegers(*this.D))
}
if this.container != nil {
return this.container
} else {
return d
}
}
// Border effect
type BorderEffect int
const (
BorderEffectNoEffect BorderEffect = iota
BorderEffectCloudy BorderEffect = iota
)
type PdfBorderEffect struct {
S *BorderEffect // Border effect type
I *float64 // Intensity of the effect
}