2018-10-07 11:03:11 +00:00
|
|
|
/*
|
|
|
|
* This file is subject to the terms and conditions defined in
|
|
|
|
* file 'LICENSE.md', which is part of this source code package.
|
|
|
|
*/
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
package annotator
|
2018-09-18 16:52:20 +00:00
|
|
|
|
|
|
|
import (
|
2018-09-18 19:57:53 +00:00
|
|
|
"bytes"
|
2018-09-18 16:52:20 +00:00
|
|
|
"errors"
|
|
|
|
|
|
|
|
"github.com/unidoc/unidoc/pdf/contentstream"
|
|
|
|
"github.com/unidoc/unidoc/pdf/core"
|
2018-10-07 11:03:11 +00:00
|
|
|
"github.com/unidoc/unidoc/pdf/model"
|
2018-09-18 16:52:20 +00:00
|
|
|
"github.com/unidoc/unidoc/pdf/model/fonts"
|
|
|
|
)
|
|
|
|
|
|
|
|
// TextFieldOptions defines optional parameter for a text field in a form.
|
|
|
|
type TextFieldOptions struct {
|
|
|
|
MaxLen int // Ignored if <= 0.
|
|
|
|
Value string // Ignored if empty ("").
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewTextField generates a new text field with partial name `name` at location
|
|
|
|
// specified by `rect` on given `page` and with field specific options `opt`.
|
2018-09-18 19:57:53 +00:00
|
|
|
func NewTextField(page *model.PdfPage, name string, rect []float64, opt TextFieldOptions) (*model.PdfFieldText, error) {
|
2018-09-18 16:52:20 +00:00
|
|
|
if page == nil {
|
|
|
|
return nil, errors.New("Page not specified")
|
|
|
|
}
|
|
|
|
if len(name) <= 0 {
|
|
|
|
return nil, errors.New("Required attribute not specified")
|
|
|
|
}
|
|
|
|
if len(rect) != 4 {
|
|
|
|
return nil, errors.New("Invalid range")
|
|
|
|
}
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
field := model.NewPdfField()
|
|
|
|
textfield := &model.PdfFieldText{}
|
2018-09-18 16:52:20 +00:00
|
|
|
field.SetContext(textfield)
|
|
|
|
textfield.PdfField = field
|
|
|
|
|
|
|
|
textfield.T = core.MakeString(name)
|
|
|
|
|
|
|
|
if opt.MaxLen > 0 {
|
|
|
|
textfield.MaxLen = core.MakeInteger(int64(opt.MaxLen))
|
|
|
|
}
|
|
|
|
if len(opt.Value) > 0 {
|
|
|
|
textfield.V = core.MakeString(opt.Value)
|
|
|
|
}
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
widget := model.NewPdfAnnotationWidget()
|
2018-09-18 16:52:20 +00:00
|
|
|
widget.Rect = core.MakeArrayFromFloats(rect) //[]float64{144.0, 595.89, 294.0, 617.9})
|
|
|
|
widget.P = page.ToPdfObject()
|
|
|
|
widget.F = core.MakeInteger(4) // 4 (100 -> Print/show annotations).
|
|
|
|
widget.Parent = textfield.ToPdfObject()
|
|
|
|
|
|
|
|
textfield.Annotations = append(textfield.Annotations, widget)
|
|
|
|
|
|
|
|
return textfield, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CheckboxFieldOptions defines optional parameters for a checkbox field a form.
|
|
|
|
type CheckboxFieldOptions struct {
|
|
|
|
Checked bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewCheckboxField generates a new checkbox field with partial name `name` at location `rect`
|
|
|
|
// on specified `page` and with field specific options `opt`.
|
2018-09-18 19:57:53 +00:00
|
|
|
func NewCheckboxField(page *model.PdfPage, name string, rect []float64, opt CheckboxFieldOptions) (*model.PdfFieldButton, error) {
|
2018-09-18 16:52:20 +00:00
|
|
|
if page == nil {
|
|
|
|
return nil, errors.New("Page not specified")
|
|
|
|
}
|
|
|
|
if len(name) <= 0 {
|
|
|
|
return nil, errors.New("Required attribute not specified")
|
|
|
|
}
|
|
|
|
if len(rect) != 4 {
|
|
|
|
return nil, errors.New("Invalid range")
|
|
|
|
}
|
|
|
|
|
|
|
|
zapfdb := fonts.NewFontZapfDingbats()
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
field := model.NewPdfField()
|
|
|
|
buttonfield := &model.PdfFieldButton{}
|
2018-09-18 16:52:20 +00:00
|
|
|
field.SetContext(buttonfield)
|
|
|
|
buttonfield.PdfField = field
|
|
|
|
|
|
|
|
buttonfield.T = core.MakeString(name)
|
2018-09-18 19:57:53 +00:00
|
|
|
buttonfield.SetType(model.ButtonTypeCheckbox)
|
2018-09-18 16:52:20 +00:00
|
|
|
|
|
|
|
state := "Off"
|
|
|
|
if opt.Checked {
|
|
|
|
state = "Yes"
|
|
|
|
}
|
|
|
|
|
|
|
|
buttonfield.V = core.MakeName(state)
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
widget := model.NewPdfAnnotationWidget()
|
2018-09-18 16:52:20 +00:00
|
|
|
widget.Rect = core.MakeArrayFromFloats(rect)
|
|
|
|
widget.P = page.ToPdfObject()
|
|
|
|
widget.F = core.MakeInteger(4)
|
|
|
|
widget.Parent = buttonfield.ToPdfObject()
|
|
|
|
|
|
|
|
w := rect[2] - rect[0]
|
|
|
|
h := rect[3] - rect[1]
|
|
|
|
|
|
|
|
// Off state.
|
|
|
|
var cs bytes.Buffer
|
|
|
|
cs.WriteString("q\n")
|
|
|
|
cs.WriteString("0 0 1 rg\n")
|
|
|
|
cs.WriteString("BT\n")
|
|
|
|
cs.WriteString("/ZaDb 12 Tf\n")
|
|
|
|
cs.WriteString("ET\n")
|
|
|
|
cs.WriteString("Q\n")
|
|
|
|
|
|
|
|
cc := contentstream.NewContentCreator()
|
|
|
|
cc.Add_q()
|
|
|
|
cc.Add_rg(0, 0, 1)
|
|
|
|
cc.Add_BT()
|
|
|
|
cc.Add_Tf(*core.MakeName("ZaDb"), 12)
|
|
|
|
cc.Add_Td(0, 0)
|
|
|
|
cc.Add_ET()
|
|
|
|
cc.Add_Q()
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
xformOff := model.NewXObjectForm()
|
2018-09-18 16:52:20 +00:00
|
|
|
xformOff.SetContentStream(cc.Bytes(), core.NewRawEncoder())
|
|
|
|
xformOff.BBox = core.MakeArrayFromFloats([]float64{0, 0, w, h})
|
2018-09-18 19:57:53 +00:00
|
|
|
xformOff.Resources = model.NewPdfPageResources()
|
2018-09-18 16:52:20 +00:00
|
|
|
xformOff.Resources.SetFontByName("ZaDb", zapfdb.ToPdfObject())
|
|
|
|
|
|
|
|
// On state (Yes).
|
|
|
|
cc = contentstream.NewContentCreator()
|
|
|
|
cc.Add_q()
|
|
|
|
cc.Add_re(0, 0, w, h)
|
|
|
|
cc.Add_W().Add_n()
|
|
|
|
cc.Add_rg(0, 0, 1)
|
|
|
|
cc.Translate(0, 3.0)
|
|
|
|
cc.Add_BT()
|
|
|
|
cc.Add_Tf(*core.MakeName("ZaDb"), 12)
|
|
|
|
cc.Add_Td(0, 0)
|
|
|
|
cc.Add_Tj(*core.MakeString("\064"))
|
|
|
|
cc.Add_ET()
|
|
|
|
cc.Add_Q()
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
xformOn := model.NewXObjectForm()
|
2018-09-18 16:52:20 +00:00
|
|
|
xformOn.SetContentStream(cc.Bytes(), core.NewRawEncoder())
|
|
|
|
xformOn.BBox = core.MakeArrayFromFloats([]float64{0, 0, w, h})
|
2018-09-18 19:57:53 +00:00
|
|
|
xformOn.Resources = model.NewPdfPageResources()
|
2018-09-18 16:52:20 +00:00
|
|
|
xformOn.Resources.SetFontByName("ZaDb", zapfdb.ToPdfObject())
|
|
|
|
|
|
|
|
dchoiceapp := core.MakeDict()
|
|
|
|
dchoiceapp.Set("Off", xformOff.ToPdfObject())
|
|
|
|
dchoiceapp.Set("Yes", xformOn.ToPdfObject())
|
|
|
|
|
|
|
|
appearance := core.MakeDict()
|
|
|
|
appearance.Set("N", dchoiceapp)
|
|
|
|
|
|
|
|
widget.AP = appearance
|
|
|
|
widget.AS = core.MakeName(state)
|
|
|
|
|
|
|
|
buttonfield.Annotations = append(buttonfield.Annotations, widget)
|
|
|
|
|
|
|
|
return buttonfield, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ComboboxFieldOptions defines optional parameters for a combobox form field.
|
|
|
|
type ComboboxFieldOptions struct {
|
|
|
|
// Choices is the list of string values that can be selected.
|
|
|
|
Choices []string
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewComboboxField generates a new combobox form field with partial name `name` at location `rect`
|
|
|
|
// on specified `page` and with field specific options `opt`.
|
2018-09-18 19:57:53 +00:00
|
|
|
func NewComboboxField(page *model.PdfPage, name string, rect []float64, opt ComboboxFieldOptions) (*model.PdfFieldChoice, error) {
|
2018-09-18 16:52:20 +00:00
|
|
|
if page == nil {
|
|
|
|
return nil, errors.New("Page not specified")
|
|
|
|
}
|
|
|
|
if len(name) <= 0 {
|
|
|
|
return nil, errors.New("Required attribute not specified")
|
|
|
|
}
|
|
|
|
if len(rect) != 4 {
|
|
|
|
return nil, errors.New("Invalid range")
|
|
|
|
}
|
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
field := model.NewPdfField()
|
|
|
|
chfield := &model.PdfFieldChoice{}
|
2018-09-18 16:52:20 +00:00
|
|
|
field.SetContext(chfield)
|
|
|
|
chfield.PdfField = field
|
|
|
|
|
|
|
|
chfield.T = core.MakeString(name)
|
|
|
|
chfield.Opt = core.MakeArray()
|
|
|
|
for _, choicestr := range opt.Choices {
|
|
|
|
chfield.Opt.Append(core.MakeString(choicestr))
|
|
|
|
}
|
2018-09-18 19:57:53 +00:00
|
|
|
chfield.SetFlag(model.FieldFlagCombo)
|
2018-09-18 16:52:20 +00:00
|
|
|
|
2018-09-18 19:57:53 +00:00
|
|
|
widget := model.NewPdfAnnotationWidget()
|
2018-09-18 16:52:20 +00:00
|
|
|
widget.Rect = core.MakeArrayFromFloats(rect)
|
|
|
|
widget.P = page.ToPdfObject()
|
|
|
|
widget.F = core.MakeInteger(4) // TODO: Make flags for these values and a way to set.
|
|
|
|
widget.Parent = chfield.ToPdfObject()
|
|
|
|
|
|
|
|
chfield.Annotations = append(chfield.Annotations, widget)
|
|
|
|
|
|
|
|
return chfield, nil
|
|
|
|
}
|