2018-07-24 21:32:02 +10:00
|
|
|
|
/*
|
|
|
|
|
* This file is subject to the terms and conditions defined in
|
|
|
|
|
* file 'LICENSE.md', which is part of this source code package.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-09-01 13:20:51 +00:00
|
|
|
|
package model
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"io/ioutil"
|
2018-11-22 22:01:04 +11:00
|
|
|
|
"strings"
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
"github.com/unidoc/unidoc/common"
|
2018-07-15 16:28:56 +10:00
|
|
|
|
"github.com/unidoc/unidoc/pdf/core"
|
2018-11-01 21:33:51 +11:00
|
|
|
|
"github.com/unidoc/unidoc/pdf/internal/textencoding"
|
2017-09-01 13:20:51 +00:00
|
|
|
|
"github.com/unidoc/unidoc/pdf/model/fonts"
|
|
|
|
|
)
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// pdfFontSimple describes a Simple Font
|
|
|
|
|
//
|
|
|
|
|
// 9.6 Simple Fonts (page 254)
|
|
|
|
|
// 9.6.1 General
|
|
|
|
|
// There are several types of simple fonts, all of which have these properties:
|
|
|
|
|
// • Glyphs in the font shall be selected by single-byte character codes obtained from a string that
|
|
|
|
|
// is shown by the text-showing operators. Logically, these codes index into a table of 256 glyphs;
|
|
|
|
|
// the mapping from codes to glyphs is called the font’s encoding. Under some circumstances, the
|
|
|
|
|
// encoding may be altered by means described in 9.6.6, "Character Encoding".
|
|
|
|
|
// • Each glyph shall have a single set of metrics, including a horizontal displacement or width,
|
|
|
|
|
// as described in 9.2.4, "Glyph Positioning and Metrics"; that is, simple fonts support only
|
|
|
|
|
// horizontal writing mode.
|
|
|
|
|
// • Except for Type 0 fonts, Type 3 fonts in non-Tagged PDF documents, and certain standard Type 1
|
|
|
|
|
// fonts, every font dictionary shall contain a subsidiary dictionary, the font descriptor,
|
|
|
|
|
// containing font-wide metrics and other attributes of the font.
|
|
|
|
|
// Among those attributes is an optional font filestream containing the font program.
|
|
|
|
|
type pdfFontSimple struct {
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon
|
2018-07-25 16:14:19 +10:00
|
|
|
|
container *core.PdfIndirectObject
|
2018-07-16 17:42:08 +10:00
|
|
|
|
|
|
|
|
|
// These fields are specific to simple PDF fonts.
|
2018-11-18 17:21:30 +11:00
|
|
|
|
|
|
|
|
|
charWidths map[uint16]float64
|
2018-10-16 14:50:43 +11:00
|
|
|
|
// std14Encoder is the encoder specified by the /Encoding entry in the font dict.
|
2018-11-18 17:21:30 +11:00
|
|
|
|
encoder *textencoding.SimpleEncoder
|
2018-10-16 14:50:43 +11:00
|
|
|
|
// std14Encoder is used for Standard 14 fonts where no /Encoding is specified in the font dict.
|
2018-11-18 17:21:30 +11:00
|
|
|
|
std14Encoder *textencoding.SimpleEncoder
|
2018-06-27 12:25:59 +10:00
|
|
|
|
|
2018-10-18 21:12:15 +11:00
|
|
|
|
// std14Descriptor is used for Standard 14 fonts where no /FontDescriptor is specified in the font dict.
|
|
|
|
|
std14Descriptor *PdfFontDescriptor
|
2018-06-27 12:25:59 +10:00
|
|
|
|
|
|
|
|
|
// Encoding is subject to limitations that are described in 9.6.6, "Character Encoding".
|
|
|
|
|
// BaseFont is derived differently.
|
2018-07-15 16:28:56 +10:00
|
|
|
|
FirstChar core.PdfObject
|
|
|
|
|
LastChar core.PdfObject
|
|
|
|
|
Widths core.PdfObject
|
|
|
|
|
Encoding core.PdfObject
|
2018-07-16 17:42:08 +10:00
|
|
|
|
|
|
|
|
|
// Standard 14 fonts metrics
|
|
|
|
|
fontMetrics map[string]fonts.CharMetrics
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pdfCIDFontType0FromSkeleton returns a pdfFontSimple with its common fields initalized.
|
|
|
|
|
func pdfFontSimpleFromSkeleton(base *fontCommon) *pdfFontSimple {
|
|
|
|
|
return &pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: *base,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// baseFields returns the fields of `font` that are common to all PDF fonts.
|
|
|
|
|
func (font *pdfFontSimple) baseFields() *fontCommon {
|
2018-07-23 14:55:23 +10:00
|
|
|
|
return &font.fontCommon
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Encoder returns the font's text encoder.
|
2018-06-27 12:25:59 +10:00
|
|
|
|
func (font *pdfFontSimple) Encoder() textencoding.TextEncoder {
|
2018-12-07 10:32:49 +00:00
|
|
|
|
// TODO(peterwilliams97): Need to make font.Encoder()==nil test work for
|
2018-12-02 09:14:58 +11:00
|
|
|
|
// font.std14=Encoder=font.encoder=nil See https://golang.org/doc/faq#nil_error
|
|
|
|
|
if font.encoder != nil {
|
|
|
|
|
return font.encoder
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-16 14:50:43 +11:00
|
|
|
|
// Standard 14 fonts have builtin encoders that we fall back to when no /Encoding is specified
|
|
|
|
|
// in the font dict.
|
2018-12-02 09:14:58 +11:00
|
|
|
|
if font.std14Encoder != nil {
|
2018-10-16 14:50:43 +11:00
|
|
|
|
return font.std14Encoder
|
|
|
|
|
}
|
2018-12-02 09:14:58 +11:00
|
|
|
|
|
|
|
|
|
// Default to StandardEncoding
|
|
|
|
|
enc, _ := textencoding.NewSimpleTextEncoder("StandardEncoding", nil)
|
|
|
|
|
return enc
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// SetEncoder sets the encoding for the underlying font.
|
2018-12-07 10:32:49 +00:00
|
|
|
|
// TODO(peterwilliams97): Change function signature to SetEncoder(encoder *textencoding.SimpleEncoder).
|
|
|
|
|
// TODO(gunnsth): Makes sense if SetEncoder is removed from the interface fonts.Font as proposed in PR #260.
|
2018-06-27 12:25:59 +10:00
|
|
|
|
func (font *pdfFontSimple) SetEncoder(encoder textencoding.TextEncoder) {
|
2018-11-18 17:21:30 +11:00
|
|
|
|
simple, ok := encoder.(*textencoding.SimpleEncoder)
|
|
|
|
|
if !ok {
|
|
|
|
|
// This can't happen.
|
2018-12-02 09:14:58 +11:00
|
|
|
|
common.Log.Error("pdfFontSimple.SetEncoder passed bad encoder type %T", encoder)
|
2018-11-18 17:21:30 +11:00
|
|
|
|
simple = nil
|
|
|
|
|
}
|
|
|
|
|
font.encoder = simple
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// GetGlyphCharMetrics returns the character metrics for the specified glyph. A bool flag is
|
|
|
|
|
// returned to indicate whether or not the entry was found in the glyph to charcode mapping.
|
|
|
|
|
func (font pdfFontSimple) GetGlyphCharMetrics(glyph string) (fonts.CharMetrics, bool) {
|
2018-07-16 17:42:08 +10:00
|
|
|
|
if font.fontMetrics != nil {
|
2018-11-30 16:53:48 +00:00
|
|
|
|
metrics, has := font.fontMetrics[glyph]
|
|
|
|
|
if has {
|
|
|
|
|
return metrics, true
|
|
|
|
|
}
|
2018-07-16 17:42:08 +10:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-01 21:33:51 +11:00
|
|
|
|
metrics := fonts.CharMetrics{GlyphName: glyph}
|
|
|
|
|
|
|
|
|
|
encoder := font.Encoder()
|
|
|
|
|
|
|
|
|
|
if encoder == nil {
|
|
|
|
|
common.Log.Debug("No encoder for fonts=%s", font)
|
|
|
|
|
return metrics, false
|
|
|
|
|
}
|
|
|
|
|
code, found := encoder.GlyphToCharcode(glyph)
|
|
|
|
|
|
2017-09-01 13:20:51 +00:00
|
|
|
|
if !found {
|
2018-11-08 15:20:12 +11:00
|
|
|
|
if glyph != "space" {
|
2018-12-02 13:09:32 +11:00
|
|
|
|
common.Log.Trace("No charcode for glyph=%q font=%s", glyph, font)
|
2018-11-08 15:20:12 +11:00
|
|
|
|
}
|
2018-10-30 21:55:30 +11:00
|
|
|
|
return fonts.CharMetrics{GlyphName: glyph}, false
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-11-01 21:33:51 +11:00
|
|
|
|
|
2018-10-30 21:55:30 +11:00
|
|
|
|
metrics, ok := font.GetCharMetrics(code)
|
2018-06-27 12:25:59 +10:00
|
|
|
|
metrics.GlyphName = glyph
|
2018-10-30 21:55:30 +11:00
|
|
|
|
return metrics, ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCharMetrics returns the character metrics for the specified character code. A bool flag is
|
|
|
|
|
// returned to indicate whether or not the entry was found in the glyph to charcode mapping.
|
2018-12-02 09:14:58 +11:00
|
|
|
|
// How it works:
|
|
|
|
|
// 1) Return a value the /Widths array (charWidths) if there is one.
|
|
|
|
|
// 2) If the font has the same name as a standard 14 font then return width=250.
|
|
|
|
|
// 3) Otherwise return no match and let the caller substitute a default.
|
2018-10-30 21:55:30 +11:00
|
|
|
|
func (font pdfFontSimple) GetCharMetrics(code uint16) (fonts.CharMetrics, bool) {
|
2018-11-18 17:21:30 +11:00
|
|
|
|
if width, ok := font.charWidths[code]; ok {
|
|
|
|
|
return fonts.CharMetrics{Wx: width}, true
|
|
|
|
|
}
|
2018-11-23 11:21:51 +11:00
|
|
|
|
if isBuiltin(Standard14Font(font.basefont)) {
|
|
|
|
|
// PdfBox says this is what Acrobat does. Their reference is PDFBOX-2334.
|
|
|
|
|
return fonts.CharMetrics{Wx: 250}, true
|
|
|
|
|
}
|
2018-11-18 17:21:30 +11:00
|
|
|
|
return fonts.CharMetrics{}, false
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// newSimpleFontFromPdfObject creates a pdfFontSimple from dictionary `d`. Elements of `d` that
|
2018-07-16 17:42:08 +10:00
|
|
|
|
// are already parsed are contained in `base`.
|
2018-10-16 14:50:43 +11:00
|
|
|
|
// Standard 14 fonts need to to specify their builtin encoders in the `std14Encoder` parameter.
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// An error is returned if there is a problem with loading.
|
|
|
|
|
//
|
|
|
|
|
// The value of Encoding is subject to limitations that are described in 9.6.6, "Character Encoding".
|
|
|
|
|
// • The value of BaseFont is derived differently.
|
|
|
|
|
//
|
2018-10-16 14:50:43 +11:00
|
|
|
|
func newSimpleFontFromPdfObject(d *core.PdfObjectDictionary, base *fontCommon,
|
2018-11-18 17:21:30 +11:00
|
|
|
|
std14Encoder *textencoding.SimpleEncoder) (*pdfFontSimple, error) {
|
2018-07-16 17:42:08 +10:00
|
|
|
|
font := pdfFontSimpleFromSkeleton(base)
|
2018-10-16 14:50:43 +11:00
|
|
|
|
font.std14Encoder = std14Encoder
|
2018-06-27 12:25:59 +10:00
|
|
|
|
|
2018-07-16 17:42:08 +10:00
|
|
|
|
// FirstChar is not defined in ~/testdata/shamirturing.pdf
|
2018-10-16 14:50:43 +11:00
|
|
|
|
if std14Encoder == nil {
|
2018-07-11 09:04:17 +10:00
|
|
|
|
obj := d.Get("FirstChar")
|
2018-07-06 16:41:13 +10:00
|
|
|
|
if obj == nil {
|
2018-07-25 16:14:19 +10:00
|
|
|
|
obj = core.MakeInteger(0)
|
2018-06-27 12:25:59 +10:00
|
|
|
|
}
|
2018-07-06 16:41:13 +10:00
|
|
|
|
font.FirstChar = obj
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-07-24 21:32:02 +10:00
|
|
|
|
intVal, ok := core.GetIntVal(obj)
|
2018-07-06 16:41:13 +10:00
|
|
|
|
if !ok {
|
|
|
|
|
common.Log.Debug("ERROR: Invalid FirstChar type (%T)", obj)
|
2018-07-15 16:28:56 +10:00
|
|
|
|
return nil, core.ErrTypeError
|
2018-07-06 16:41:13 +10:00
|
|
|
|
}
|
2018-11-18 17:21:30 +11:00
|
|
|
|
firstChar := int(intVal)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-07-06 16:41:13 +10:00
|
|
|
|
obj = d.Get("LastChar")
|
|
|
|
|
if obj == nil {
|
2018-07-24 21:32:02 +10:00
|
|
|
|
obj = core.MakeInteger(255)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-07-06 16:41:13 +10:00
|
|
|
|
font.LastChar = obj
|
2018-07-24 21:32:02 +10:00
|
|
|
|
intVal, ok = core.GetIntVal(obj)
|
2018-07-06 16:41:13 +10:00
|
|
|
|
if !ok {
|
|
|
|
|
common.Log.Debug("ERROR: Invalid LastChar type (%T)", obj)
|
2018-07-15 16:28:56 +10:00
|
|
|
|
return nil, core.ErrTypeError
|
2018-07-06 16:41:13 +10:00
|
|
|
|
}
|
2018-11-18 17:21:30 +11:00
|
|
|
|
lastChar := int(intVal)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-11-18 17:21:30 +11:00
|
|
|
|
font.charWidths = map[uint16]float64{}
|
2018-07-06 16:41:13 +10:00
|
|
|
|
obj = d.Get("Widths")
|
2018-07-13 17:40:27 +10:00
|
|
|
|
if obj != nil {
|
|
|
|
|
font.Widths = obj
|
|
|
|
|
|
2018-07-24 21:32:02 +10:00
|
|
|
|
arr, ok := core.GetArray(obj)
|
2018-07-13 17:40:27 +10:00
|
|
|
|
if !ok {
|
2018-07-19 10:28:23 +10:00
|
|
|
|
common.Log.Debug("ERROR: Widths attribute != array (%T)", obj)
|
2018-07-15 16:28:56 +10:00
|
|
|
|
return nil, core.ErrTypeError
|
2018-07-13 17:40:27 +10:00
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-07-13 17:40:27 +10:00
|
|
|
|
widths, err := arr.ToFloat64Array()
|
|
|
|
|
if err != nil {
|
|
|
|
|
common.Log.Debug("ERROR: converting widths to array")
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-11-18 17:21:30 +11:00
|
|
|
|
if len(widths) != (lastChar - firstChar + 1) {
|
2018-07-13 17:40:27 +10:00
|
|
|
|
common.Log.Debug("ERROR: Invalid widths length != %d (%d)",
|
2018-11-18 17:21:30 +11:00
|
|
|
|
lastChar-firstChar+1, len(widths))
|
2018-07-15 16:28:56 +10:00
|
|
|
|
return nil, core.ErrRangeError
|
2018-07-13 17:40:27 +10:00
|
|
|
|
}
|
2018-11-18 17:21:30 +11:00
|
|
|
|
for i, w := range widths {
|
|
|
|
|
font.charWidths[uint16(firstChar+i)] = w
|
|
|
|
|
}
|
2018-07-06 16:41:13 +10:00
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-07-15 16:28:56 +10:00
|
|
|
|
font.Encoding = core.TraceToDirectObject(d.Get("Encoding"))
|
2018-07-06 16:41:13 +10:00
|
|
|
|
return font, nil
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 10:32:49 +00:00
|
|
|
|
// addEncoding adds the encoding to the font and sets the `font.encoder` field.
|
|
|
|
|
// The order of precedence is important:
|
|
|
|
|
// 1. If encoder already set, load it initially (with subsequent steps potentially overwriting).
|
|
|
|
|
// 2. Attempts to construct the encoder from the Encoding dictionary.
|
|
|
|
|
// 3. If no encoder loaded, attempt to load from the font file.
|
|
|
|
|
// 4. Apply differences map and set as the `font`'s encoder.
|
2018-07-06 16:41:13 +10:00
|
|
|
|
func (font *pdfFontSimple) addEncoding() error {
|
2018-07-13 17:40:27 +10:00
|
|
|
|
var baseEncoder string
|
|
|
|
|
var differences map[byte]string
|
2018-07-31 11:44:37 +10:00
|
|
|
|
var encoder *textencoding.SimpleEncoder
|
2018-07-23 14:55:23 +10:00
|
|
|
|
|
2018-11-22 22:01:04 +11:00
|
|
|
|
if font.Encoder() != nil {
|
|
|
|
|
encoder, ok := font.Encoder().(*textencoding.SimpleEncoder)
|
|
|
|
|
if ok && encoder != nil {
|
|
|
|
|
baseEncoder = encoder.BaseName()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-13 17:40:27 +10:00
|
|
|
|
if font.Encoding != nil {
|
2018-11-22 22:01:04 +11:00
|
|
|
|
baseEncoderName, differences, err := font.getFontEncoding()
|
2018-07-13 17:40:27 +10:00
|
|
|
|
if err != nil {
|
2018-07-16 17:42:08 +10:00
|
|
|
|
common.Log.Debug("ERROR: BaseFont=%q Subtype=%q Encoding=%s (%T) err=%v", font.basefont,
|
|
|
|
|
font.subtype, font.Encoding, font.Encoding, err)
|
2018-07-13 17:40:27 +10:00
|
|
|
|
return err
|
|
|
|
|
}
|
2018-11-22 22:01:04 +11:00
|
|
|
|
if baseEncoderName != "" {
|
|
|
|
|
baseEncoder = baseEncoderName
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 11:44:37 +10:00
|
|
|
|
encoder, err = textencoding.NewSimpleTextEncoder(baseEncoder, differences)
|
2018-07-06 16:41:13 +10:00
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2018-06-27 12:25:59 +10:00
|
|
|
|
}
|
2018-07-06 16:41:13 +10:00
|
|
|
|
|
2018-07-31 11:44:37 +10:00
|
|
|
|
if encoder == nil {
|
2018-07-16 17:42:08 +10:00
|
|
|
|
descriptor := font.fontDescriptor
|
2018-07-13 17:40:27 +10:00
|
|
|
|
if descriptor != nil {
|
2018-07-16 17:42:08 +10:00
|
|
|
|
switch font.subtype {
|
2018-07-13 17:40:27 +10:00
|
|
|
|
case "Type1":
|
|
|
|
|
if descriptor.fontFile != nil && descriptor.fontFile.encoder != nil {
|
|
|
|
|
common.Log.Debug("Using fontFile")
|
2018-07-31 11:44:37 +10:00
|
|
|
|
encoder = descriptor.fontFile.encoder
|
2018-07-13 17:40:27 +10:00
|
|
|
|
}
|
|
|
|
|
case "TrueType":
|
|
|
|
|
if descriptor.fontFile2 != nil {
|
|
|
|
|
common.Log.Debug("Using FontFile2")
|
2018-07-31 11:44:37 +10:00
|
|
|
|
enc, err := descriptor.fontFile2.MakeEncoder()
|
2018-07-13 21:15:03 +10:00
|
|
|
|
if err == nil {
|
2018-07-31 11:44:37 +10:00
|
|
|
|
encoder = enc
|
2018-07-13 17:40:27 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-02 16:46:43 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-06 16:41:13 +10:00
|
|
|
|
|
2018-07-31 11:44:37 +10:00
|
|
|
|
if encoder != nil {
|
|
|
|
|
// At the end, apply the differences.
|
|
|
|
|
if differences != nil {
|
|
|
|
|
common.Log.Trace("differences=%+v font=%s", differences, font.baseFields())
|
|
|
|
|
encoder.ApplyDifferences(differences)
|
2018-07-03 14:26:42 +10:00
|
|
|
|
}
|
2018-07-31 11:44:37 +10:00
|
|
|
|
font.SetEncoder(encoder)
|
2018-06-27 12:25:59 +10:00
|
|
|
|
}
|
2018-07-31 11:44:37 +10:00
|
|
|
|
|
2018-07-06 16:41:13 +10:00
|
|
|
|
return nil
|
2018-06-27 12:25:59 +10:00
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-07-25 16:14:19 +10:00
|
|
|
|
// getFontEncoding returns font encoding of `obj` the "Encoding" entry in a font dict.
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// Table 114 – Entries in an encoding dictionary (page 263)
|
|
|
|
|
// 9.6.6.1 General (page 262)
|
|
|
|
|
// A font’s encoding is the association between character codes (obtained from text strings that
|
|
|
|
|
// are shown) and glyph descriptions. This sub-clause describes the character encoding scheme used
|
|
|
|
|
// with simple PDF fonts. Composite fonts (Type 0) use a different character mapping algorithm, as
|
|
|
|
|
// discussed in 9.7, "Composite Fonts".
|
|
|
|
|
// Except for Type 3 fonts, every font program shall have a built-in encoding. Under certain
|
|
|
|
|
// circumstances, a PDF font dictionary may change the encoding used with the font program to match
|
|
|
|
|
// the requirements of the conforming writer generating the text being shown.
|
2018-11-22 22:01:04 +11:00
|
|
|
|
func (font *pdfFontSimple) getFontEncoding() (baseName string, differences map[byte]string, err error) {
|
2018-07-24 21:32:02 +10:00
|
|
|
|
baseName = "StandardEncoding"
|
2018-11-22 22:01:04 +11:00
|
|
|
|
if name, ok := builtinEncodings[font.basefont]; ok {
|
|
|
|
|
baseName = name
|
|
|
|
|
} else if font.fontFlags()&fontFlagSymbolic != 0 {
|
|
|
|
|
for base, name := range builtinEncodings {
|
|
|
|
|
if strings.Contains(font.basefont, base) {
|
|
|
|
|
baseName = name
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-27 12:25:59 +10:00
|
|
|
|
|
2018-11-22 22:01:04 +11:00
|
|
|
|
if font.Encoding == nil {
|
2018-11-23 11:21:51 +11:00
|
|
|
|
// Fall back to StandardEncoding | SymbolEncoding | ZapfDingbatsEncoding
|
2018-07-26 14:36:40 +10:00
|
|
|
|
// This works because the only way BaseEncoding can get overridden is by FontFile entries
|
|
|
|
|
// and the only encoding names we have seen in FontFile's are StandardEncoding or no entry.
|
2018-06-27 12:25:59 +10:00
|
|
|
|
return baseName, nil, nil
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-22 22:01:04 +11:00
|
|
|
|
switch encoding := font.Encoding.(type) {
|
2018-07-15 16:28:56 +10:00
|
|
|
|
case *core.PdfObjectName:
|
2018-06-27 12:25:59 +10:00
|
|
|
|
return string(*encoding), nil, nil
|
2018-07-15 16:28:56 +10:00
|
|
|
|
case *core.PdfObjectDictionary:
|
2018-07-25 16:14:19 +10:00
|
|
|
|
if typ, ok := core.GetNameVal(encoding.Get("Type")); ok && typ == "Encoding" {
|
|
|
|
|
if base, ok := core.GetNameVal(encoding.Get("BaseEncoding")); ok {
|
2018-06-27 12:25:59 +10:00
|
|
|
|
baseName = base
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-21 13:14:11 +11:00
|
|
|
|
if diffObj := encoding.Get("Differences"); diffObj != nil {
|
|
|
|
|
diffList, ok := core.GetArray(diffObj)
|
|
|
|
|
if !ok {
|
|
|
|
|
common.Log.Debug("ERROR: Bad font encoding dict=%+v Differences=%T",
|
|
|
|
|
encoding, encoding.Get("Differences"))
|
|
|
|
|
return "", nil, core.ErrTypeError
|
|
|
|
|
}
|
|
|
|
|
differences, err = textencoding.FromFontDifferences(diffList)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-06-27 12:25:59 +10:00
|
|
|
|
return baseName, differences, err
|
|
|
|
|
default:
|
2018-11-22 22:01:04 +11:00
|
|
|
|
common.Log.Debug("ERROR: Encoding not a name or dict (%T) %s", font.Encoding, font.Encoding)
|
2018-07-15 16:28:56 +10:00
|
|
|
|
return "", nil, core.ErrTypeError
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 11:21:51 +11:00
|
|
|
|
var builtinEncodings = map[string]string{
|
|
|
|
|
"Symbol": "SymbolEncoding",
|
|
|
|
|
"ZapfDingbats": "ZapfDingbatsEncoding",
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// ToPdfObject converts the pdfFontSimple to its PDF representation for outputting.
|
2018-07-15 16:28:56 +10:00
|
|
|
|
func (font *pdfFontSimple) ToPdfObject() core.PdfObject {
|
2018-06-27 12:25:59 +10:00
|
|
|
|
if font.container == nil {
|
2018-07-15 16:28:56 +10:00
|
|
|
|
font.container = &core.PdfIndirectObject{}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-07-16 17:42:08 +10:00
|
|
|
|
d := font.baseFields().asPdfObjectDictionary("")
|
2018-06-27 12:25:59 +10:00
|
|
|
|
font.container.PdfObject = d
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
if font.FirstChar != nil {
|
|
|
|
|
d.Set("FirstChar", font.FirstChar)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-06-27 12:25:59 +10:00
|
|
|
|
if font.LastChar != nil {
|
|
|
|
|
d.Set("LastChar", font.LastChar)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-06-27 12:25:59 +10:00
|
|
|
|
if font.Widths != nil {
|
|
|
|
|
d.Set("Widths", font.Widths)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-06-27 12:25:59 +10:00
|
|
|
|
if font.Encoding != nil {
|
|
|
|
|
d.Set("Encoding", font.Encoding)
|
2018-07-16 17:42:08 +10:00
|
|
|
|
} else if font.encoder != nil {
|
2018-11-01 21:33:51 +11:00
|
|
|
|
encObj := font.encoder.ToPdfObject()
|
|
|
|
|
if encObj != nil {
|
|
|
|
|
d.Set("Encoding", encObj)
|
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
return font.container
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
// NewPdfFontFromTTFFile loads a TTF font and returns a PdfFont type that can be used in text
|
|
|
|
|
// styling functions.
|
2017-09-01 13:20:51 +00:00
|
|
|
|
// Uses a WinAnsiTextEncoder and loads only character codes 32-255.
|
|
|
|
|
func NewPdfFontFromTTFFile(filePath string) (*PdfFont, error) {
|
2018-07-02 13:49:06 +10:00
|
|
|
|
const minCode = 32
|
|
|
|
|
const maxCode = 255
|
|
|
|
|
|
2017-09-01 13:20:51 +00:00
|
|
|
|
ttf, err := fonts.TtfParse(filePath)
|
|
|
|
|
if err != nil {
|
2018-06-27 12:25:59 +10:00
|
|
|
|
common.Log.Debug("ERROR: loading ttf font: %v", err)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 14:55:23 +10:00
|
|
|
|
truefont := &pdfFontSimple{
|
2018-11-18 17:21:30 +11:00
|
|
|
|
charWidths: map[uint16]float64{},
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "TrueType",
|
|
|
|
|
},
|
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
truefont.encoder = textencoding.NewWinAnsiTextEncoder()
|
|
|
|
|
|
2018-07-02 17:10:34 +10:00
|
|
|
|
truefont.basefont = ttf.PostScriptName
|
2018-07-15 16:28:56 +10:00
|
|
|
|
truefont.FirstChar = core.MakeInteger(minCode)
|
|
|
|
|
truefont.LastChar = core.MakeInteger(maxCode)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
k := 1000.0 / float64(ttf.UnitsPerEm)
|
|
|
|
|
if len(ttf.Widths) <= 0 {
|
2018-06-27 12:25:59 +10:00
|
|
|
|
return nil, errors.New("ERROR: Missing required attribute (Widths)")
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
missingWidth := k * float64(ttf.Widths[0])
|
|
|
|
|
|
2018-07-02 13:49:06 +10:00
|
|
|
|
vals := make([]float64, 0, maxCode-minCode+1)
|
|
|
|
|
for code := minCode; code <= maxCode; code++ {
|
2018-06-27 12:25:59 +10:00
|
|
|
|
r, found := truefont.Encoder().CharcodeToRune(uint16(code))
|
2017-09-01 13:20:51 +00:00
|
|
|
|
if !found {
|
2018-06-27 12:25:59 +10:00
|
|
|
|
common.Log.Debug("Rune not found (code: %d)", code)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
vals = append(vals, missingWidth)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
pos, ok := ttf.Chars[uint16(r)]
|
2017-09-01 13:20:51 +00:00
|
|
|
|
if !ok {
|
|
|
|
|
common.Log.Debug("Rune not in TTF Chars")
|
|
|
|
|
vals = append(vals, missingWidth)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := k * float64(ttf.Widths[pos])
|
|
|
|
|
|
|
|
|
|
vals = append(vals, w)
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:14:19 +10:00
|
|
|
|
truefont.Widths = core.MakeIndirectObject(core.MakeArrayFromFloats(vals))
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-11-18 17:21:30 +11:00
|
|
|
|
if len(vals) < maxCode-minCode+1 {
|
2018-06-27 12:25:59 +10:00
|
|
|
|
common.Log.Debug("ERROR: Invalid length of widths, %d < %d", len(vals), 255-32+1)
|
2018-07-15 16:28:56 +10:00
|
|
|
|
return nil, core.ErrRangeError
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-18 17:21:30 +11:00
|
|
|
|
for i := uint16(minCode); i <= maxCode; i++ {
|
|
|
|
|
truefont.charWidths[i] = vals[i-minCode]
|
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
// Use WinAnsiEncoding by default.
|
2018-07-15 16:28:56 +10:00
|
|
|
|
truefont.Encoding = core.MakeName("WinAnsiEncoding")
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
descriptor := &PdfFontDescriptor{}
|
2018-09-07 21:43:39 +10:00
|
|
|
|
descriptor.FontName = core.MakeName(ttf.PostScriptName)
|
2018-07-15 16:28:56 +10:00
|
|
|
|
descriptor.Ascent = core.MakeFloat(k * float64(ttf.TypoAscender))
|
|
|
|
|
descriptor.Descent = core.MakeFloat(k * float64(ttf.TypoDescender))
|
|
|
|
|
descriptor.CapHeight = core.MakeFloat(k * float64(ttf.CapHeight))
|
|
|
|
|
descriptor.FontBBox = core.MakeArrayFromFloats([]float64{k * float64(ttf.Xmin),
|
|
|
|
|
k * float64(ttf.Ymin), k * float64(ttf.Xmax), k * float64(ttf.Ymax)})
|
|
|
|
|
descriptor.ItalicAngle = core.MakeFloat(float64(ttf.ItalicAngle))
|
|
|
|
|
descriptor.MissingWidth = core.MakeFloat(k * float64(ttf.Widths[0]))
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
ttfBytes, err := ioutil.ReadFile(filePath)
|
|
|
|
|
if err != nil {
|
2018-07-15 16:28:56 +10:00
|
|
|
|
common.Log.Debug("ERROR: Unable to read file contents: %v", err)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-15 16:28:56 +10:00
|
|
|
|
stream, err := core.MakeStream(ttfBytes, core.NewFlateEncoder())
|
2017-09-01 13:20:51 +00:00
|
|
|
|
if err != nil {
|
2018-07-15 16:28:56 +10:00
|
|
|
|
common.Log.Debug("ERROR: Unable to make stream: %v", err)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2018-07-15 16:28:56 +10:00
|
|
|
|
stream.PdfObjectDictionary.Set("Length1", core.MakeInteger(int64(len(ttfBytes))))
|
2017-09-01 13:20:51 +00:00
|
|
|
|
descriptor.FontFile2 = stream
|
|
|
|
|
|
|
|
|
|
if ttf.Bold {
|
2018-07-15 16:28:56 +10:00
|
|
|
|
descriptor.StemV = core.MakeInteger(120)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
} else {
|
2018-07-15 16:28:56 +10:00
|
|
|
|
descriptor.StemV = core.MakeInteger(70)
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 13:21:13 +10:00
|
|
|
|
flags := fontFlagNonsymbolic
|
2017-09-01 13:20:51 +00:00
|
|
|
|
if ttf.IsFixedPitch {
|
2018-07-23 13:21:13 +10:00
|
|
|
|
flags |= fontFlagFixedPitch
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
|
|
|
|
if ttf.ItalicAngle != 0 {
|
2018-07-23 13:21:13 +10:00
|
|
|
|
flags |= fontFlagItalic
|
2017-09-01 13:20:51 +00:00
|
|
|
|
}
|
2018-07-15 16:28:56 +10:00
|
|
|
|
descriptor.Flags = core.MakeInteger(int64(flags))
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
// Build Font.
|
2018-07-16 17:42:08 +10:00
|
|
|
|
truefont.fontDescriptor = descriptor
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
2018-06-27 12:25:59 +10:00
|
|
|
|
font := &PdfFont{
|
2018-07-16 17:42:08 +10:00
|
|
|
|
context: truefont,
|
2018-06-27 12:25:59 +10:00
|
|
|
|
}
|
2017-09-01 13:20:51 +00:00
|
|
|
|
|
|
|
|
|
return font, nil
|
|
|
|
|
}
|
2018-07-16 17:42:08 +10:00
|
|
|
|
|
2018-09-21 16:25:57 +10:00
|
|
|
|
// Standard14Font is to be used only to define the standard 14 font names that follow.
|
|
|
|
|
// This guarantees that calls to NewStandard14FontMustCompile will succeed.
|
|
|
|
|
type Standard14Font string
|
|
|
|
|
|
2018-12-07 10:32:49 +00:00
|
|
|
|
// Standard 14 fonts constant definitions.
|
2018-09-21 16:25:57 +10:00
|
|
|
|
const (
|
|
|
|
|
Courier Standard14Font = "Courier"
|
|
|
|
|
CourierBold Standard14Font = "Courier-Bold"
|
|
|
|
|
CourierBoldOblique Standard14Font = "Courier-BoldOblique"
|
|
|
|
|
CourierOblique Standard14Font = "Courier-Oblique"
|
|
|
|
|
Helvetica Standard14Font = "Helvetica"
|
|
|
|
|
HelveticaBold Standard14Font = "Helvetica-Bold"
|
|
|
|
|
HelveticaBoldOblique Standard14Font = "Helvetica-BoldOblique"
|
|
|
|
|
HelveticaOblique Standard14Font = "Helvetica-Oblique"
|
|
|
|
|
TimesRoman Standard14Font = "Times-Roman"
|
|
|
|
|
TimesBold Standard14Font = "Times-Bold"
|
|
|
|
|
TimesBoldItalic Standard14Font = "Times-BoldItalic"
|
|
|
|
|
TimesItalic Standard14Font = "Times-Italic"
|
|
|
|
|
Symbol Standard14Font = "Symbol"
|
|
|
|
|
ZapfDingbats Standard14Font = "ZapfDingbats"
|
|
|
|
|
)
|
|
|
|
|
|
2018-11-23 11:21:51 +11:00
|
|
|
|
func isBuiltin(basefont Standard14Font) bool {
|
|
|
|
|
if alias, ok := standard14Aliases[basefont]; ok {
|
|
|
|
|
basefont = alias
|
|
|
|
|
}
|
|
|
|
|
_, ok := standard14Fonts[basefont]
|
|
|
|
|
return ok
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-08 15:20:12 +11:00
|
|
|
|
// loadStandard14Font returns the builtin font named `baseFont`. The boolean return indicates whether
|
2018-10-18 21:12:15 +11:00
|
|
|
|
// the builtin font exists.
|
|
|
|
|
func loadStandard14Font(baseFont Standard14Font) (pdfFontSimple, bool) {
|
2018-11-20 17:49:37 +11:00
|
|
|
|
if alias, ok := standard14Aliases[baseFont]; ok {
|
|
|
|
|
baseFont = alias
|
|
|
|
|
}
|
2018-10-18 21:12:15 +11:00
|
|
|
|
std, ok := standard14Fonts[baseFont]
|
|
|
|
|
if !ok {
|
|
|
|
|
return pdfFontSimple{}, false
|
|
|
|
|
}
|
2018-11-18 17:21:30 +11:00
|
|
|
|
|
2018-10-18 21:12:15 +11:00
|
|
|
|
descriptor := builtinDescriptor(string(baseFont))
|
|
|
|
|
if descriptor == nil {
|
|
|
|
|
return pdfFontSimple{}, false
|
|
|
|
|
}
|
2018-11-10 21:41:47 +11:00
|
|
|
|
|
2018-10-18 21:12:15 +11:00
|
|
|
|
std.std14Descriptor = descriptor
|
2018-11-18 17:21:30 +11:00
|
|
|
|
|
|
|
|
|
return std, true
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 11:21:51 +11:00
|
|
|
|
// updateStandard14Font fills the font.charWidths for standard 14 fonts.
|
|
|
|
|
// Don't call this function with a font that is not in the standard 14.
|
2018-11-18 17:21:30 +11:00
|
|
|
|
func (font *pdfFontSimple) updateStandard14Font() {
|
|
|
|
|
se, ok := font.Encoder().(*textencoding.SimpleEncoder)
|
2018-11-08 15:20:12 +11:00
|
|
|
|
if !ok {
|
2018-11-18 17:21:30 +11:00
|
|
|
|
// This can't happen.
|
|
|
|
|
common.Log.Error("Wrong encoder type: %T. font=%s.", font.Encoder(), font)
|
|
|
|
|
return
|
2018-11-08 15:20:12 +11:00
|
|
|
|
}
|
2018-11-18 17:21:30 +11:00
|
|
|
|
|
|
|
|
|
font.charWidths = map[uint16]float64{}
|
2018-11-23 11:21:51 +11:00
|
|
|
|
for code, glyph := range se.CodeToGlyph {
|
2018-11-18 17:21:30 +11:00
|
|
|
|
font.charWidths[code] = font.fontMetrics[glyph].Wx
|
2018-11-08 15:20:12 +11:00
|
|
|
|
}
|
2018-10-18 21:12:15 +11:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-20 17:49:37 +11:00
|
|
|
|
// The aliases seen for the standard 14 font names.
|
2018-11-21 13:14:11 +11:00
|
|
|
|
// Most of these are from table 5.5.1 in
|
|
|
|
|
// https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/adobe_supplement_iso32000.pdf
|
2018-11-20 17:49:37 +11:00
|
|
|
|
var standard14Aliases = map[Standard14Font]Standard14Font{
|
|
|
|
|
"CourierCourierNew": "Courier",
|
|
|
|
|
"CourierNew": "Courier",
|
|
|
|
|
"CourierNew,Italic": "Courier-Oblique",
|
|
|
|
|
"CourierNew,Bold": "Courier-Bold",
|
|
|
|
|
"CourierNew,BoldItalic": "Courier-BoldOblique",
|
|
|
|
|
"Arial": "Helvetica",
|
|
|
|
|
"Arial,Italic": "Helvetica-Oblique",
|
|
|
|
|
"Arial,Bold": "Helvetica-Bold",
|
|
|
|
|
"Arial,BoldItalic": "Helvetica-BoldOblique",
|
|
|
|
|
"TimesNewRoman": "Times-Roman",
|
|
|
|
|
"TimesNewRoman,Italic": "Times-Italic",
|
|
|
|
|
"TimesNewRoman,Bold": "Times-Bold",
|
|
|
|
|
"TimesNewRoman,BoldItalic": "Times-BoldItalic",
|
|
|
|
|
"Times": "Times-Roman",
|
|
|
|
|
"Times,Italic": "Times-Italic",
|
|
|
|
|
"Times,Bold": "Times-Bold",
|
|
|
|
|
"Times,BoldItalic": "Times-BoldItalic",
|
|
|
|
|
"Symbol,Italic": "Symbol",
|
|
|
|
|
"Symbol,Bold": "Symbol",
|
|
|
|
|
"Symbol,BoldItalic": "Symbol",
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-21 16:25:57 +10:00
|
|
|
|
var standard14Fonts = map[Standard14Font]pdfFontSimple{
|
|
|
|
|
Courier: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Courier",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.CourierCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
CourierBold: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Courier-Bold",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.CourierBoldCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
CourierBoldOblique: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Courier-BoldOblique",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.CourierBoldObliqueCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
CourierOblique: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Courier-Oblique",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.CourierObliqueCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
Helvetica: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Helvetica",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.HelveticaCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
HelveticaBold: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Helvetica-Bold",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.HelveticaBoldCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
HelveticaBoldOblique: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Helvetica-BoldOblique",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.HelveticaBoldObliqueCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
HelveticaOblique: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Helvetica-Oblique",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.HelveticaObliqueCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
TimesRoman: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Times-Roman",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.TimesRomanCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
TimesBold: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Times-Bold",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.TimesBoldCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
TimesBoldItalic: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Times-BoldItalic",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.TimesBoldItalicCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
TimesItalic: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Times-Italic",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewWinAnsiTextEncoder(),
|
|
|
|
|
fontMetrics: fonts.TimesItalicCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
Symbol: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "Symbol",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewSymbolEncoder(),
|
|
|
|
|
fontMetrics: fonts.SymbolCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
2018-09-21 16:25:57 +10:00
|
|
|
|
ZapfDingbats: pdfFontSimple{
|
2018-07-23 14:55:23 +10:00
|
|
|
|
fontCommon: fontCommon{
|
|
|
|
|
subtype: "Type1",
|
|
|
|
|
basefont: "ZapfDingbats",
|
|
|
|
|
},
|
2018-10-16 14:50:43 +11:00
|
|
|
|
std14Encoder: textencoding.NewZapfDingbatsEncoder(),
|
|
|
|
|
fontMetrics: fonts.ZapfDingbatsCharMetrics,
|
2018-07-16 17:42:08 +10:00
|
|
|
|
},
|
|
|
|
|
}
|
2018-10-18 21:12:15 +11:00
|
|
|
|
|
|
|
|
|
// builtinDescriptor returns the PdfFontDescriptor for the builtin font named `baseFont`, or nil if
|
|
|
|
|
// there is none.
|
|
|
|
|
func builtinDescriptor(baseFont string) *PdfFontDescriptor {
|
|
|
|
|
l, ok := fonts.Standard14Descriptors[baseFont]
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &PdfFontDescriptor{
|
2018-10-23 10:36:38 +11:00
|
|
|
|
FontName: core.MakeName(l.FontName),
|
|
|
|
|
FontFamily: core.MakeName(l.FontFamily),
|
2018-10-23 10:44:58 +11:00
|
|
|
|
FontWeight: core.MakeFloat(float64(l.FontWeight)),
|
2018-10-23 10:36:38 +11:00
|
|
|
|
Flags: core.MakeInteger(int64(l.Flags)),
|
|
|
|
|
FontBBox: core.MakeArrayFromFloats(l.FontBBox[:]),
|
|
|
|
|
ItalicAngle: core.MakeFloat(l.ItalicAngle),
|
|
|
|
|
Ascent: core.MakeFloat(l.Ascent),
|
|
|
|
|
Descent: core.MakeFloat(l.Descent),
|
|
|
|
|
CapHeight: core.MakeFloat(l.CapHeight),
|
|
|
|
|
XHeight: core.MakeFloat(l.XHeight),
|
|
|
|
|
StemV: core.MakeFloat(l.StemV),
|
|
|
|
|
StemH: core.MakeFloat(l.StemH),
|
2018-10-18 21:12:15 +11:00
|
|
|
|
}
|
|
|
|
|
}
|