mirror of
https://github.com/unidoc/unipdf.git
synced 2025-05-01 22:17:29 +08:00
commit
098019ac2c
19
Gopkg.lock
generated
19
Gopkg.lock
generated
@ -21,9 +21,26 @@
|
||||
]
|
||||
revision = "cd38e8056d9b27bb2f265effa37fb0ea6b8a7f0f"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"encoding",
|
||||
"encoding/charmap",
|
||||
"encoding/internal",
|
||||
"encoding/internal/identifier",
|
||||
"internal/gen",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"transform",
|
||||
"unicode/cldr",
|
||||
"unicode/norm"
|
||||
]
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "2dcb31447fae810daeea813d2c0cdaa9bce2122d0e556718741fcef5a7506eed"
|
||||
inputs-digest = "564f0035f32edd92273b270310a310d5b3111a181851eb2c0e2f0d514980aa2e"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
1
go.mod
1
go.mod
@ -3,4 +3,5 @@ module github.com/unidoc/unidoc
|
||||
require (
|
||||
github.com/boombuler/barcode v1.0.0
|
||||
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b
|
||||
golang.org/x/text v0.3.0
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -2,3 +2,5 @@ github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDd
|
||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b h1:VHyIDlv3XkfCa5/a81uzaoDkHH4rr81Z62g+xlnO8uM=
|
||||
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/contentstream"
|
||||
"github.com/unidoc/unidoc/pdf/core"
|
||||
"github.com/unidoc/unidoc/pdf/internal/textencoding"
|
||||
"github.com/unidoc/unidoc/pdf/model"
|
||||
)
|
||||
|
||||
@ -33,9 +32,8 @@ type FieldAppearance struct {
|
||||
type AppearanceStyle struct {
|
||||
// How much of Rect height to fill when autosizing text.
|
||||
AutoFontSizeFraction float64
|
||||
// Glyph used for check mark in checkboxes (for ZapfDingbats font).
|
||||
// TODO(dennwc): can be a rune
|
||||
CheckmarkGlyph textencoding.GlyphName
|
||||
// CheckmarkRune is a rune used for check mark in checkboxes (for ZapfDingbats font).
|
||||
CheckmarkRune rune
|
||||
|
||||
BorderSize float64
|
||||
BorderColor model.PdfColor
|
||||
@ -73,7 +71,7 @@ func (fa FieldAppearance) Style() AppearanceStyle {
|
||||
// Default values returned if style not set.
|
||||
return AppearanceStyle{
|
||||
AutoFontSizeFraction: 0.65,
|
||||
CheckmarkGlyph: "a20",
|
||||
CheckmarkRune: '✔',
|
||||
BorderSize: 0.0,
|
||||
BorderColor: model.NewPdfColorDeviceGray(0),
|
||||
FillColor: model.NewPdfColorDeviceGray(1),
|
||||
@ -759,18 +757,13 @@ func genFieldCheckboxAppearance(wa *model.PdfAnnotationWidget, fbtn *model.PdfFi
|
||||
|
||||
fontsize := style.AutoFontSizeFraction * height
|
||||
|
||||
checkcode, ok := zapfdb.Encoder().GlyphToCharcode(style.CheckmarkGlyph)
|
||||
if !ok {
|
||||
return nil, errors.New("checkmark glyph - charcode mapping not found")
|
||||
}
|
||||
checkrune, ok := zapfdb.Encoder().CharcodeToRune(checkcode)
|
||||
if !ok {
|
||||
return nil, errors.New("checkmark glyph - rune mapping not found")
|
||||
}
|
||||
checkmetrics, ok := zapfdb.GetRuneMetrics(checkrune)
|
||||
checkmetrics, ok := zapfdb.GetRuneMetrics(style.CheckmarkRune)
|
||||
if !ok {
|
||||
return nil, errors.New("glyph not found")
|
||||
}
|
||||
enc := zapfdb.Encoder()
|
||||
checkstr := enc.Encode(string(style.CheckmarkRune))
|
||||
|
||||
checkwidth := checkmetrics.Wx * fontsize / 1000.0
|
||||
// TODO: Get bbox of specific glyph that is chosen. Choice of specific value will cause slight
|
||||
// deviations for other glyphs, but should be fairly close.
|
||||
@ -791,7 +784,7 @@ func genFieldCheckboxAppearance(wa *model.PdfAnnotationWidget, fbtn *model.PdfFi
|
||||
Add_BT().
|
||||
Add_Tf("ZaDb", fontsize).
|
||||
Add_Td(tx, ty).
|
||||
Add_Tj(*core.MakeString(string(checkcode))).
|
||||
Add_Tj(*core.MakeStringFromBytes(checkstr)).
|
||||
Add_ET().
|
||||
Add_Q()
|
||||
|
||||
@ -1091,11 +1084,10 @@ func (style *AppearanceStyle) applyAppearanceCharacteristics(mkDict *core.PdfObj
|
||||
// Normal caption.
|
||||
if CA, has := core.GetString(mkDict.Get("CA")); has && font != nil {
|
||||
encoded := CA.Bytes()
|
||||
if len(encoded) == 1 {
|
||||
// TODO: this may be a multi-byte encoding
|
||||
charcode := textencoding.CharCode(encoded[0])
|
||||
if checkglyph, has := font.Encoder().CharcodeToGlyph(charcode); has {
|
||||
style.CheckmarkGlyph = checkglyph
|
||||
if len(encoded) != 0 {
|
||||
runes := []rune(font.Encoder().Decode(encoded))
|
||||
if len(runes) == 1 {
|
||||
style.CheckmarkRune = runes[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ package creator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
@ -496,31 +497,30 @@ func drawParagraphOnBlock(blk *Block, p *Paragraph, ctx DrawContext) (DrawContex
|
||||
shift := (p.wrapWidth*1000.0 - textWidth) / p.fontSize
|
||||
objs = append(objs, core.MakeFloat(-shift))
|
||||
}
|
||||
enc := p.textFont.Encoder()
|
||||
|
||||
var encoded []byte
|
||||
isCID := p.textFont.IsCID()
|
||||
for _, r := range runes {
|
||||
glyph, ok := p.textFont.Encoder().RuneToGlyph(r)
|
||||
if !ok {
|
||||
common.Log.Debug("Rune 0x%x not supported by text encoder", r)
|
||||
return ctx, errors.New("unsupported rune in text encoding")
|
||||
}
|
||||
|
||||
if glyph == "space" { // TODO: What about \t and other spaces.
|
||||
if r == ' ' { // TODO: What about \t and other spaces.
|
||||
if len(encoded) > 0 {
|
||||
objs = append(objs, core.MakeStringFromBytes(encoded))
|
||||
encoded = []byte{}
|
||||
encoded = nil
|
||||
}
|
||||
objs = append(objs, core.MakeFloat(-spaceWidth))
|
||||
} else {
|
||||
code, ok := p.textFont.Encoder().RuneToCharcode(r)
|
||||
if ok {
|
||||
if isCID {
|
||||
hi, lo := code>>8, code&0xff
|
||||
encoded = append(encoded, byte(hi), byte(lo))
|
||||
} else {
|
||||
encoded = append(encoded, byte(code))
|
||||
}
|
||||
code, ok := enc.RuneToCharcode(r)
|
||||
if !ok {
|
||||
err := fmt.Errorf("unsupported rune in text encoding: %#x (%c)", r, r)
|
||||
common.Log.Debug("%s", err)
|
||||
return ctx, err
|
||||
}
|
||||
// TODO(dennwc): this should not be done manually; encoder should do this
|
||||
if isCID {
|
||||
hi, lo := code>>8, code&0xff
|
||||
encoded = append(encoded, byte(hi), byte(lo))
|
||||
} else {
|
||||
encoded = append(encoded, byte(code))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -659,16 +659,11 @@ func drawStyledParagraphOnBlock(blk *Block, p *StyledParagraph, ctx DrawContext)
|
||||
fontSize = style.FontSize
|
||||
spaceWidth = spaceMetrics.Wx
|
||||
}
|
||||
enc := style.Font.Encoder()
|
||||
|
||||
var encStr []byte
|
||||
for _, rn := range chunk.Text {
|
||||
glyph, found := style.Font.Encoder().RuneToGlyph(rn)
|
||||
if !found {
|
||||
common.Log.Debug("Rune 0x%x not supported by text encoder", r)
|
||||
return ctx, errors.New("unsupported rune in text encoding")
|
||||
}
|
||||
|
||||
if glyph == "space" {
|
||||
if rn == ' ' {
|
||||
if len(encStr) > 0 {
|
||||
cc.Add_rg(r, g, b).
|
||||
Add_Tf(fonts[idx][k], style.FontSize).
|
||||
@ -684,7 +679,7 @@ func drawStyledParagraphOnBlock(blk *Block, p *StyledParagraph, ctx DrawContext)
|
||||
|
||||
chunkWidths[k] += spaceWidth * fontSize
|
||||
} else {
|
||||
encStr = append(encStr, style.Font.Encoder().Encode(string(rn))...)
|
||||
encStr = append(encStr, enc.Encode(string(rn))...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* 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/unidoc/pdf/core"
|
||||
|
||||
// CID represents a character identifier.
|
||||
type CID uint16
|
||||
|
||||
// CMap maps character codes to CIDs.
|
||||
type CMap interface {
|
||||
CharacterCodesToCID(charcodes []byte) ([]CID, error)
|
||||
}
|
||||
|
||||
// CMapIdentityH is a representation of the /Identity-H cmap.
|
||||
type CMapIdentityH struct {
|
||||
}
|
||||
|
||||
// CharacterCodesToCID converts charcodes to CIDs for the Identity CMap, which maps
|
||||
// 2-byte character codes (from the raw data) from 0-65535 to the same 2-byte CID value.
|
||||
func (cmap CMapIdentityH) CharacterCodesToCID(raw []byte) ([]CID, error) {
|
||||
if len(raw)%2 != 0 {
|
||||
return nil, core.ErrRangeError
|
||||
}
|
||||
|
||||
var cids []CID
|
||||
for i := 0; i < len(raw); i += 2 {
|
||||
b1 := CID(raw[i])
|
||||
b2 := CID(raw[i+1])
|
||||
cids = append(cids, (b1<<8)|b2)
|
||||
}
|
||||
return cids, nil
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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 "testing"
|
||||
|
||||
func TestCMapIdentityH_CharacterCodesToCID(t *testing.T) {
|
||||
identityCMap := CMapIdentityH{}
|
||||
|
||||
type dataPair struct {
|
||||
raw []byte
|
||||
expected []CID
|
||||
errs bool
|
||||
}
|
||||
|
||||
dataPairs := []dataPair{
|
||||
{[]byte{0x00, 0x00, 0x04, 0xff}, []CID{0x0000, 0x04ff}, false},
|
||||
{[]byte{0x00, 0x00, 0x04}, []CID{0x0000, 0x04ff}, true},
|
||||
}
|
||||
|
||||
for _, data := range dataPairs {
|
||||
cids, err := identityCMap.CharacterCodesToCID(data.raw)
|
||||
if err != nil {
|
||||
if data.errs {
|
||||
continue
|
||||
}
|
||||
t.Errorf("Failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(data.expected) != len(cids) {
|
||||
t.Errorf("Length mismatch")
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(data.expected); i++ {
|
||||
if cids[i] != data.expected[i] {
|
||||
t.Errorf("Not equal")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
182
pdf/internal/textencoding/differences.go
Normal file
182
pdf/internal/textencoding/differences.go
Normal file
@ -0,0 +1,182 @@
|
||||
package textencoding
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/core"
|
||||
)
|
||||
|
||||
// FromFontDifferences converts `diffList` (a /Differences array from an /Encoding object) to a map
|
||||
// representing character code to glyph mappings.
|
||||
func FromFontDifferences(diffList *core.PdfObjectArray) (map[CharCode]GlyphName, error) {
|
||||
differences := make(map[CharCode]GlyphName)
|
||||
var n CharCode
|
||||
for _, obj := range diffList.Elements() {
|
||||
switch v := obj.(type) {
|
||||
case *core.PdfObjectInteger:
|
||||
n = CharCode(*v)
|
||||
case *core.PdfObjectName:
|
||||
s := string(*v)
|
||||
differences[n] = GlyphName(s)
|
||||
n++
|
||||
default:
|
||||
common.Log.Debug("ERROR: Bad type. obj=%s", obj)
|
||||
return nil, core.ErrTypeError
|
||||
}
|
||||
}
|
||||
return differences, nil
|
||||
}
|
||||
|
||||
// toFontDifferences converts `differences` (a map representing character code to glyph mappings)
|
||||
// to a /Differences array for an /Encoding object.
|
||||
func toFontDifferences(differences map[CharCode]GlyphName) *core.PdfObjectArray {
|
||||
if len(differences) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
codes := make([]CharCode, 0, len(differences))
|
||||
for c := range differences {
|
||||
codes = append(codes, c)
|
||||
}
|
||||
sort.Slice(codes, func(i, j int) bool {
|
||||
return codes[i] < codes[j]
|
||||
})
|
||||
|
||||
n := codes[0]
|
||||
diffList := []core.PdfObject{core.MakeInteger(int64(n)), core.MakeName(string(differences[n]))}
|
||||
for _, c := range codes[1:] {
|
||||
if c == n+1 {
|
||||
diffList = append(diffList, core.MakeName(string(differences[c])))
|
||||
} else {
|
||||
diffList = append(diffList, core.MakeInteger(int64(c)))
|
||||
}
|
||||
n = c
|
||||
}
|
||||
return core.MakeArray(diffList...)
|
||||
}
|
||||
|
||||
// ApplyDifferences modifies or wraps the base encoding and overlays differences over it.
|
||||
func ApplyDifferences(base SimpleEncoder, differences map[CharCode]GlyphName) SimpleEncoder {
|
||||
// TODO(dennwc): check if it's a differencesEncoding, and merge the mapping
|
||||
d := &differencesEncoding{
|
||||
base: base,
|
||||
differences: differences,
|
||||
decode: make(map[byte]rune),
|
||||
encode: make(map[rune]byte),
|
||||
}
|
||||
for code, glyph := range differences {
|
||||
b := byte(code)
|
||||
r, ok := GlyphToRune(glyph)
|
||||
if ok {
|
||||
d.encode[r] = b
|
||||
} else {
|
||||
common.Log.Debug("ERROR: No match for glyph=%q differences=%+v", glyph, differences)
|
||||
}
|
||||
d.decode[b] = r
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// differencesEncoding remaps characters of a base encoding and act as a pass-trough for other characters.
|
||||
// Assumes that an underlying encoding is 8 bit.
|
||||
type differencesEncoding struct {
|
||||
base SimpleEncoder
|
||||
|
||||
// original mapping to encode to PDF
|
||||
differences map[CharCode]GlyphName
|
||||
|
||||
// overlayed on top of base encoding (8 bit)
|
||||
decode map[byte]rune
|
||||
encode map[rune]byte
|
||||
}
|
||||
|
||||
// BaseName returns base encoding name.
|
||||
func (enc *differencesEncoding) BaseName() string {
|
||||
return enc.base.BaseName()
|
||||
}
|
||||
|
||||
// String returns a string that describes the encoding.
|
||||
func (enc *differencesEncoding) String() string {
|
||||
return fmt.Sprintf("differences(%s, %v)", enc.base.String(), enc.differences)
|
||||
}
|
||||
|
||||
// Charcodes returns a slice of all charcodes in this encoding.
|
||||
func (enc *differencesEncoding) Charcodes() []CharCode {
|
||||
codes := enc.base.Charcodes()
|
||||
sorted := true
|
||||
seen := make(map[CharCode]struct{}, len(codes))
|
||||
for _, code := range codes {
|
||||
seen[code] = struct{}{}
|
||||
}
|
||||
for b := range enc.decode {
|
||||
code := CharCode(b)
|
||||
if _, ok := seen[code]; !ok {
|
||||
codes = append(codes, code)
|
||||
sorted = false
|
||||
}
|
||||
}
|
||||
if !sorted {
|
||||
sort.Slice(codes, func(i, j int) bool {
|
||||
return codes[i] < codes[j]
|
||||
})
|
||||
}
|
||||
return codes
|
||||
}
|
||||
|
||||
// Encode converts a Go unicode string to a PDF encoded string.
|
||||
func (enc *differencesEncoding) Encode(str string) []byte {
|
||||
runes := []rune(str)
|
||||
buf := bytes.NewBuffer(nil)
|
||||
buf.Grow(len(runes))
|
||||
for _, r := range runes {
|
||||
code, _ := enc.RuneToCharcode(r)
|
||||
// relies on the fact that underlying encoding is 8 bit
|
||||
buf.WriteByte(byte(code))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// Decode converts PDF encoded string to a Go unicode string.
|
||||
func (enc *differencesEncoding) Decode(raw []byte) string {
|
||||
runes := make([]rune, 0, len(raw))
|
||||
// relies on the fact that underlying encoding is 8 bit
|
||||
for _, b := range raw {
|
||||
r, _ := enc.CharcodeToRune(CharCode(b))
|
||||
runes = append(runes, r)
|
||||
}
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
// RuneToCharcode returns the PDF character code corresponding to rune `r`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func (enc *differencesEncoding) RuneToCharcode(r rune) (CharCode, bool) {
|
||||
if b, ok := enc.encode[r]; ok {
|
||||
return CharCode(b), true
|
||||
}
|
||||
return enc.base.RuneToCharcode(r)
|
||||
}
|
||||
|
||||
// CharcodeToRune returns the rune corresponding to character code `code`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func (enc *differencesEncoding) CharcodeToRune(code CharCode) (rune, bool) {
|
||||
if code > 0xff {
|
||||
return MissingCodeRune, false
|
||||
}
|
||||
b := byte(code)
|
||||
if r, ok := enc.decode[b]; ok {
|
||||
return r, true
|
||||
}
|
||||
return enc.base.CharcodeToRune(code)
|
||||
}
|
||||
|
||||
// ToPdfObject returns the encoding as a PdfObject.
|
||||
func (enc *differencesEncoding) ToPdfObject() core.PdfObject {
|
||||
dict := core.MakeDict()
|
||||
dict.Set("Type", core.MakeName("Encoding"))
|
||||
dict.Set("BaseEncoding", enc.base.ToPdfObject())
|
||||
dict.Set("Differences", toFontDifferences(enc.differences))
|
||||
return core.MakeIndirectObject(dict)
|
||||
}
|
@ -23,16 +23,11 @@ type TextEncoder interface {
|
||||
// String returns a string that describes the TextEncoder instance.
|
||||
String() string
|
||||
|
||||
// Encode converts the Go unicode string `raw` to a PDF encoded string.
|
||||
Encode(raw string) []byte
|
||||
// Encode converts the Go unicode string to a PDF encoded string.
|
||||
Encode(str string) []byte
|
||||
|
||||
// CharcodeToGlyph returns the glyph name for character code `code`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
CharcodeToGlyph(code CharCode) (GlyphName, bool)
|
||||
|
||||
// GlyphToCharcode returns the PDF character code corresponding to glyph name `glyph`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
GlyphToCharcode(glyph GlyphName) (CharCode, bool)
|
||||
// Decode converts PDF encoded string to a Go unicode string.
|
||||
Decode(raw []byte) string
|
||||
|
||||
// RuneToCharcode returns the PDF character code corresponding to rune `r`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
@ -44,14 +39,6 @@ type TextEncoder interface {
|
||||
// This is usually implemented as CharcodeToGlyph->GlyphToRune
|
||||
CharcodeToRune(code CharCode) (rune, bool)
|
||||
|
||||
// RuneToGlyph returns the glyph name for rune `r`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
RuneToGlyph(r rune) (GlyphName, bool)
|
||||
|
||||
// GlyphToRune returns the rune corresponding to glyph name `glyph`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
GlyphToRune(glyph GlyphName) (rune, bool)
|
||||
|
||||
// ToPdfObject returns a PDF Object that represents the encoding.
|
||||
ToPdfObject() core.PdfObject
|
||||
}
|
||||
@ -94,22 +81,26 @@ func encodeString16bit(enc TextEncoder, raw string) []byte {
|
||||
return encoded
|
||||
}
|
||||
|
||||
// doRuneToCharcode converts rune `r` to a PDF character code.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func doRuneToCharcode(enc TextEncoder, r rune) (CharCode, bool) {
|
||||
g, ok := enc.RuneToGlyph(r)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return enc.GlyphToCharcode(g)
|
||||
}
|
||||
// decodeString16bit converts PDF encoded string to a Go unicode string using the encoder `enc`.
|
||||
// Each character will be decoded from two bytes.
|
||||
func decodeString16bit(enc TextEncoder, raw []byte) string {
|
||||
// bytes -> character codes -> runes
|
||||
runes := make([]rune, 0, len(raw)/2+len(raw)%2)
|
||||
|
||||
// doCharcodeToRune converts PDF character code `code` to a rune.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func doCharcodeToRune(enc TextEncoder, code CharCode) (rune, bool) {
|
||||
g, ok := enc.CharcodeToGlyph(code)
|
||||
if !ok {
|
||||
return 0, false
|
||||
for len(raw) > 0 {
|
||||
if len(raw) == 1 {
|
||||
raw = []byte{raw[0], 0}
|
||||
}
|
||||
// Each entry represented by 2 bytes.
|
||||
code := CharCode(binary.BigEndian.Uint16(raw[:]))
|
||||
raw = raw[2:]
|
||||
|
||||
r, ok := enc.CharcodeToRune(code)
|
||||
if !ok {
|
||||
common.Log.Debug("Failed to map charcode to rune. charcode=%#x", code)
|
||||
continue
|
||||
}
|
||||
runes = append(runes, r)
|
||||
}
|
||||
return enc.GlyphToRune(g)
|
||||
return string(runes)
|
||||
}
|
||||
|
@ -25,3 +25,33 @@ func TestGlypRune(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestRuneToGlyph checks for known glyph->rune mappings.
|
||||
func TestRuneToGlyph(t *testing.T) {
|
||||
runes := []rune("₂₃₄₅◊fl˝ˇ¾Ðí©ºªı„δ∂ℵ⌡×÷®Ï☎①➔➨")
|
||||
glyphs := []GlyphName{
|
||||
"twoinferior", "threeinferior", "fourinferior", "fiveinferior",
|
||||
"lozenge", "fl", "hungarumlaut", "caron",
|
||||
"threequarters", "Eth", "iacute", "copyright",
|
||||
"ordmasculine", "ordfeminine", "dotlessi", "quotedblbase",
|
||||
"delta", "partialdiff", "aleph", "integralbt",
|
||||
"multiply", "divide", "registered", "Idieresis",
|
||||
"a4", "a120", "a160", "a178",
|
||||
}
|
||||
|
||||
if len(runes) != len(glyphs) {
|
||||
t.Fatalf("Bad test: runes=%d glyphs=%d", len(runes), len(glyphs))
|
||||
}
|
||||
for i, glyph := range glyphs {
|
||||
t.Run(string(glyph), func(t *testing.T) {
|
||||
expected := runes[i]
|
||||
r, ok := GlyphToRune(glyph)
|
||||
if !ok {
|
||||
t.Fatalf("no glyph %q", glyph)
|
||||
}
|
||||
if r != expected {
|
||||
t.Fatalf("Expected 0x%04x=%c. Got 0x%04x=%c", r, r, expected, expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -29,32 +29,14 @@ func (enc IdentityEncoder) String() string {
|
||||
return enc.baseName
|
||||
}
|
||||
|
||||
// Encode converts the Go unicode string `raw` to a PDF encoded string.
|
||||
func (enc IdentityEncoder) Encode(raw string) []byte {
|
||||
return encodeString16bit(enc, raw)
|
||||
// Encode converts the Go unicode string to a PDF encoded string.
|
||||
func (enc IdentityEncoder) Encode(str string) []byte {
|
||||
return encodeString16bit(enc, str)
|
||||
}
|
||||
|
||||
// CharcodeToGlyph returns the glyph name matching character code `code`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func (enc IdentityEncoder) CharcodeToGlyph(code CharCode) (GlyphName, bool) {
|
||||
r, found := enc.CharcodeToRune(code)
|
||||
if found && r == 0x20 {
|
||||
return "space", true
|
||||
}
|
||||
|
||||
// Returns "uniXXXX" format where XXXX is the code in hex format.
|
||||
glyph := GlyphName(fmt.Sprintf("uni%.4X", code))
|
||||
return glyph, true
|
||||
}
|
||||
|
||||
// GlyphToCharcode returns the character code matching glyph `glyph`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func (enc IdentityEncoder) GlyphToCharcode(glyph GlyphName) (CharCode, bool) {
|
||||
r, ok := enc.GlyphToRune(glyph)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return enc.RuneToCharcode(r)
|
||||
// Decode converts PDF encoded string to a Go unicode string.
|
||||
func (enc IdentityEncoder) Decode(raw []byte) string {
|
||||
return decodeString16bit(enc, raw)
|
||||
}
|
||||
|
||||
// RuneToCharcode converts rune `r` to a PDF character code.
|
||||
|
File diff suppressed because it is too large
Load Diff
121
pdf/internal/textencoding/simple_mac.go
Normal file
121
pdf/internal/textencoding/simple_mac.go
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.md', which is part of this source code package.
|
||||
*/
|
||||
|
||||
package textencoding
|
||||
|
||||
const (
|
||||
baseMacExpert = "MacExpertEncoding"
|
||||
baseMacRoman = "MacRomanEncoding"
|
||||
)
|
||||
|
||||
var (
|
||||
macExpert = newSimpleMapping(baseMacExpert, macExpertCharToRune)
|
||||
macRoman = newSimpleMapping(baseMacRoman, macRomanCharToRune)
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterSimpleEncoding(baseMacExpert, NewMacExpertEncoder)
|
||||
RegisterSimpleEncoding(baseMacRoman, NewMacRomanEncoder)
|
||||
}
|
||||
|
||||
// NewMacExpertEncoder returns a SimpleEncoder that implements MacExpertEncoding.
|
||||
func NewMacExpertEncoder() SimpleEncoder {
|
||||
return macExpert.NewEncoder()
|
||||
}
|
||||
|
||||
// NewMacRomanEncoder returns a SimpleEncoder that implements MacRomanEncoding.
|
||||
func NewMacRomanEncoder() SimpleEncoder {
|
||||
return macRoman.NewEncoder()
|
||||
}
|
||||
|
||||
var macExpertCharToRune = map[byte]rune{ // 165 entries
|
||||
0x20: ' ', 0x21: '\uf721', 0x22: '\uf6f8', 0x23: '\uf7a2', 0x24: '\uf724',
|
||||
0x25: '\uf6e4', 0x26: '\uf726', 0x27: '\uf7b4', 0x28: '⁽', 0x29: '⁾',
|
||||
0x2a: '‥', 0x2b: '․', 0x2c: ',', 0x2d: '-', 0x2e: '.',
|
||||
0x2f: '⁄', 0x30: '\uf730', 0x31: '\uf731', 0x32: '\uf732', 0x33: '\uf733',
|
||||
0x34: '\uf734', 0x35: '\uf735', 0x36: '\uf736', 0x37: '\uf737', 0x38: '\uf738',
|
||||
0x39: '\uf739', 0x3a: ':', 0x3b: ';', 0x3d: '\uf6de', 0x3f: '\uf73f',
|
||||
0x44: '\uf7f0', 0x47: '¼', 0x48: '½', 0x49: '¾', 0x4a: '⅛',
|
||||
0x4b: '⅜', 0x4c: '⅝', 0x4d: '⅞', 0x4e: '⅓', 0x4f: '⅔',
|
||||
0x56: 'ff', 0x57: 'fi', 0x58: 'fl', 0x59: 'ffi', 0x5a: 'ffl',
|
||||
0x5b: '₍', 0x5d: '₎', 0x5e: '\uf6f6', 0x5f: '\uf6e5', 0x60: '\uf760',
|
||||
0x61: '\uf761', 0x62: '\uf762', 0x63: '\uf763', 0x64: '\uf764', 0x65: '\uf765',
|
||||
0x66: '\uf766', 0x67: '\uf767', 0x68: '\uf768', 0x69: '\uf769', 0x6a: '\uf76a',
|
||||
0x6b: '\uf76b', 0x6c: '\uf76c', 0x6d: '\uf76d', 0x6e: '\uf76e', 0x6f: '\uf76f',
|
||||
0x70: '\uf770', 0x71: '\uf771', 0x72: '\uf772', 0x73: '\uf773', 0x74: '\uf774',
|
||||
0x75: '\uf775', 0x76: '\uf776', 0x77: '\uf777', 0x78: '\uf778', 0x79: '\uf779',
|
||||
0x7a: '\uf77a', 0x7b: '₡', 0x7c: '\uf6dc', 0x7d: '\uf6dd', 0x7e: '\uf6fe',
|
||||
0x81: '\uf6e9', 0x82: '\uf6e0', 0x87: '\uf7e1', 0x88: '\uf7e0', 0x89: '\uf7e2',
|
||||
0x8a: '\uf7e4', 0x8b: '\uf7e3', 0x8c: '\uf7e5', 0x8d: '\uf7e7', 0x8e: '\uf7e9',
|
||||
0x8f: '\uf7e8', 0x90: '\uf7ea', 0x91: '\uf7eb', 0x92: '\uf7ed', 0x93: '\uf7ec',
|
||||
0x94: '\uf7ee', 0x95: '\uf7ef', 0x96: '\uf7f1', 0x97: '\uf7f3', 0x98: '\uf7f2',
|
||||
0x99: '\uf7f4', 0x9a: '\uf7f6', 0x9b: '\uf7f5', 0x9c: '\uf7fa', 0x9d: '\uf7f9',
|
||||
0x9e: '\uf7fb', 0x9f: '\uf7fc', 0xa1: '⁸', 0xa2: '₄', 0xa3: '₃',
|
||||
0xa4: '₆', 0xa5: '₈', 0xa6: '₇', 0xa7: '\uf6fd', 0xa9: '\uf6df',
|
||||
0xaa: '₂', 0xac: '\uf7a8', 0xae: '\uf6f5', 0xaf: '\uf6f0', 0xb0: '₅',
|
||||
0xb2: '\uf6e1', 0xb3: '\uf6e7', 0xb4: '\uf7fd', 0xb6: '\uf6e3', 0xb9: '\uf7fe',
|
||||
0xbb: '₉', 0xbc: '₀', 0xbd: '\uf6ff', 0xbe: '\uf7e6', 0xbf: '\uf7f8',
|
||||
0xc0: '\uf7bf', 0xc1: '₁', 0xc2: '\uf6f9', 0xc9: '\uf7b8', 0xcf: '\uf6fa',
|
||||
0xd0: '‒', 0xd1: '\uf6e6', 0xd6: '\uf7a1', 0xd8: '\uf7ff', 0xda: '¹',
|
||||
0xdb: '²', 0xdc: '³', 0xdd: '⁴', 0xde: '⁵', 0xdf: '⁶',
|
||||
0xe0: '⁷', 0xe1: '⁹', 0xe2: '⁰', 0xe4: '\uf6ec', 0xe5: '\uf6f1',
|
||||
0xe6: '\uf6f3', 0xe9: '\uf6ed', 0xea: '\uf6f2', 0xeb: '\uf6eb', 0xf1: '\uf6ee',
|
||||
0xf2: '\uf6fb', 0xf3: '\uf6f4', 0xf4: '\uf7af', 0xf5: '\uf6ea', 0xf6: 'ⁿ',
|
||||
0xf7: '\uf6ef', 0xf8: '\uf6e2', 0xf9: '\uf6e8', 0xfa: '\uf6f7', 0xfb: '\uf6fc',
|
||||
}
|
||||
|
||||
var macRomanCharToRune = map[byte]rune{ // 255 entries
|
||||
0x1: '\x01', 0x2: '\x02', 0x3: '\x03', 0x4: '\x04', 0x5: '\x05',
|
||||
0x6: '\x06', 0x7: '\a', 0x8: '\b', 0x9: '\t', 0xa: '\n',
|
||||
0xb: '\v', 0xc: '\f', 0xd: '\r', 0xe: '\x0e', 0xf: '\x0f',
|
||||
0x10: '\x10', 0x11: '\x11', 0x12: '\x12', 0x13: '\x13', 0x14: '\x14',
|
||||
0x15: '\x15', 0x16: '\x16', 0x17: '\x17', 0x18: '\x18', 0x19: '\x19',
|
||||
0x1a: '\x1a', 0x1b: '\x1b', 0x1c: '\x1c', 0x1d: '\x1d', 0x1e: '\x1e',
|
||||
0x1f: '\x1f', 0x20: ' ', 0x21: '!', 0x22: '"', 0x23: '#',
|
||||
0x24: '$', 0x25: '%', 0x26: '&', 0x27: '\'', 0x28: '(',
|
||||
0x29: ')', 0x2a: '*', 0x2b: '+', 0x2c: ',', 0x2d: '-',
|
||||
0x2e: '.', 0x2f: '/', 0x30: '0', 0x31: '1', 0x32: '2',
|
||||
0x33: '3', 0x34: '4', 0x35: '5', 0x36: '6', 0x37: '7',
|
||||
0x38: '8', 0x39: '9', 0x3a: ':', 0x3b: ';', 0x3c: '<',
|
||||
0x3d: '=', 0x3e: '>', 0x3f: '?', 0x40: '@', 0x41: 'A',
|
||||
0x42: 'B', 0x43: 'C', 0x44: 'D', 0x45: 'E', 0x46: 'F',
|
||||
0x47: 'G', 0x48: 'H', 0x49: 'I', 0x4a: 'J', 0x4b: 'K',
|
||||
0x4c: 'L', 0x4d: 'M', 0x4e: 'N', 0x4f: 'O', 0x50: 'P',
|
||||
0x51: 'Q', 0x52: 'R', 0x53: 'S', 0x54: 'T', 0x55: 'U',
|
||||
0x56: 'V', 0x57: 'W', 0x58: 'X', 0x59: 'Y', 0x5a: 'Z',
|
||||
0x5b: '[', 0x5c: '\\', 0x5d: ']', 0x5e: '^', 0x5f: '_',
|
||||
0x60: '`', 0x61: 'a', 0x62: 'b', 0x63: 'c', 0x64: 'd',
|
||||
0x65: 'e', 0x66: 'f', 0x67: 'g', 0x68: 'h', 0x69: 'i',
|
||||
0x6a: 'j', 0x6b: 'k', 0x6c: 'l', 0x6d: 'm', 0x6e: 'n',
|
||||
0x6f: 'o', 0x70: 'p', 0x71: 'q', 0x72: 'r', 0x73: 's',
|
||||
0x74: 't', 0x75: 'u', 0x76: 'v', 0x77: 'w', 0x78: 'x',
|
||||
0x79: 'y', 0x7a: 'z', 0x7b: '{', 0x7c: '|', 0x7d: '}',
|
||||
0x7e: '~', 0x7f: '\u007f', 0x80: 'Ä', 0x81: 'Å', 0x82: 'Ç',
|
||||
0x83: 'É', 0x84: 'Ñ', 0x85: 'Ö', 0x86: 'Ü', 0x87: 'á',
|
||||
0x88: 'à', 0x89: 'â', 0x8a: 'ä', 0x8b: 'ã', 0x8c: 'å',
|
||||
0x8d: 'ç', 0x8e: 'é', 0x8f: 'è', 0x90: 'ê', 0x91: 'ë',
|
||||
0x92: 'í', 0x93: 'ì', 0x94: 'î', 0x95: 'ï', 0x96: 'ñ',
|
||||
0x97: 'ó', 0x98: 'ò', 0x99: 'ô', 0x9a: 'ö', 0x9b: 'õ',
|
||||
0x9c: 'ú', 0x9d: 'ù', 0x9e: 'û', 0x9f: 'ü', 0xa0: '†',
|
||||
0xa1: '°', 0xa2: '¢', 0xa3: '£', 0xa4: '§', 0xa5: '•',
|
||||
0xa6: '¶', 0xa7: 'ß', 0xa8: '®', 0xa9: '©', 0xaa: '™',
|
||||
0xab: '´', 0xac: '¨', 0xad: '≠', 0xae: 'Æ', 0xaf: 'Ø',
|
||||
0xb0: '∞', 0xb1: '±', 0xb2: '≤', 0xb3: '≥', 0xb4: '¥',
|
||||
0xb5: 'µ', 0xb6: '∂', 0xb7: '∑', 0xb8: '∏', 0xb9: 'π',
|
||||
0xba: '∫', 0xbb: 'ª', 0xbc: 'º', 0xbd: 'Ω', 0xbe: 'æ',
|
||||
0xbf: 'ø', 0xc0: '¿', 0xc1: '¡', 0xc2: '¬', 0xc3: '√',
|
||||
0xc4: 'ƒ', 0xc5: '≈', 0xc6: '∆', 0xc7: '«', 0xc8: '»',
|
||||
0xc9: '…', 0xca: '\u00a0', 0xcb: 'À', 0xcc: 'Ã', 0xcd: 'Õ',
|
||||
0xce: 'Œ', 0xcf: 'œ', 0xd0: '–', 0xd1: '—', 0xd2: '“',
|
||||
0xd3: '”', 0xd4: '‘', 0xd5: '’', 0xd6: '÷', 0xd7: '◊',
|
||||
0xd8: 'ÿ', 0xd9: 'Ÿ', 0xda: '⁄', 0xdb: '€', 0xdc: '‹',
|
||||
0xdd: '›', 0xde: 'fi', 0xdf: 'fl', 0xe0: '‡', 0xe1: '·',
|
||||
0xe2: '‚', 0xe3: '„', 0xe4: '‰', 0xe5: 'Â', 0xe6: 'Ê',
|
||||
0xe7: 'Á', 0xe8: 'Ë', 0xe9: 'È', 0xea: 'Í', 0xeb: 'Î',
|
||||
0xec: 'Ï', 0xed: 'Ì', 0xee: 'Ó', 0xef: 'Ô', 0xf0: '\uf8ff',
|
||||
0xf1: 'Ò', 0xf2: 'Ú', 0xf3: 'Û', 0xf4: 'Ù', 0xf5: 'ı',
|
||||
0xf6: 'ˆ', 0xf7: '˜', 0xf8: '¯', 0xf9: '˘', 0xfa: '˙',
|
||||
0xfb: '˚', 0xfc: '¸', 0xfd: '˝', 0xfe: '˛', 0xff: 'ˇ',
|
||||
}
|
126
pdf/internal/textencoding/simple_other.go
Normal file
126
pdf/internal/textencoding/simple_other.go
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.md', which is part of this source code package.
|
||||
*/
|
||||
|
||||
package textencoding
|
||||
|
||||
const (
|
||||
baseSymbol = "SymbolEncoding"
|
||||
baseZapfDingbats = "ZapfDingbatsEncoding"
|
||||
)
|
||||
|
||||
var (
|
||||
symbol = newSimpleMapping(baseSymbol, symbolCharToRune)
|
||||
zapfDingbats = newSimpleMapping(baseZapfDingbats, zapfDingbatsCharToRune)
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterSimpleEncoding(baseSymbol, NewSymbolEncoder)
|
||||
RegisterSimpleEncoding(baseZapfDingbats, NewZapfDingbatsEncoder)
|
||||
}
|
||||
|
||||
// NewSymbolEncoder returns a SimpleEncoder that implements SymbolEncoding.
|
||||
func NewSymbolEncoder() SimpleEncoder {
|
||||
return symbol.NewEncoder()
|
||||
}
|
||||
|
||||
// NewZapfDingbatsEncoder returns a SimpleEncoder that implements ZapfDingbatsEncoding.
|
||||
func NewZapfDingbatsEncoder() SimpleEncoder {
|
||||
return zapfDingbats.NewEncoder()
|
||||
}
|
||||
|
||||
var symbolCharToRune = map[byte]rune{ // 189 entries
|
||||
0x20: ' ', 0x21: '!', 0x22: '∀', 0x23: '#',
|
||||
0x24: '∃', 0x25: '%', 0x26: '&', 0x27: '∋',
|
||||
0x28: '(', 0x29: ')', 0x2a: '∗', 0x2b: '+',
|
||||
0x2c: ',', 0x2d: '−', 0x2e: '.', 0x2f: '/',
|
||||
0x30: '0', 0x31: '1', 0x32: '2', 0x33: '3',
|
||||
0x34: '4', 0x35: '5', 0x36: '6', 0x37: '7',
|
||||
0x38: '8', 0x39: '9', 0x3a: ':', 0x3b: ';',
|
||||
0x3c: '<', 0x3d: '=', 0x3e: '>', 0x3f: '?',
|
||||
0x40: '≅', 0x41: 'Α', 0x42: 'Β', 0x43: 'Χ',
|
||||
0x44: '∆', 0x45: 'Ε', 0x46: 'Φ', 0x47: 'Γ',
|
||||
0x48: 'Η', 0x49: 'Ι', 0x4a: 'ϑ', 0x4b: 'Κ',
|
||||
0x4c: 'Λ', 0x4d: 'Μ', 0x4e: 'Ν', 0x4f: 'Ο',
|
||||
0x50: 'Π', 0x51: 'Θ', 0x52: 'Ρ', 0x53: 'Σ',
|
||||
0x54: 'Τ', 0x55: 'Υ', 0x56: 'ς', 0x57: 'Ω',
|
||||
0x58: 'Ξ', 0x59: 'Ψ', 0x5a: 'Ζ', 0x5b: '[',
|
||||
0x5c: '∴', 0x5d: ']', 0x5e: '⊥', 0x5f: '_',
|
||||
0x60: '\uf8e5', 0x61: 'α', 0x62: 'β', 0x63: 'χ',
|
||||
0x64: 'δ', 0x65: 'ε', 0x66: 'φ', 0x67: 'γ',
|
||||
0x68: 'η', 0x69: 'ι', 0x6a: 'ϕ', 0x6b: 'κ',
|
||||
0x6c: 'λ', 0x6d: 'µ', 0x6e: 'ν', 0x6f: 'ο',
|
||||
0x70: 'π', 0x71: 'θ', 0x72: 'ρ', 0x73: 'σ',
|
||||
0x74: 'τ', 0x75: 'υ', 0x76: 'ϖ', 0x77: 'ω',
|
||||
0x78: 'ξ', 0x79: 'ψ', 0x7a: 'ζ', 0x7b: '{',
|
||||
0x7c: '|', 0x7d: '}', 0x7e: '∼', 0xa0: '€',
|
||||
0xa1: 'ϒ', 0xa2: '′', 0xa3: '≤', 0xa4: '⁄',
|
||||
0xa5: '∞', 0xa6: 'ƒ', 0xa7: '♣', 0xa8: '♦',
|
||||
0xa9: '♥', 0xaa: '♠', 0xab: '↔', 0xac: '←',
|
||||
0xad: '↑', 0xae: '→', 0xaf: '↓', 0xb0: '°',
|
||||
0xb1: '±', 0xb2: '″', 0xb3: '≥', 0xb4: '×',
|
||||
0xb5: '∝', 0xb6: '∂', 0xb7: '•', 0xb8: '÷',
|
||||
0xb9: '≠', 0xba: '≡', 0xbb: '≈', 0xbc: '…',
|
||||
0xbd: '\uf8e6', 0xbe: '\uf8e7', 0xbf: '↵', 0xc0: 'ℵ',
|
||||
0xc1: 'ℑ', 0xc2: 'ℜ', 0xc3: '℘', 0xc4: '⊗',
|
||||
0xc5: '⊕', 0xc6: '∅', 0xc7: '∩', 0xc8: '∪',
|
||||
0xc9: '⊃', 0xca: '⊇', 0xcb: '⊄', 0xcc: '⊂',
|
||||
0xcd: '⊆', 0xce: '∈', 0xcf: '∉', 0xd0: '∠',
|
||||
0xd1: '∇', 0xd2: '\uf6da', 0xd3: '\uf6d9', 0xd4: '\uf6db',
|
||||
0xd5: '∏', 0xd6: '√', 0xd7: '⋅', 0xd8: '¬',
|
||||
0xd9: '∧', 0xda: '∨', 0xdb: '⇔', 0xdc: '⇐',
|
||||
0xdd: '⇑', 0xde: '⇒', 0xdf: '⇓', 0xe0: '◊',
|
||||
0xe1: '〈', 0xe2: '\uf8e8', 0xe3: '\uf8e9', 0xe4: '\uf8ea',
|
||||
0xe5: '∑', 0xe6: '\uf8eb', 0xe7: '\uf8ec', 0xe8: '\uf8ed',
|
||||
0xe9: '\uf8ee', 0xea: '\uf8ef', 0xeb: '\uf8f0', 0xec: '\uf8f1',
|
||||
0xed: '\uf8f2', 0xee: '\uf8f3', 0xef: '\uf8f4', 0xf1: '〉',
|
||||
0xf2: '∫', 0xf3: '⌠', 0xf4: '\uf8f5', 0xf5: '⌡',
|
||||
0xf6: '\uf8f6', 0xf7: '\uf8f7', 0xf8: '\uf8f8', 0xf9: '\uf8f9',
|
||||
0xfa: '\uf8fa', 0xfb: '\uf8fb', 0xfc: '\uf8fc', 0xfd: '\uf8fd',
|
||||
0xfe: '\uf8fe',
|
||||
}
|
||||
|
||||
var zapfDingbatsCharToRune = map[byte]rune{ // 202 entries
|
||||
0x20: ' ', 0x21: '✁', 0x22: '✂', 0x23: '✃', 0x24: '✄',
|
||||
0x25: '☎', 0x26: '✆', 0x27: '✇', 0x28: '✈', 0x29: '✉',
|
||||
0x2a: '☛', 0x2b: '☞', 0x2c: '✌', 0x2d: '✍', 0x2e: '✎',
|
||||
0x2f: '✏', 0x30: '✐', 0x31: '✑', 0x32: '✒', 0x33: '✓',
|
||||
0x34: '✔', 0x35: '✕', 0x36: '✖', 0x37: '✗', 0x38: '✘',
|
||||
0x39: '✙', 0x3a: '✚', 0x3b: '✛', 0x3c: '✜', 0x3d: '✝',
|
||||
0x3e: '✞', 0x3f: '✟', 0x40: '✠', 0x41: '✡', 0x42: '✢',
|
||||
0x43: '✣', 0x44: '✤', 0x45: '✥', 0x46: '✦', 0x47: '✧',
|
||||
0x48: '★', 0x49: '✩', 0x4a: '✪', 0x4b: '✫', 0x4c: '✬',
|
||||
0x4d: '✭', 0x4e: '✮', 0x4f: '✯', 0x50: '✰', 0x51: '✱',
|
||||
0x52: '✲', 0x53: '✳', 0x54: '✴', 0x55: '✵', 0x56: '✶',
|
||||
0x57: '✷', 0x58: '✸', 0x59: '✹', 0x5a: '✺', 0x5b: '✻',
|
||||
0x5c: '✼', 0x5d: '✽', 0x5e: '✾', 0x5f: '✿', 0x60: '❀',
|
||||
0x61: '❁', 0x62: '❂', 0x63: '❃', 0x64: '❄', 0x65: '❅',
|
||||
0x66: '❆', 0x67: '❇', 0x68: '❈', 0x69: '❉', 0x6a: '❊',
|
||||
0x6b: '❋', 0x6c: '●', 0x6d: '❍', 0x6e: '■', 0x6f: '❏',
|
||||
0x70: '❐', 0x71: '❑', 0x72: '❒', 0x73: '▲', 0x74: '▼',
|
||||
0x75: '◆', 0x76: '❖', 0x77: '◗', 0x78: '❘', 0x79: '❙',
|
||||
0x7a: '❚', 0x7b: '❛', 0x7c: '❜', 0x7d: '❝', 0x7e: '❞',
|
||||
0x80: '\uf8d7', 0x81: '\uf8d8', 0x82: '\uf8d9', 0x83: '\uf8da', 0x84: '\uf8db',
|
||||
0x85: '\uf8dc', 0x86: '\uf8dd', 0x87: '\uf8de', 0x88: '\uf8df', 0x89: '\uf8e0',
|
||||
0x8a: '\uf8e1', 0x8b: '\uf8e2', 0x8c: '\uf8e3', 0x8d: '\uf8e4', 0xa1: '❡',
|
||||
0xa2: '❢', 0xa3: '❣', 0xa4: '❤', 0xa5: '❥', 0xa6: '❦',
|
||||
0xa7: '❧', 0xa8: '♣', 0xa9: '♦', 0xaa: '♥', 0xab: '♠',
|
||||
0xac: '①', 0xad: '②', 0xae: '③', 0xaf: '④', 0xb0: '⑤',
|
||||
0xb1: '⑥', 0xb2: '⑦', 0xb3: '⑧', 0xb4: '⑨', 0xb5: '⑩',
|
||||
0xb6: '❶', 0xb7: '❷', 0xb8: '❸', 0xb9: '❹', 0xba: '❺',
|
||||
0xbb: '❻', 0xbc: '❼', 0xbd: '❽', 0xbe: '❾', 0xbf: '❿',
|
||||
0xc0: '➀', 0xc1: '➁', 0xc2: '➂', 0xc3: '➃', 0xc4: '➄',
|
||||
0xc5: '➅', 0xc6: '➆', 0xc7: '➇', 0xc8: '➈', 0xc9: '➉',
|
||||
0xca: '➊', 0xcb: '➋', 0xcc: '➌', 0xcd: '➍', 0xce: '➎',
|
||||
0xcf: '➏', 0xd0: '➐', 0xd1: '➑', 0xd2: '➒', 0xd3: '➓',
|
||||
0xd4: '➔', 0xd5: '→', 0xd6: '↔', 0xd7: '↕', 0xd8: '➘',
|
||||
0xd9: '➙', 0xda: '➚', 0xdb: '➛', 0xdc: '➜', 0xdd: '➝',
|
||||
0xde: '➞', 0xdf: '➟', 0xe0: '➠', 0xe1: '➡', 0xe2: '➢',
|
||||
0xe3: '➣', 0xe4: '➤', 0xe5: '➥', 0xe6: '➦', 0xe7: '➧',
|
||||
0xe8: '➨', 0xe9: '➩', 0xea: '➪', 0xeb: '➫', 0xec: '➬',
|
||||
0xed: '➭', 0xee: '➮', 0xef: '➯', 0xf1: '➱', 0xf2: '➲',
|
||||
0xf3: '➳', 0xf4: '➴', 0xf5: '➵', 0xf6: '➶', 0xf7: '➷',
|
||||
0xf8: '➸', 0xf9: '➹', 0xfa: '➺', 0xfb: '➻', 0xfc: '➼',
|
||||
0xfd: '➽', 0xfe: '➾',
|
||||
}
|
118
pdf/internal/textencoding/simple_pdf.go
Normal file
118
pdf/internal/textencoding/simple_pdf.go
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.md', which is part of this source code package.
|
||||
*/
|
||||
|
||||
package textencoding
|
||||
|
||||
const (
|
||||
basePdfDoc = "PdfDocEncoding"
|
||||
baseStandard = "StandardEncoding"
|
||||
)
|
||||
|
||||
var (
|
||||
pdfDoc = newSimpleMapping(basePdfDoc, pdfDocCharToRune)
|
||||
standard = newSimpleMapping(baseStandard, standardCharToRune)
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterSimpleEncoding(basePdfDoc, NewPdfDocEncoder)
|
||||
RegisterSimpleEncoding(baseStandard, NewStandardEncoder)
|
||||
}
|
||||
|
||||
// NewPdfDocEncoder returns a SimpleEncoder that implements PdfDocEncoding.
|
||||
func NewPdfDocEncoder() SimpleEncoder {
|
||||
return pdfDoc.NewEncoder()
|
||||
}
|
||||
|
||||
// NewStandardEncoder returns a SimpleEncoder that implements StandardEncoding.
|
||||
func NewStandardEncoder() SimpleEncoder {
|
||||
return standard.NewEncoder()
|
||||
}
|
||||
|
||||
var pdfDocCharToRune = map[byte]rune{ // 252 entries
|
||||
0x1: '\x01', 0x2: '\x02', 0x3: '\x03', 0x4: '\x04', 0x5: '\x05',
|
||||
0x6: '\x06', 0x7: '\a', 0x8: '\b', 0x9: '\t', 0xa: '\n',
|
||||
0xb: '\v', 0xc: '\f', 0xd: '\r', 0xe: '\x0e', 0xf: '\x0f',
|
||||
0x10: '\x10', 0x11: '\x11', 0x12: '\x12', 0x13: '\x13', 0x14: '\x14',
|
||||
0x15: '\x15', 0x16: '\x17', 0x17: '\x17', 0x18: '˘', 0x19: 'ˇ',
|
||||
0x1a: 'ˆ', 0x1b: '˙', 0x1c: '˝', 0x1d: '˛', 0x1e: '˚',
|
||||
0x1f: '˜', 0x20: ' ', 0x21: '!', 0x22: '"', 0x23: '#',
|
||||
0x24: '$', 0x25: '%', 0x26: '&', 0x27: '\'', 0x28: '(',
|
||||
0x29: ')', 0x2a: '*', 0x2b: '+', 0x2c: ',', 0x2d: '-',
|
||||
0x2e: '.', 0x2f: '/', 0x30: '0', 0x31: '1', 0x32: '2',
|
||||
0x33: '3', 0x34: '4', 0x35: '5', 0x36: '6', 0x37: '7',
|
||||
0x38: '8', 0x39: '9', 0x3a: ':', 0x3b: ';', 0x3c: '<',
|
||||
0x3d: '=', 0x3e: '>', 0x3f: '?', 0x40: '@', 0x41: 'A',
|
||||
0x42: 'B', 0x43: 'C', 0x44: 'D', 0x45: 'E', 0x46: 'F',
|
||||
0x47: 'G', 0x48: 'H', 0x49: 'I', 0x4a: 'J', 0x4b: 'K',
|
||||
0x4c: 'L', 0x4d: 'M', 0x4e: 'N', 0x4f: 'O', 0x50: 'P',
|
||||
0x51: 'Q', 0x52: 'R', 0x53: 'S', 0x54: 'T', 0x55: 'U',
|
||||
0x56: 'V', 0x57: 'W', 0x58: 'X', 0x59: 'Y', 0x5a: 'Z',
|
||||
0x5b: '[', 0x5c: '\\', 0x5d: ']', 0x5e: '^', 0x5f: '_',
|
||||
0x60: '`', 0x61: 'a', 0x62: 'b', 0x63: 'c', 0x64: 'd',
|
||||
0x65: 'e', 0x66: 'f', 0x67: 'g', 0x68: 'h', 0x69: 'i',
|
||||
0x6a: 'j', 0x6b: 'k', 0x6c: 'l', 0x6d: 'm', 0x6e: 'n',
|
||||
0x6f: 'o', 0x70: 'p', 0x71: 'q', 0x72: 'r', 0x73: 's',
|
||||
0x74: 't', 0x75: 'u', 0x76: 'v', 0x77: 'w', 0x78: 'x',
|
||||
0x79: 'y', 0x7a: 'z', 0x7b: '{', 0x7c: '|', 0x7d: '}',
|
||||
0x7e: '~', 0x80: '•', 0x81: '†', 0x82: '‡', 0x83: '…',
|
||||
0x84: '—', 0x85: '–', 0x86: 'ƒ', 0x87: '⁄', 0x88: '‹',
|
||||
0x89: '›', 0x8a: '−', 0x8b: '‰', 0x8c: '„', 0x8d: '“',
|
||||
0x8e: '”', 0x8f: '‘', 0x90: '’', 0x91: '‚', 0x92: '™',
|
||||
0x93: 'fi', 0x94: 'fl', 0x95: 'Ł', 0x96: 'Œ', 0x97: 'Š',
|
||||
0x98: 'Ÿ', 0x99: 'Ž', 0x9a: 'ı', 0x9b: 'ł', 0x9c: 'œ',
|
||||
0x9d: 'š', 0x9e: 'ž', 0xa0: '€', 0xa1: '¡', 0xa2: '¢',
|
||||
0xa3: '£', 0xa4: '¤', 0xa5: '¥', 0xa6: '¦', 0xa7: '§',
|
||||
0xa8: '¨', 0xa9: '©', 0xaa: 'ª', 0xab: '«', 0xac: '¬',
|
||||
0xae: '®', 0xaf: '¯', 0xb0: '°', 0xb1: '±', 0xb2: '²',
|
||||
0xb3: '³', 0xb4: '´', 0xb5: 'µ', 0xb6: '¶', 0xb7: '·',
|
||||
0xb8: '¸', 0xb9: '¹', 0xba: 'º', 0xbb: '»', 0xbc: '¼',
|
||||
0xbd: '½', 0xbe: '¾', 0xbf: '¿', 0xc0: 'À', 0xc1: 'Á',
|
||||
0xc2: 'Â', 0xc3: 'Ã', 0xc4: 'Ä', 0xc5: 'Å', 0xc6: 'Æ',
|
||||
0xc7: 'Ç', 0xc8: 'È', 0xc9: 'É', 0xca: 'Ê', 0xcb: 'Ë',
|
||||
0xcc: 'Ì', 0xcd: 'Í', 0xce: 'Î', 0xcf: 'Ï', 0xd0: 'Ð',
|
||||
0xd1: 'Ñ', 0xd2: 'Ò', 0xd3: 'Ó', 0xd4: 'Ô', 0xd5: 'Õ',
|
||||
0xd6: 'Ö', 0xd7: '×', 0xd8: 'Ø', 0xd9: 'Ù', 0xda: 'Ú',
|
||||
0xdb: 'Û', 0xdc: 'Ü', 0xdd: 'Ý', 0xde: 'Þ', 0xdf: 'ß',
|
||||
0xe0: 'à', 0xe1: 'á', 0xe2: 'â', 0xe3: 'ã', 0xe4: 'ä',
|
||||
0xe5: 'å', 0xe6: 'æ', 0xe7: 'ç', 0xe8: 'è', 0xe9: 'é',
|
||||
0xea: 'ê', 0xeb: 'ë', 0xec: 'ì', 0xed: 'í', 0xee: 'î',
|
||||
0xef: 'ï', 0xf0: 'ð', 0xf1: 'ñ', 0xf2: 'ò', 0xf3: 'ó',
|
||||
0xf4: 'ô', 0xf5: 'õ', 0xf6: 'ö', 0xf7: '÷', 0xf8: 'ø',
|
||||
0xf9: 'ù', 0xfa: 'ú', 0xfb: 'û', 0xfc: 'ü', 0xfd: 'ý',
|
||||
0xfe: 'þ', 0xff: 'ÿ',
|
||||
}
|
||||
|
||||
var standardCharToRune = map[byte]rune{ // 149 entries
|
||||
0x20: ' ', 0x21: '!', 0x22: '"', 0x23: '#', 0x24: '$',
|
||||
0x25: '%', 0x26: '&', 0x27: '’', 0x28: '(', 0x29: ')',
|
||||
0x2a: '*', 0x2b: '+', 0x2c: ',', 0x2d: '-', 0x2e: '.',
|
||||
0x2f: '/', 0x30: '0', 0x31: '1', 0x32: '2', 0x33: '3',
|
||||
0x34: '4', 0x35: '5', 0x36: '6', 0x37: '7', 0x38: '8',
|
||||
0x39: '9', 0x3a: ':', 0x3b: ';', 0x3c: '<', 0x3d: '=',
|
||||
0x3e: '>', 0x3f: '?', 0x40: '@', 0x41: 'A', 0x42: 'B',
|
||||
0x43: 'C', 0x44: 'D', 0x45: 'E', 0x46: 'F', 0x47: 'G',
|
||||
0x48: 'H', 0x49: 'I', 0x4a: 'J', 0x4b: 'K', 0x4c: 'L',
|
||||
0x4d: 'M', 0x4e: 'N', 0x4f: 'O', 0x50: 'P', 0x51: 'Q',
|
||||
0x52: 'R', 0x53: 'S', 0x54: 'T', 0x55: 'U', 0x56: 'V',
|
||||
0x57: 'W', 0x58: 'X', 0x59: 'Y', 0x5a: 'Z', 0x5b: '[',
|
||||
0x5c: '\\', 0x5d: ']', 0x5e: '^', 0x5f: '_', 0x60: '`',
|
||||
0x61: 'a', 0x62: 'b', 0x63: 'c', 0x64: 'd', 0x65: 'e',
|
||||
0x66: 'f', 0x67: 'g', 0x68: 'h', 0x69: 'i', 0x6a: 'j',
|
||||
0x6b: 'k', 0x6c: 'l', 0x6d: 'm', 0x6e: 'n', 0x6f: 'o',
|
||||
0x70: 'p', 0x71: 'q', 0x72: 'r', 0x73: 's', 0x74: 't',
|
||||
0x75: 'u', 0x76: 'v', 0x77: 'w', 0x78: 'x', 0x79: 'y',
|
||||
0x7a: 'z', 0x7b: '{', 0x7c: '|', 0x7d: '}', 0x7e: '~',
|
||||
0xa1: '¡', 0xa2: '¢', 0xa3: '£', 0xa4: '⁄', 0xa5: '¥',
|
||||
0xa6: 'ƒ', 0xa7: '§', 0xa8: '¤', 0xa9: '\'', 0xaa: '“',
|
||||
0xab: '«', 0xac: '‹', 0xad: '›', 0xae: 'fi', 0xaf: 'fl',
|
||||
0xb1: '–', 0xb2: '†', 0xb3: '‡', 0xb4: '·', 0xb6: '¶',
|
||||
0xb7: '•', 0xb8: '‚', 0xb9: '„', 0xba: '”', 0xbb: '»',
|
||||
0xbc: '…', 0xbd: '‰', 0xbf: '¿', 0xc1: '`', 0xc2: '´',
|
||||
0xc3: 'ˆ', 0xc4: '˜', 0xc5: '¯', 0xc6: '˘', 0xc7: '˙',
|
||||
0xc8: '¨', 0xca: '˚', 0xcb: '¸', 0xcc: '˝', 0xcd: '˛',
|
||||
0xce: 'ˇ', 0xcf: '—', 0xe0: 'Æ', 0xe2: 'ª', 0xe7: 'Ł',
|
||||
0xe8: 'Ø', 0xe9: 'Œ', 0xea: 'º', 0xf0: 'æ', 0xf5: 'ı',
|
||||
0xf7: 'ł', 0xf8: 'ø', 0xf9: 'œ', 0xfa: 'ß',
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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 (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
)
|
||||
|
||||
// This test covers all the standard encodings in simple.go
|
||||
|
||||
func init() {
|
||||
common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
|
||||
}
|
||||
|
||||
// TestBasicEncodings checks for known glyph->rune mappings in the standard encodings.
|
||||
func TestBasicEncodings(t *testing.T) {
|
||||
for _, test := range testCases {
|
||||
test.check(t)
|
||||
}
|
||||
}
|
||||
|
||||
var testCases = []encodingTest{
|
||||
{"MacExpertEncoding", "₂₃₄₅", []GlyphName{"twoinferior", "threeinferior", "fourinferior", "fiveinferior"}},
|
||||
{"MacRomanEncoding", "◊fl˝ˇ", []GlyphName{"lozenge", "fl", "hungarumlaut", "caron"}},
|
||||
{"PdfDocEncoding", "¾Ðí©", []GlyphName{"threequarters", "Eth", "iacute", "copyright"}},
|
||||
{"StandardEncoding", "ºªı„", []GlyphName{"ordmasculine", "ordfeminine", "dotlessi", "quotedblbase"}},
|
||||
{"SymbolEncoding", "δ∂ℵ⌡", []GlyphName{"delta", "partialdiff", "aleph", "integralbt"}},
|
||||
{"WinAnsiEncoding", "×÷®Ï", []GlyphName{"multiply", "divide", "registered", "Idieresis"}},
|
||||
{"ZapfDingbatsEncoding", "☎①➔➨", []GlyphName{"a4", "a120", "a160", "a178"}},
|
||||
}
|
||||
|
||||
type encodingTest struct {
|
||||
encoding string
|
||||
runes string
|
||||
glyphs []GlyphName
|
||||
}
|
||||
|
||||
func (f *encodingTest) String() string {
|
||||
return fmt.Sprintf("ENCODING_TEST{%#q}", f.encoding)
|
||||
}
|
||||
|
||||
func (f *encodingTest) check(t *testing.T) {
|
||||
common.Log.Debug("encodingTest: %s", f)
|
||||
runes := []rune(f.runes)
|
||||
if len(runes) != len(f.glyphs) {
|
||||
t.Fatalf("Bad test %s runes=%d glyphs=%d", f, len(runes), len(f.glyphs))
|
||||
}
|
||||
enc, err := NewSimpleTextEncoder(f.encoding, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("NewSimpleTextEncoder(%#q) failed. err=%v", f.encoding, err)
|
||||
}
|
||||
for i, glyph := range f.glyphs {
|
||||
expected := runes[i]
|
||||
r, ok := enc.GlyphToRune(glyph)
|
||||
if !ok {
|
||||
t.Fatalf("Encoding %#q has no glyph %q", f.encoding, glyph)
|
||||
}
|
||||
if r != expected {
|
||||
t.Fatalf("%s: Expected 0x%04x=%c. Got 0x%04x=%c", f, r, r, expected, expected)
|
||||
}
|
||||
}
|
||||
}
|
69
pdf/internal/textencoding/simple_winansi.go
Normal file
69
pdf/internal/textencoding/simple_winansi.go
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.md', which is part of this source code package.
|
||||
*/
|
||||
|
||||
package textencoding
|
||||
|
||||
const baseWinAnsi = "WinAnsiEncoding"
|
||||
|
||||
var (
|
||||
winAnsi = newSimpleMapping(baseWinAnsi, winAnsiCharToRune)
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterSimpleEncoding(baseWinAnsi, NewWinAnsiEncoder)
|
||||
}
|
||||
|
||||
// NewWinAnsiEncoder returns a simpleEncoder that implements WinAnsiEncoding.
|
||||
func NewWinAnsiEncoder() SimpleEncoder {
|
||||
return winAnsi.NewEncoder()
|
||||
}
|
||||
|
||||
var winAnsiCharToRune = map[byte]rune{ // 224 entries
|
||||
0x20: ' ', 0x21: '!', 0x22: '"', 0x23: '#', 0x24: '$',
|
||||
0x25: '%', 0x26: '&', 0x27: '\'', 0x28: '(', 0x29: ')',
|
||||
0x2a: '*', 0x2b: '+', 0x2c: ',', 0x2d: '-', 0x2e: '.',
|
||||
0x2f: '/', 0x30: '0', 0x31: '1', 0x32: '2', 0x33: '3',
|
||||
0x34: '4', 0x35: '5', 0x36: '6', 0x37: '7', 0x38: '8',
|
||||
0x39: '9', 0x3a: ':', 0x3b: ';', 0x3c: '<', 0x3d: '=',
|
||||
0x3e: '>', 0x3f: '?', 0x40: '@', 0x41: 'A', 0x42: 'B',
|
||||
0x43: 'C', 0x44: 'D', 0x45: 'E', 0x46: 'F', 0x47: 'G',
|
||||
0x48: 'H', 0x49: 'I', 0x4a: 'J', 0x4b: 'K', 0x4c: 'L',
|
||||
0x4d: 'M', 0x4e: 'N', 0x4f: 'O', 0x50: 'P', 0x51: 'Q',
|
||||
0x52: 'R', 0x53: 'S', 0x54: 'T', 0x55: 'U', 0x56: 'V',
|
||||
0x57: 'W', 0x58: 'X', 0x59: 'Y', 0x5a: 'Z', 0x5b: '[',
|
||||
0x5c: '\\', 0x5d: ']', 0x5e: '^', 0x5f: '_', 0x60: '`',
|
||||
0x61: 'a', 0x62: 'b', 0x63: 'c', 0x64: 'd', 0x65: 'e',
|
||||
0x66: 'f', 0x67: 'g', 0x68: 'h', 0x69: 'i', 0x6a: 'j',
|
||||
0x6b: 'k', 0x6c: 'l', 0x6d: 'm', 0x6e: 'n', 0x6f: 'o',
|
||||
0x70: 'p', 0x71: 'q', 0x72: 'r', 0x73: 's', 0x74: 't',
|
||||
0x75: 'u', 0x76: 'v', 0x77: 'w', 0x78: 'x', 0x79: 'y',
|
||||
0x7a: 'z', 0x7b: '{', 0x7c: '|', 0x7d: '}', 0x7e: '~',
|
||||
0x7f: '•', 0x80: '€', 0x81: '•', 0x82: '‚', 0x83: 'ƒ',
|
||||
0x84: '„', 0x85: '…', 0x86: '†', 0x87: '‡', 0x88: 'ˆ',
|
||||
0x89: '‰', 0x8a: 'Š', 0x8b: '‹', 0x8c: 'Œ', 0x8d: '•',
|
||||
0x8e: 'Ž', 0x8f: '•', 0x90: '•', 0x91: '‘', 0x92: '’',
|
||||
0x93: '“', 0x94: '”', 0x95: '•', 0x96: '–', 0x97: '—',
|
||||
0x98: '˜', 0x99: '™', 0x9a: 'š', 0x9b: '›', 0x9c: 'œ',
|
||||
0x9d: '•', 0x9e: 'ž', 0x9f: 'Ÿ', 0xa0: ' ', 0xa1: '¡',
|
||||
0xa2: '¢', 0xa3: '£', 0xa4: '¤', 0xa5: '¥', 0xa6: '¦',
|
||||
0xa7: '§', 0xa8: '¨', 0xa9: '©', 0xaa: 'ª', 0xab: '«',
|
||||
0xac: '¬', 0xad: '-', 0xae: '®', 0xaf: '¯', 0xb0: '°',
|
||||
0xb1: '±', 0xb2: '²', 0xb3: '³', 0xb4: '´', 0xb5: 'µ',
|
||||
0xb6: '¶', 0xb7: '·', 0xb8: '¸', 0xb9: '¹', 0xba: 'º',
|
||||
0xbb: '»', 0xbc: '¼', 0xbd: '½', 0xbe: '¾', 0xbf: '¿',
|
||||
0xc0: 'À', 0xc1: 'Á', 0xc2: 'Â', 0xc3: 'Ã', 0xc4: 'Ä',
|
||||
0xc5: 'Å', 0xc6: 'Æ', 0xc7: 'Ç', 0xc8: 'È', 0xc9: 'É',
|
||||
0xca: 'Ê', 0xcb: 'Ë', 0xcc: 'Ì', 0xcd: 'Í', 0xce: 'Î',
|
||||
0xcf: 'Ï', 0xd0: 'Ð', 0xd1: 'Ñ', 0xd2: 'Ò', 0xd3: 'Ó',
|
||||
0xd4: 'Ô', 0xd5: 'Õ', 0xd6: 'Ö', 0xd7: '×', 0xd8: 'Ø',
|
||||
0xd9: 'Ù', 0xda: 'Ú', 0xdb: 'Û', 0xdc: 'Ü', 0xdd: 'Ý',
|
||||
0xde: 'Þ', 0xdf: 'ß', 0xe0: 'à', 0xe1: 'á', 0xe2: 'â',
|
||||
0xe3: 'ã', 0xe4: 'ä', 0xe5: 'å', 0xe6: 'æ', 0xe7: 'ç',
|
||||
0xe8: 'è', 0xe9: 'é', 0xea: 'ê', 0xeb: 'ë', 0xec: 'ì',
|
||||
0xed: 'í', 0xee: 'î', 0xef: 'ï', 0xf0: 'ð', 0xf1: 'ñ',
|
||||
0xf2: 'ò', 0xf3: 'ó', 0xf4: 'ô', 0xf5: 'õ', 0xf6: 'ö',
|
||||
0xf7: '÷', 0xf8: 'ø', 0xf9: 'ù', 0xfa: 'ú', 0xfb: 'û',
|
||||
0xfc: 'ü', 0xfd: 'ý', 0xfe: 'þ', 0xff: 'ÿ',
|
||||
}
|
@ -8,15 +8,20 @@ package textencoding
|
||||
import "testing"
|
||||
|
||||
func TestWinAnsiEncoder(t *testing.T) {
|
||||
enc := NewWinAnsiTextEncoder()
|
||||
enc := NewWinAnsiEncoder()
|
||||
|
||||
glyph, found := enc.CharcodeToGlyph(32)
|
||||
if !found || glyph != "space" {
|
||||
t.Errorf("Glyph != space")
|
||||
r, found := enc.CharcodeToRune(32)
|
||||
if !found || r != ' ' {
|
||||
t.Errorf("rune != space")
|
||||
return
|
||||
}
|
||||
code, found := enc.RuneToCharcode('þ')
|
||||
if !found || code != 254 {
|
||||
t.Errorf("code != 254")
|
||||
return
|
||||
}
|
||||
|
||||
glyph, found = enc.RuneToGlyph('þ')
|
||||
glyph, found := RuneToGlyph('þ')
|
||||
if !found || glyph != "thorn" {
|
||||
t.Errorf("Glyph != thorn")
|
||||
return
|
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.md', which is part of this source code package.
|
||||
*/
|
||||
|
||||
package textencoding
|
||||
|
||||
// NewSymbolEncoder returns a SimpleEncoder that implements SymbolEncoding.
|
||||
func NewSymbolEncoder() *SimpleEncoder {
|
||||
enc, _ := NewSimpleTextEncoder("SymbolEncoding", nil)
|
||||
return enc
|
||||
}
|
@ -17,13 +17,14 @@ import (
|
||||
// GID is a glyph index.
|
||||
type GID uint16
|
||||
|
||||
// TODO(dennwc): should not mix Identity-H CMap and Encoding in the same object
|
||||
|
||||
// TrueTypeFontEncoder handles text encoding for composite TrueType fonts.
|
||||
// It performs mapping between character ids and glyph ids.
|
||||
// It has a preloaded rune (unicode code point) to glyph index map that has been loaded from a font.
|
||||
// Corresponds to Identity-H.
|
||||
// Corresponds to Identity-H CMap and Identity encoding.
|
||||
type TrueTypeFontEncoder struct {
|
||||
runeToGIDMap map[rune]GID
|
||||
cmap CMap
|
||||
}
|
||||
|
||||
// NewTrueTypeFontEncoder creates a new text encoder for TTF fonts with a runeToGlyphIndexMap that
|
||||
@ -33,11 +34,10 @@ type TrueTypeFontEncoder struct {
|
||||
func NewTrueTypeFontEncoder(runeToGIDMap map[rune]GID) TrueTypeFontEncoder {
|
||||
return TrueTypeFontEncoder{
|
||||
runeToGIDMap: runeToGIDMap,
|
||||
cmap: CMapIdentityH{},
|
||||
}
|
||||
}
|
||||
|
||||
// ttEncoderMaxNumEntries is the maximum number of encoding entries shown in SimpleEncoder.String().
|
||||
// ttEncoderMaxNumEntries is the maximum number of encoding entries shown in simpleEncoder.String().
|
||||
const ttEncoderMaxNumEntries = 10
|
||||
|
||||
// String returns a string that describes `enc`.
|
||||
@ -66,22 +66,14 @@ func (enc TrueTypeFontEncoder) String() string {
|
||||
return fmt.Sprintf("TRUETYPE_ENCODER{%s}", strings.Join(parts, ", "))
|
||||
}
|
||||
|
||||
// Encode converts the Go unicode string `raw` to a PDF encoded string.
|
||||
func (enc TrueTypeFontEncoder) Encode(raw string) []byte {
|
||||
return encodeString16bit(enc, raw)
|
||||
// Encode converts the Go unicode string to a PDF encoded string.
|
||||
func (enc TrueTypeFontEncoder) Encode(str string) []byte {
|
||||
return encodeString16bit(enc, str)
|
||||
}
|
||||
|
||||
// CharcodeToGlyph returns the glyph name matching character code `code`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func (enc TrueTypeFontEncoder) CharcodeToGlyph(code CharCode) (GlyphName, bool) {
|
||||
r, found := enc.CharcodeToRune(code)
|
||||
if found && r == 0x20 {
|
||||
return "space", true
|
||||
}
|
||||
|
||||
// Returns "uniXXXX" format where XXXX is the code in hex format.
|
||||
glyph := GlyphName(fmt.Sprintf("uni%.4X", code))
|
||||
return glyph, true
|
||||
// Decode converts PDF encoded string to a Go unicode string.
|
||||
func (enc TrueTypeFontEncoder) Decode(raw []byte) string {
|
||||
return decodeString16bit(enc, raw)
|
||||
}
|
||||
|
||||
// GlyphToCharcode returns character code matching the glyph name `glyph`.
|
||||
@ -136,37 +128,8 @@ func (enc TrueTypeFontEncoder) CharcodeToRune(code CharCode) (rune, bool) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// RuneToGlyph returns the glyph name for rune `r`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func (enc TrueTypeFontEncoder) RuneToGlyph(r rune) (GlyphName, bool) {
|
||||
if r == 0x20 {
|
||||
return "space", true
|
||||
}
|
||||
glyph := GlyphName(fmt.Sprintf("uni%.4X", r))
|
||||
return glyph, true
|
||||
}
|
||||
|
||||
// GlyphToRune returns the rune corresponding to glyph name `glyph`.
|
||||
// The bool return flag is true if there was a match, and false otherwise.
|
||||
func (enc TrueTypeFontEncoder) GlyphToRune(glyph GlyphName) (rune, bool) {
|
||||
// String with "uniXXXX" format where XXXX is the hexcode.
|
||||
if len(glyph) == 7 && glyph[0:3] == "uni" {
|
||||
unicode := uint16(0)
|
||||
n, err := fmt.Sscanf(string(glyph), "uni%X", &unicode)
|
||||
if n == 1 && err == nil {
|
||||
return rune(unicode), true
|
||||
}
|
||||
}
|
||||
|
||||
// Look in glyphlist.
|
||||
if r, ok := glyphlistGlyphToRuneMap[glyph]; ok {
|
||||
return r, true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// ToPdfObject returns a nil as it is not truly a PDF object and should not be attempted to store in file.
|
||||
func (enc TrueTypeFontEncoder) ToPdfObject() core.PdfObject {
|
||||
// TODO(dennwc): reasonable question: why it have to implement this interface then?
|
||||
return core.MakeNull()
|
||||
}
|
||||
|
@ -31,34 +31,6 @@ func runeToGlyph(r rune, runeToGlyphMap map[rune]GlyphName) (GlyphName, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
func splitWords(raw string, encoder TextEncoder) []string {
|
||||
runes := []rune(raw)
|
||||
|
||||
var words []string
|
||||
|
||||
startsAt := 0
|
||||
for idx, r := range runes {
|
||||
glyph, ok := encoder.RuneToGlyph(r)
|
||||
if !ok {
|
||||
common.Log.Debug("Glyph not found for rune %s", rs(r))
|
||||
continue
|
||||
}
|
||||
|
||||
if glyph == "space" || glyph == "uni0020" {
|
||||
word := runes[startsAt:idx]
|
||||
words = append(words, string(word))
|
||||
startsAt = idx + 1
|
||||
}
|
||||
}
|
||||
|
||||
word := runes[startsAt:]
|
||||
if len(word) > 0 {
|
||||
words = append(words, string(word))
|
||||
}
|
||||
|
||||
return words
|
||||
}
|
||||
|
||||
// rs returns a string describing rune `r`.
|
||||
func rs(r rune) string {
|
||||
c := "unprintable"
|
||||
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.md', which is part of this source code package.
|
||||
*/
|
||||
|
||||
package textencoding
|
||||
|
||||
// NewWinAnsiTextEncoder returns a SimpleEncoder that implements WinAnsiEncoding.
|
||||
func NewWinAnsiTextEncoder() *SimpleEncoder {
|
||||
const baseName = "WinAnsiEncoding"
|
||||
enc := newSimpleTextEncoder(winAnsiEncoding, baseName, nil)
|
||||
return enc
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.md', which is part of this source code package.
|
||||
*/
|
||||
|
||||
package textencoding
|
||||
|
||||
// NewZapfDingbatsEncoder returns a SimpleEncoder that implements ZapfDingbatsEncoding.
|
||||
func NewZapfDingbatsEncoder() *SimpleEncoder {
|
||||
enc, _ := NewSimpleTextEncoder("ZapfDingbatsEncoding", nil)
|
||||
return enc
|
||||
}
|
@ -96,11 +96,23 @@ func DefaultFont() *PdfFont {
|
||||
return &PdfFont{context: &std}
|
||||
}
|
||||
|
||||
func newStandard14Font(basefont fonts.StdFontName) (pdfFontSimple, error) {
|
||||
fnt, ok := fonts.NewStdFontByName(basefont)
|
||||
if !ok {
|
||||
return pdfFontSimple{}, ErrFontNotSupported
|
||||
}
|
||||
std := stdFontToSimpleFont(fnt)
|
||||
return std, nil
|
||||
}
|
||||
|
||||
// NewStandard14Font returns the standard 14 font named `basefont` as a *PdfFont, or an error if it
|
||||
// `basefont` is not one of the standard 14 font names.
|
||||
func NewStandard14Font(basefont fonts.StdFontName) (*PdfFont, error) {
|
||||
std, _, err := NewStandard14FontWithEncoding(basefont, nil)
|
||||
return std, err
|
||||
std, err := newStandard14Font(basefont)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PdfFont{context: &std}, nil
|
||||
}
|
||||
|
||||
// NewStandard14FontMustCompile returns the standard 14 font named `basefont` as a *PdfFont.
|
||||
@ -114,86 +126,6 @@ func NewStandard14FontMustCompile(basefont fonts.StdFontName) *PdfFont {
|
||||
return font
|
||||
}
|
||||
|
||||
// NewStandard14FontWithEncoding returns the standard 14 font named `basefont` as a *PdfFont and
|
||||
// a SimpleEncoder that encodes all the runes in `alphabet`, or an error if this is not possible.
|
||||
// An error can occur if `basefont` is not one the standard 14 font names.
|
||||
func NewStandard14FontWithEncoding(basefont fonts.StdFontName, alphabet map[rune]int) (*PdfFont,
|
||||
*textencoding.SimpleEncoder, error) {
|
||||
baseEncoder := "MacRomanEncoding"
|
||||
common.Log.Trace("NewStandard14FontWithEncoding: basefont=%#q baseEncoder=%#q alphabet=%q",
|
||||
basefont, baseEncoder, string(sortedAlphabet(alphabet)))
|
||||
|
||||
fnt, ok := fonts.NewStdFontByName(basefont)
|
||||
if !ok {
|
||||
return nil, nil, ErrFontNotSupported
|
||||
}
|
||||
std := stdFontToSimpleFont(fnt)
|
||||
|
||||
encoder, err := textencoding.NewSimpleTextEncoder(baseEncoder, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// glyphCode are the encoding glyphs. We need to match them to the font glyphs.
|
||||
glyphCode := make(map[textencoding.GlyphName]textencoding.CharCode)
|
||||
|
||||
// slots are the indexes in the encoding where the new character codes are added.
|
||||
// slots are unused indexes, which are filled first. slots1 are the used indexes.
|
||||
var slots, slots1 []textencoding.CharCode
|
||||
for code := textencoding.CharCode(1); code <= 0xff; code++ {
|
||||
if glyph, ok := encoder.CharcodeToGlyph(code); ok {
|
||||
glyphCode[glyph] = code
|
||||
// Don't overwrite space
|
||||
if glyph != "space" {
|
||||
|
||||
slots1 = append(slots1, code)
|
||||
}
|
||||
} else {
|
||||
slots = append(slots, code)
|
||||
}
|
||||
}
|
||||
slots = append(slots, slots1...)
|
||||
|
||||
// `glyphs` are the font glyphs that we need to encode.
|
||||
var glyphs []textencoding.GlyphName
|
||||
for _, r := range sortedAlphabet(alphabet) {
|
||||
glyph, ok := textencoding.RuneToGlyph(r)
|
||||
if !ok {
|
||||
common.Log.Debug("No glyph for rune 0x%02x=%c", r, r)
|
||||
continue
|
||||
}
|
||||
if _, ok = std.fontMetrics[glyph]; !ok {
|
||||
common.Log.Trace("Glyph %q (0x%04x=%c)not in font", glyph, r, r)
|
||||
continue
|
||||
}
|
||||
if len(glyphs) >= 255 {
|
||||
common.Log.Debug("Too many characters for encoding")
|
||||
break
|
||||
}
|
||||
glyphs = append(glyphs, glyph)
|
||||
|
||||
}
|
||||
|
||||
// Fill the slots, starting with the empty ones.
|
||||
slotIdx := 0
|
||||
differences := make(map[textencoding.CharCode]textencoding.GlyphName)
|
||||
for _, glyph := range glyphs {
|
||||
if _, ok := glyphCode[glyph]; !ok {
|
||||
differences[slots[slotIdx]] = glyph
|
||||
slotIdx++
|
||||
}
|
||||
}
|
||||
|
||||
encoder, err = textencoding.NewSimpleTextEncoder(baseEncoder, differences)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
std.std14Encoder = encoder
|
||||
std.updateStandard14Font()
|
||||
|
||||
return &PdfFont{context: &std}, encoder, nil
|
||||
}
|
||||
|
||||
// GetAlphabet returns a map of the runes in `text` and their frequencies.
|
||||
func GetAlphabet(text string) map[rune]int {
|
||||
alphabet := map[rune]int{}
|
||||
@ -528,9 +460,10 @@ func (font *PdfFont) GetRuneMetrics(r rune) (fonts.CharMetrics, bool) {
|
||||
func (font *PdfFont) GetCharMetrics(code textencoding.CharCode) (fonts.CharMetrics, bool) {
|
||||
var nometrics fonts.CharMetrics
|
||||
|
||||
// XXX(peterwilliams97) pdfFontType0.GetCharMetrics() calls pdfCIDFontType2.GetCharMetrics()
|
||||
// through this function. Would it be more straightforward for pdfFontType0.GetCharMetrics() to
|
||||
// call pdfCIDFontType0.GetCharMetrics() and pdfCIDFontType2.GetCharMetrics() directly?
|
||||
// TODO(peterwilliams97): pdfFontType0.GetCharMetrics() calls pdfCIDFontType2.GetCharMetrics()
|
||||
// through this function. Would it be more straightforward for
|
||||
// pdfFontType0.GetCharMetrics() to call pdfCIDFontType0.GetCharMetrics()
|
||||
// and pdfCIDFontType2.GetCharMetrics() directly?
|
||||
|
||||
switch t := font.context.(type) {
|
||||
case *pdfFontSimple:
|
||||
|
@ -298,8 +298,8 @@ type pdfCIDFontType2 struct {
|
||||
defaultWidth float64
|
||||
|
||||
// Mapping between unicode runes to widths.
|
||||
// TODO(dennwc): both are used only in GetGlyphCharMetrics
|
||||
// we can precompute metrics and drop both
|
||||
// TODO(dennwc): it is used only in GetGlyphCharMetrics
|
||||
// we can precompute metrics and drop it
|
||||
runeToWidthMap map[rune]int
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,9 @@ type pdfFontSimple struct {
|
||||
|
||||
charWidths map[textencoding.CharCode]float64
|
||||
// std14Encoder is the encoder specified by the /Encoding entry in the font dict.
|
||||
encoder *textencoding.SimpleEncoder
|
||||
encoder textencoding.TextEncoder
|
||||
// std14Encoder is used for Standard 14 fonts where no /Encoding is specified in the font dict.
|
||||
std14Encoder *textencoding.SimpleEncoder
|
||||
std14Encoder textencoding.TextEncoder
|
||||
|
||||
// std14Descriptor is used for Standard 14 fonts where no /FontDescriptor is specified in the font dict.
|
||||
std14Descriptor *PdfFontDescriptor
|
||||
@ -58,7 +58,7 @@ type pdfFontSimple struct {
|
||||
Encoding core.PdfObject
|
||||
|
||||
// Standard 14 fonts metrics
|
||||
fontMetrics map[textencoding.GlyphName]fonts.CharMetrics
|
||||
fontMetrics map[rune]fonts.CharMetrics
|
||||
}
|
||||
|
||||
// pdfCIDFontType0FromSkeleton returns a pdfFontSimple with its common fields initalized.
|
||||
@ -100,27 +100,26 @@ func (font *pdfFontSimple) Encoder() textencoding.TextEncoder {
|
||||
}
|
||||
|
||||
// SetEncoder sets the encoding for the underlying font.
|
||||
// TODO(peterwilliams97): Change function signature to SetEncoder(encoder *textencoding.SimpleEncoder).
|
||||
// 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.
|
||||
func (font *pdfFontSimple) SetEncoder(encoder textencoding.TextEncoder) {
|
||||
simple, ok := encoder.(*textencoding.SimpleEncoder)
|
||||
if !ok {
|
||||
// This can't happen.
|
||||
common.Log.Error("pdfFontSimple.SetEncoder passed bad encoder type %T", encoder)
|
||||
simple = nil
|
||||
}
|
||||
font.encoder = simple
|
||||
font.encoder = encoder
|
||||
}
|
||||
|
||||
// GetRuneMetrics returns the character metrics for the rune.
|
||||
// A bool flag is returned to indicate whether or not the entry was found.
|
||||
func (font pdfFontSimple) GetRuneMetrics(r rune) (fonts.CharMetrics, bool) {
|
||||
if font.fontMetrics != nil {
|
||||
metrics, has := font.fontMetrics[r]
|
||||
if has {
|
||||
return metrics, true
|
||||
}
|
||||
}
|
||||
encoder := font.Encoder()
|
||||
if encoder == nil {
|
||||
common.Log.Debug("No encoder for fonts=%s", font)
|
||||
return fonts.CharMetrics{}, false
|
||||
}
|
||||
|
||||
code, found := encoder.RuneToCharcode(r)
|
||||
if !found {
|
||||
if r != ' ' {
|
||||
@ -128,14 +127,6 @@ func (font pdfFontSimple) GetRuneMetrics(r rune) (fonts.CharMetrics, bool) {
|
||||
}
|
||||
return fonts.CharMetrics{}, false
|
||||
}
|
||||
if font.fontMetrics != nil {
|
||||
if glyph, found := encoder.CharcodeToGlyph(code); found {
|
||||
metrics, has := font.fontMetrics[glyph]
|
||||
if has {
|
||||
return metrics, true
|
||||
}
|
||||
}
|
||||
}
|
||||
metrics, ok := font.GetCharMetrics(code)
|
||||
return metrics, ok
|
||||
}
|
||||
@ -166,7 +157,7 @@ func (font pdfFontSimple) GetCharMetrics(code textencoding.CharCode) (fonts.Char
|
||||
// • The value of BaseFont is derived differently.
|
||||
//
|
||||
func newSimpleFontFromPdfObject(d *core.PdfObjectDictionary, base *fontCommon,
|
||||
std14Encoder *textencoding.SimpleEncoder) (*pdfFontSimple, error) {
|
||||
std14Encoder textencoding.TextEncoder) (*pdfFontSimple, error) {
|
||||
font := pdfFontSimpleFromSkeleton(base)
|
||||
font.std14Encoder = std14Encoder
|
||||
|
||||
@ -239,11 +230,11 @@ func (font *pdfFontSimple) addEncoding() error {
|
||||
var (
|
||||
baseEncoder string
|
||||
differences map[textencoding.CharCode]textencoding.GlyphName
|
||||
encoder *textencoding.SimpleEncoder
|
||||
encoder textencoding.SimpleEncoder
|
||||
)
|
||||
|
||||
if font.Encoder() != nil {
|
||||
encoder, ok := font.Encoder().(*textencoding.SimpleEncoder)
|
||||
encoder, ok := font.Encoder().(textencoding.SimpleEncoder)
|
||||
if ok && encoder != nil {
|
||||
baseEncoder = encoder.BaseName()
|
||||
}
|
||||
@ -291,7 +282,7 @@ func (font *pdfFontSimple) addEncoding() error {
|
||||
// At the end, apply the differences.
|
||||
if differences != nil {
|
||||
common.Log.Trace("differences=%+v font=%s", differences, font.baseFields())
|
||||
encoder.ApplyDifferences(differences)
|
||||
encoder = textencoding.ApplyDifferences(encoder, differences)
|
||||
}
|
||||
font.SetEncoder(encoder)
|
||||
}
|
||||
@ -408,7 +399,7 @@ func NewPdfFontFromTTFFile(filePath string) (*PdfFont, error) {
|
||||
},
|
||||
}
|
||||
|
||||
truefont.encoder = textencoding.NewWinAnsiTextEncoder()
|
||||
truefont.encoder = textencoding.NewWinAnsiEncoder()
|
||||
|
||||
truefont.basefont = ttf.PostScriptName
|
||||
truefont.FirstChar = core.MakeInteger(int64(minCode))
|
||||
@ -430,14 +421,14 @@ func NewPdfFontFromTTFFile(filePath string) (*PdfFont, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
pos, ok := ttf.Chars[r]
|
||||
gid, ok := ttf.Chars[r]
|
||||
if !ok {
|
||||
common.Log.Debug("Rune not in TTF Chars")
|
||||
vals = append(vals, missingWidth)
|
||||
continue
|
||||
}
|
||||
|
||||
w := k * float64(ttf.Widths[pos])
|
||||
w := k * float64(ttf.Widths[gid])
|
||||
|
||||
vals = append(vals, w)
|
||||
}
|
||||
@ -508,7 +499,7 @@ func NewPdfFontFromTTFFile(filePath string) (*PdfFont, error) {
|
||||
// updateStandard14Font fills the font.charWidths for standard 14 fonts.
|
||||
// Don't call this function with a font that is not in the standard 14.
|
||||
func (font *pdfFontSimple) updateStandard14Font() {
|
||||
se, ok := font.Encoder().(*textencoding.SimpleEncoder)
|
||||
se, ok := font.Encoder().(textencoding.SimpleEncoder)
|
||||
if !ok {
|
||||
// This can't happen.
|
||||
common.Log.Error("Wrong encoder type: %T. font=%s.", font.Encoder(), font)
|
||||
@ -518,9 +509,9 @@ func (font *pdfFontSimple) updateStandard14Font() {
|
||||
codes := se.Charcodes()
|
||||
font.charWidths = make(map[textencoding.CharCode]float64, len(codes))
|
||||
for _, code := range codes {
|
||||
// codes was built from CharcodeToGlyph mapping, so each should have a glyph
|
||||
glyph, _ := se.CharcodeToGlyph(code)
|
||||
font.charWidths[code] = font.fontMetrics[glyph].Wx
|
||||
// codes was built from the same mapping mapping, so each should have a rune
|
||||
r, _ := se.CharcodeToRune(code)
|
||||
font.charWidths[code] = font.fontMetrics[r].Wx
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,6 +537,6 @@ func stdFontToSimpleFont(f fonts.StdFont) pdfFontSimple {
|
||||
StemV: core.MakeFloat(l.StemV),
|
||||
StemH: core.MakeFloat(l.StemH),
|
||||
},
|
||||
std14Encoder: f.SimpleEncoder(),
|
||||
std14Encoder: f.Encoder(),
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
@ -119,7 +118,8 @@ func TestNewStandard14Font(t *testing.T) {
|
||||
"Courier": {
|
||||
subtype: "Type1",
|
||||
basefont: "Courier",
|
||||
CharMetrics: fonts.CharMetrics{Wx: 600}},
|
||||
CharMetrics: fonts.CharMetrics{Wx: 600},
|
||||
},
|
||||
}
|
||||
|
||||
for in, expect := range tests {
|
||||
@ -638,172 +638,172 @@ endobj
|
||||
// The expected encoding is StandardEncoding with the applied differences.
|
||||
baseEncoding := newStandandTextEncoder(t)
|
||||
|
||||
differencesMap := map[textencoding.CharCode]textencoding.GlyphName{
|
||||
24: `/breve`,
|
||||
25: `/caron`,
|
||||
26: `/circumflex`,
|
||||
27: `/dotaccent`,
|
||||
28: `/hungarumlaut`,
|
||||
29: `/ogonek`,
|
||||
30: `/ring`,
|
||||
31: `/tilde`,
|
||||
39: `/quotesingle`,
|
||||
96: `/grave`,
|
||||
128: `/bullet`,
|
||||
129: `/dagger`,
|
||||
130: `/daggerdbl`,
|
||||
131: `/ellipsis`,
|
||||
132: `/emdash`,
|
||||
133: `/endash`,
|
||||
134: `/florin`,
|
||||
135: `/fraction`,
|
||||
136: `/guilsinglleft`,
|
||||
137: `/guilsinglright`,
|
||||
138: `/minus`,
|
||||
139: `/perthousand`,
|
||||
140: `/quotedblbase`,
|
||||
141: `/quotedblleft`,
|
||||
142: `/quotedblright`,
|
||||
143: `/quoteleft`,
|
||||
144: `/quoteright`,
|
||||
145: `/quotesinglbase`,
|
||||
146: `/trademark`,
|
||||
147: `/fi`,
|
||||
148: `/fl`,
|
||||
149: `/Lslash`,
|
||||
150: `/OE`,
|
||||
151: `/Scaron`,
|
||||
152: `/Ydieresis`,
|
||||
153: `/Zcaron`,
|
||||
154: `/dotlessi`,
|
||||
155: `/lslash`,
|
||||
156: `/oe`,
|
||||
157: `/scaron`,
|
||||
158: `/zcaron`,
|
||||
160: `/Euro`,
|
||||
164: `/currency`,
|
||||
166: `/brokenbar`,
|
||||
168: `/dieresis`,
|
||||
169: `/copyright`,
|
||||
170: `/ordfeminine`,
|
||||
172: `/logicalnot`,
|
||||
173: `/.notdef`,
|
||||
174: `/registered`,
|
||||
175: `/macron`,
|
||||
176: `/degree`,
|
||||
177: `/plusminus`,
|
||||
178: `/twosuperior`,
|
||||
179: `/threesuperior`,
|
||||
180: `/acute`,
|
||||
181: `/mu`,
|
||||
183: `/periodcentered`,
|
||||
184: `/cedilla`,
|
||||
185: `/onesuperior`,
|
||||
186: `/ordmasculine`,
|
||||
188: `/onequarter`,
|
||||
189: `/onehalf`,
|
||||
190: `/threequarters`,
|
||||
192: `/Agrave`,
|
||||
193: `/Aacute`,
|
||||
194: `/Acircumflex`,
|
||||
195: `/Atilde`,
|
||||
196: `/Adieresis`,
|
||||
197: `/Aring`,
|
||||
198: `/AE`,
|
||||
199: `/Ccedilla`,
|
||||
200: `/Egrave`,
|
||||
201: `/Eacute`,
|
||||
202: `/Ecircumflex`,
|
||||
203: `/Edieresis`,
|
||||
204: `/Igrave`,
|
||||
205: `/Iacute`,
|
||||
206: `/Icircumflex`,
|
||||
207: `/Idieresis`,
|
||||
208: `/Eth`,
|
||||
209: `/Ntilde`,
|
||||
210: `/Ograve`,
|
||||
211: `/Oacute`,
|
||||
212: `/Ocircumflex`,
|
||||
213: `/Otilde`,
|
||||
214: `/Odieresis`,
|
||||
215: `/multiply`,
|
||||
216: `/Oslash`,
|
||||
217: `/Ugrave`,
|
||||
218: `/Uacute`,
|
||||
219: `/Ucircumflex`,
|
||||
220: `/Udieresis`,
|
||||
221: `/Yacute`,
|
||||
222: `/Thorn`,
|
||||
223: `/germandbls`,
|
||||
224: `/agrave`,
|
||||
225: `/aacute`,
|
||||
226: `/acircumflex`,
|
||||
227: `/atilde`,
|
||||
228: `/adieresis`,
|
||||
229: `/aring`,
|
||||
230: `/ae`,
|
||||
231: `/ccedilla`,
|
||||
232: `/egrave`,
|
||||
233: `/eacute`,
|
||||
234: `/ecircumflex`,
|
||||
235: `/edieresis`,
|
||||
236: `/igrave`,
|
||||
237: `/iacute`,
|
||||
238: `/icircumflex`,
|
||||
239: `/idieresis`,
|
||||
240: `/eth`,
|
||||
241: `/ntilde`,
|
||||
242: `/ograve`,
|
||||
243: `/oacute`,
|
||||
244: `/ocircumflex`,
|
||||
245: `/otilde`,
|
||||
246: `/odieresis`,
|
||||
247: `/divide`,
|
||||
248: `/oslash`,
|
||||
249: `/ugrave`,
|
||||
250: `/uacute`,
|
||||
251: `/ucircumflex`,
|
||||
252: `/udieresis`,
|
||||
253: `/yacute`,
|
||||
254: `/thorn`,
|
||||
255: `/ydieresis`,
|
||||
differencesMap := map[textencoding.CharCode]rune{
|
||||
24: '˘',
|
||||
25: 'ˇ',
|
||||
26: 'ˆ',
|
||||
27: '˙',
|
||||
28: '˝',
|
||||
29: '˛',
|
||||
30: '˚',
|
||||
31: '˜',
|
||||
39: '\'',
|
||||
96: '`',
|
||||
128: '•',
|
||||
129: '†',
|
||||
130: '‡',
|
||||
131: '…',
|
||||
132: '—',
|
||||
133: '–',
|
||||
134: 'ƒ',
|
||||
135: '⁄',
|
||||
136: '‹',
|
||||
137: '›',
|
||||
138: '−',
|
||||
139: '‰',
|
||||
140: '„',
|
||||
141: '“',
|
||||
142: '”',
|
||||
143: '‘',
|
||||
144: '’',
|
||||
145: '‚',
|
||||
146: '™',
|
||||
147: 'fi',
|
||||
148: 'fl',
|
||||
149: 'Ł',
|
||||
150: 'Œ',
|
||||
151: 'Š',
|
||||
152: 'Ÿ',
|
||||
153: 'Ž',
|
||||
154: 'ı',
|
||||
155: 'ł',
|
||||
156: 'œ',
|
||||
157: 'š',
|
||||
158: 'ž',
|
||||
160: '€',
|
||||
164: '¤',
|
||||
166: '¦',
|
||||
168: '¨',
|
||||
169: '©',
|
||||
170: 'ª',
|
||||
172: '¬',
|
||||
173: '<27>',
|
||||
174: '®',
|
||||
175: '¯',
|
||||
176: '°',
|
||||
177: '±',
|
||||
178: '²',
|
||||
179: '³',
|
||||
180: '´',
|
||||
181: 'µ',
|
||||
183: '·',
|
||||
184: '¸',
|
||||
185: '¹',
|
||||
186: 'º',
|
||||
188: '¼',
|
||||
189: '½',
|
||||
190: '¾',
|
||||
192: 'À',
|
||||
193: 'Á',
|
||||
194: 'Â',
|
||||
195: 'Ã',
|
||||
196: 'Ä',
|
||||
197: 'Å',
|
||||
198: 'Æ',
|
||||
199: 'Ç',
|
||||
200: 'È',
|
||||
201: 'É',
|
||||
202: 'Ê',
|
||||
203: 'Ë',
|
||||
204: 'Ì',
|
||||
205: 'Í',
|
||||
206: 'Î',
|
||||
207: 'Ï',
|
||||
208: 'Ð',
|
||||
209: 'Ñ',
|
||||
210: 'Ò',
|
||||
211: 'Ó',
|
||||
212: 'Ô',
|
||||
213: 'Õ',
|
||||
214: 'Ö',
|
||||
215: '×',
|
||||
216: 'Ø',
|
||||
217: 'Ù',
|
||||
218: 'Ú',
|
||||
219: 'Û',
|
||||
220: 'Ü',
|
||||
221: 'Ý',
|
||||
222: 'Þ',
|
||||
223: 'ß',
|
||||
224: 'à',
|
||||
225: 'á',
|
||||
226: 'â',
|
||||
227: 'ã',
|
||||
228: 'ä',
|
||||
229: 'å',
|
||||
230: 'æ',
|
||||
231: 'ç',
|
||||
232: 'è',
|
||||
233: 'é',
|
||||
234: 'ê',
|
||||
235: 'ë',
|
||||
236: 'ì',
|
||||
237: 'í',
|
||||
238: 'î',
|
||||
239: 'ï',
|
||||
240: 'ð',
|
||||
241: 'ñ',
|
||||
242: 'ò',
|
||||
243: 'ó',
|
||||
244: 'ô',
|
||||
245: 'õ',
|
||||
246: 'ö',
|
||||
247: '÷',
|
||||
248: 'ø',
|
||||
249: 'ù',
|
||||
250: 'ú',
|
||||
251: 'û',
|
||||
252: 'ü',
|
||||
253: 'ý',
|
||||
254: 'þ',
|
||||
255: 'ÿ',
|
||||
}
|
||||
|
||||
for ccode := textencoding.CharCode(32); ccode < 255; ccode++ {
|
||||
fontglyph, has := font.Encoder().CharcodeToGlyph(ccode)
|
||||
enc := font.Encoder()
|
||||
for code := textencoding.CharCode(32); code < 255; code++ {
|
||||
fontrune, has := enc.CharcodeToRune(code)
|
||||
if !has {
|
||||
baseglyph, bad := baseEncoding.CharcodeToGlyph(ccode)
|
||||
baserune, bad := baseEncoding.CharcodeToRune(code)
|
||||
if bad {
|
||||
t.Fatalf("font not having glyph for char code %d - whereas base encoding had '%s'", ccode, baseglyph)
|
||||
t.Fatalf("font not having glyph for char code %d - whereas base encoding had %q", code, baserune)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if in differencesmap first.
|
||||
glyph, has := differencesMap[ccode]
|
||||
rune, has := differencesMap[code]
|
||||
if has {
|
||||
glyph = textencoding.GlyphName(strings.Trim(string(glyph), `/`))
|
||||
if glyph != fontglyph {
|
||||
t.Fatalf("Mismatch for char code %d, font has: %s and expected is: %s (differences)", ccode, fontglyph, glyph)
|
||||
if rune != fontrune {
|
||||
t.Fatalf("Mismatch for char code %d, font has: %q and expected is: %q (differences)", code, fontrune, rune)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// If not in differences, should be according to StandardEncoding (base).
|
||||
glyph, has = baseEncoding.CharcodeToGlyph(ccode)
|
||||
if has && glyph != fontglyph {
|
||||
t.Fatalf("Mismatch for char code %d (%X), font has: %s and expected is: %s (StandardEncoding)", ccode, ccode, fontglyph, glyph)
|
||||
rune, has = baseEncoding.CharcodeToRune(code)
|
||||
if has && rune != fontrune {
|
||||
t.Fatalf("Mismatch for char code %d (%X), font has: %q and expected is: %q (StandardEncoding)", code, code, fontrune, rune)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// newStandandTextEncoder returns a SimpleEncoder that implements StandardEncoding.
|
||||
// newStandandTextEncoder returns a simpleEncoder that implements StandardEncoding.
|
||||
// The non-symbolic standard 14 fonts have StandardEncoding.
|
||||
func newStandandTextEncoder(t *testing.T) textencoding.SimpleEncoder {
|
||||
enc, err := textencoding.NewSimpleTextEncoder("StandardEncoding", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error: %v", err)
|
||||
}
|
||||
return *enc
|
||||
return enc
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import (
|
||||
type fontFile struct {
|
||||
name string
|
||||
subtype string
|
||||
encoder *textencoding.SimpleEncoder
|
||||
encoder textencoding.SimpleEncoder
|
||||
}
|
||||
|
||||
// String returns a human readable description of `fontfile`.
|
||||
|
@ -72,18 +72,18 @@ var _ Font = StdFont{}
|
||||
// StdFont represents one of the built-in fonts and it is assumed that every reader has access to it.
|
||||
type StdFont struct {
|
||||
desc Descriptor
|
||||
metrics map[GlyphName]CharMetrics
|
||||
encoder *textencoding.SimpleEncoder
|
||||
metrics map[rune]CharMetrics
|
||||
encoder textencoding.TextEncoder
|
||||
}
|
||||
|
||||
// NewStdFont returns a new instance of the font with a default encoder set (WinAnsiEncoding).
|
||||
func NewStdFont(desc Descriptor, metrics map[GlyphName]CharMetrics) StdFont {
|
||||
enc := textencoding.NewWinAnsiTextEncoder() // Default
|
||||
func NewStdFont(desc Descriptor, metrics map[rune]CharMetrics) StdFont {
|
||||
enc := textencoding.NewWinAnsiEncoder() // Default
|
||||
return NewStdFontWithEncoding(desc, metrics, enc)
|
||||
}
|
||||
|
||||
// NewStdFontWithEncoding returns a new instance of the font with a specified encoder.
|
||||
func NewStdFontWithEncoding(desc Descriptor, metrics map[GlyphName]CharMetrics, encoder *textencoding.SimpleEncoder) StdFont {
|
||||
func NewStdFontWithEncoding(desc Descriptor, metrics map[rune]CharMetrics, encoder textencoding.TextEncoder) StdFont {
|
||||
return StdFont{
|
||||
desc: desc,
|
||||
metrics: metrics,
|
||||
@ -98,27 +98,18 @@ func (font StdFont) Name() string {
|
||||
|
||||
// Encoder returns the font's text encoder.
|
||||
func (font StdFont) Encoder() textencoding.TextEncoder {
|
||||
return font.SimpleEncoder()
|
||||
}
|
||||
|
||||
// SimpleEncoder returns the font's text encoder.
|
||||
func (font StdFont) SimpleEncoder() *textencoding.SimpleEncoder {
|
||||
return font.encoder
|
||||
}
|
||||
|
||||
// GetRuneMetrics returns character metrics for a given rune.
|
||||
func (font StdFont) GetRuneMetrics(r rune) (CharMetrics, bool) {
|
||||
glyph, has := font.encoder.RuneToGlyph(r)
|
||||
if !has {
|
||||
return CharMetrics{}, false
|
||||
}
|
||||
metrics, has := font.metrics[glyph]
|
||||
return metrics, true
|
||||
metrics, has := font.metrics[r]
|
||||
return metrics, has
|
||||
}
|
||||
|
||||
// GetMetricsTable is a method specific to standard fonts. It returns the metrics table of all glyphs.
|
||||
// Caller should not modify the table.
|
||||
func (font StdFont) GetMetricsTable() map[GlyphName]CharMetrics {
|
||||
func (font StdFont) GetMetricsTable() map[rune]CharMetrics {
|
||||
return font.metrics
|
||||
}
|
||||
|
||||
@ -138,69 +129,38 @@ func (font StdFont) ToPdfObject() core.PdfObject {
|
||||
return core.MakeIndirectObject(fontDict)
|
||||
}
|
||||
|
||||
// type1CommonGlyphs is list of common glyph names for some Type1. Used to unpack character metrics.
|
||||
var type1CommonGlyphs = []textencoding.GlyphName{
|
||||
"A", "AE", "Aacute", "Abreve", "Acircumflex",
|
||||
"Adieresis", "Agrave", "Amacron", "Aogonek", "Aring",
|
||||
"Atilde", "B", "C", "Cacute", "Ccaron",
|
||||
"Ccedilla", "D", "Dcaron", "Dcroat", "Delta",
|
||||
"E", "Eacute", "Ecaron", "Ecircumflex", "Edieresis",
|
||||
"Edotaccent", "Egrave", "Emacron", "Eogonek", "Eth",
|
||||
"Euro", "F", "G", "Gbreve", "Gcommaaccent",
|
||||
"H", "I", "Iacute", "Icircumflex", "Idieresis",
|
||||
"Idotaccent", "Igrave", "Imacron", "Iogonek", "J",
|
||||
"K", "Kcommaaccent", "L", "Lacute", "Lcaron",
|
||||
"Lcommaaccent", "Lslash", "M", "N", "Nacute",
|
||||
"Ncaron", "Ncommaaccent", "Ntilde", "O", "OE",
|
||||
"Oacute", "Ocircumflex", "Odieresis", "Ograve", "Ohungarumlaut",
|
||||
"Omacron", "Oslash", "Otilde", "P", "Q",
|
||||
"R", "Racute", "Rcaron", "Rcommaaccent", "S",
|
||||
"Sacute", "Scaron", "Scedilla", "Scommaaccent", "T",
|
||||
"Tcaron", "Tcommaaccent", "Thorn", "U", "Uacute",
|
||||
"Ucircumflex", "Udieresis", "Ugrave", "Uhungarumlaut", "Umacron",
|
||||
"Uogonek", "Uring", "V", "W", "X",
|
||||
"Y", "Yacute", "Ydieresis", "Z", "Zacute",
|
||||
"Zcaron", "Zdotaccent", "a", "aacute", "abreve",
|
||||
"acircumflex", "acute", "adieresis", "ae", "agrave",
|
||||
"amacron", "ampersand", "aogonek", "aring", "asciicircum",
|
||||
"asciitilde", "asterisk", "at", "atilde", "b",
|
||||
"backslash", "bar", "braceleft", "braceright", "bracketleft",
|
||||
"bracketright", "breve", "brokenbar", "bullet", "c",
|
||||
"cacute", "caron", "ccaron", "ccedilla", "cedilla",
|
||||
"cent", "circumflex", "colon", "comma", "commaaccent",
|
||||
"copyright", "currency", "d", "dagger", "daggerdbl",
|
||||
"dcaron", "dcroat", "degree", "dieresis", "divide",
|
||||
"dollar", "dotaccent", "dotlessi", "e", "eacute",
|
||||
"ecaron", "ecircumflex", "edieresis", "edotaccent", "egrave",
|
||||
"eight", "ellipsis", "emacron", "emdash", "endash",
|
||||
"eogonek", "equal", "eth", "exclam", "exclamdown",
|
||||
"f", "fi", "five", "fl", "florin",
|
||||
"four", "fraction", "g", "gbreve", "gcommaaccent",
|
||||
"germandbls", "grave", "greater", "greaterequal", "guillemotleft",
|
||||
"guillemotright", "guilsinglleft", "guilsinglright", "h", "hungarumlaut",
|
||||
"hyphen", "i", "iacute", "icircumflex", "idieresis",
|
||||
"igrave", "imacron", "iogonek", "j", "k",
|
||||
"kcommaaccent", "l", "lacute", "lcaron", "lcommaaccent",
|
||||
"less", "lessequal", "logicalnot", "lozenge", "lslash",
|
||||
"m", "macron", "minus", "mu", "multiply",
|
||||
"n", "nacute", "ncaron", "ncommaaccent", "nine",
|
||||
"notequal", "ntilde", "numbersign", "o", "oacute",
|
||||
"ocircumflex", "odieresis", "oe", "ogonek", "ograve",
|
||||
"ohungarumlaut", "omacron", "one", "onehalf", "onequarter",
|
||||
"onesuperior", "ordfeminine", "ordmasculine", "oslash", "otilde",
|
||||
"p", "paragraph", "parenleft", "parenright", "partialdiff",
|
||||
"percent", "period", "periodcentered", "perthousand", "plus",
|
||||
"plusminus", "q", "question", "questiondown", "quotedbl",
|
||||
"quotedblbase", "quotedblleft", "quotedblright", "quoteleft", "quoteright",
|
||||
"quotesinglbase", "quotesingle", "r", "racute", "radical",
|
||||
"rcaron", "rcommaaccent", "registered", "ring", "s",
|
||||
"sacute", "scaron", "scedilla", "scommaaccent", "section",
|
||||
"semicolon", "seven", "six", "slash", "space",
|
||||
"sterling", "summation", "t", "tcaron", "tcommaaccent",
|
||||
"thorn", "three", "threequarters", "threesuperior", "tilde",
|
||||
"trademark", "two", "twosuperior", "u", "uacute",
|
||||
"ucircumflex", "udieresis", "ugrave", "uhungarumlaut", "umacron",
|
||||
"underscore", "uogonek", "uring", "v", "w",
|
||||
"x", "y", "yacute", "ydieresis", "yen",
|
||||
"z", "zacute", "zcaron", "zdotaccent", "zero",
|
||||
// type1CommonRunes is list of runes common for some Type1 fonts. Used to unpack character metrics.
|
||||
var type1CommonRunes = []rune{
|
||||
'A', 'Æ', 'Á', 'Ă', 'Â', 'Ä', 'À', 'Ā', 'Ą', 'Å',
|
||||
'Ã', 'B', 'C', 'Ć', 'Č', 'Ç', 'D', 'Ď', 'Đ', '∆',
|
||||
'E', 'É', 'Ě', 'Ê', 'Ë', 'Ė', 'È', 'Ē', 'Ę', 'Ð',
|
||||
'€', 'F', 'G', 'Ğ', 'Ģ', 'H', 'I', 'Í', 'Î', 'Ï',
|
||||
'İ', 'Ì', 'Ī', 'Į', 'J', 'K', 'Ķ', 'L', 'Ĺ', 'Ľ',
|
||||
'Ļ', 'Ł', 'M', 'N', 'Ń', 'Ň', 'Ņ', 'Ñ', 'O', 'Œ',
|
||||
'Ó', 'Ô', 'Ö', 'Ò', 'Ő', 'Ō', 'Ø', 'Õ', 'P', 'Q',
|
||||
'R', 'Ŕ', 'Ř', 'Ŗ', 'S', 'Ś', 'Š', 'Ş', 'Ș', 'T',
|
||||
'Ť', 'Ţ', 'Þ', 'U', 'Ú', 'Û', 'Ü', 'Ù', 'Ű', 'Ū',
|
||||
'Ų', 'Ů', 'V', 'W', 'X', 'Y', 'Ý', 'Ÿ', 'Z', 'Ź',
|
||||
'Ž', 'Ż', 'a', 'á', 'ă', 'â', '´', 'ä', 'æ', 'à',
|
||||
'ā', '&', 'ą', 'å', '^', '~', '*', '@', 'ã', 'b',
|
||||
'\\', '|', '{', '}', '[', ']', '˘', '¦', '•', 'c',
|
||||
'ć', 'ˇ', 'č', 'ç', '¸', '¢', 'ˆ', ':', ',', '\uf6c3',
|
||||
'©', '¤', 'd', '†', '‡', 'ď', 'đ', '°', '¨', '÷',
|
||||
'$', '˙', 'ı', 'e', 'é', 'ě', 'ê', 'ë', 'ė', 'è',
|
||||
'8', '…', 'ē', '—', '–', 'ę', '=', 'ð', '!', '¡',
|
||||
'f', 'fi', '5', 'fl', 'ƒ', '4', '⁄', 'g', 'ğ', 'ģ',
|
||||
'ß', '`', '>', '≥', '«', '»', '‹', '›', 'h', '˝',
|
||||
'-', 'i', 'í', 'î', 'ï', 'ì', 'ī', 'į', 'j', 'k',
|
||||
'ķ', 'l', 'ĺ', 'ľ', 'ļ', '<', '≤', '¬', '◊', 'ł',
|
||||
'm', '¯', '−', 'µ', '×', 'n', 'ń', 'ň', 'ņ', '9',
|
||||
'≠', 'ñ', '#', 'o', 'ó', 'ô', 'ö', 'œ', '˛', 'ò',
|
||||
'ő', 'ō', '1', '½', '¼', '¹', 'ª', 'º', 'ø', 'õ',
|
||||
'p', '¶', '(', ')', '∂', '%', '.', '·', '‰', '+',
|
||||
'±', 'q', '?', '¿', '"', '„', '“', '”', '‘', '’',
|
||||
'‚', '\'', 'r', 'ŕ', '√', 'ř', 'ŗ', '®', '˚', 's',
|
||||
'ś', 'š', 'ş', 'ș', '§', ';', '7', '6', '/', ' ',
|
||||
'£', '∑', 't', 'ť', 'ţ', 'þ', '3', '¾', '³', '˜',
|
||||
'™', '2', '²', 'u', 'ú', 'û', 'ü', 'ù', 'ű', 'ū',
|
||||
'_', 'ų', 'ů', 'v', 'w', 'x', 'y', 'ý', 'ÿ', '¥',
|
||||
'z', 'ź', 'ž', 'ż', '0',
|
||||
}
|
||||
|
@ -118,9 +118,9 @@ var courierOnce sync.Once
|
||||
func initCourier() {
|
||||
// the only font that has same metrics for all glyphs (fixed-width)
|
||||
const wx = 600
|
||||
courierCharMetrics = make(map[GlyphName]CharMetrics, len(type1CommonGlyphs))
|
||||
for _, glyph := range type1CommonGlyphs {
|
||||
courierCharMetrics[glyph] = CharMetrics{Wx: wx}
|
||||
courierCharMetrics = make(map[rune]CharMetrics, len(type1CommonRunes))
|
||||
for _, r := range type1CommonRunes {
|
||||
courierCharMetrics[r] = CharMetrics{Wx: wx}
|
||||
}
|
||||
// other font variant still have the same metrics
|
||||
courierBoldCharMetrics = courierCharMetrics
|
||||
@ -130,15 +130,15 @@ func initCourier() {
|
||||
|
||||
// courierCharMetrics are the font metrics loaded from afms/Courier.afm. See afms/MustRead.html for
|
||||
// license information.
|
||||
var courierCharMetrics map[GlyphName]CharMetrics
|
||||
var courierCharMetrics map[rune]CharMetrics
|
||||
|
||||
// Courier-Bold font metrics loaded from afms/Courier-Bold.afm. See afms/MustRead.html for license information.
|
||||
var courierBoldCharMetrics map[GlyphName]CharMetrics
|
||||
var courierBoldCharMetrics map[rune]CharMetrics
|
||||
|
||||
// courierBoldObliqueCharMetrics are the font metrics loaded from afms/Courier-BoldOblique.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var courierBoldObliqueCharMetrics map[GlyphName]CharMetrics
|
||||
var courierBoldObliqueCharMetrics map[rune]CharMetrics
|
||||
|
||||
// courierObliqueCharMetrics are the font metrics loaded from afms/Courier-Oblique.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var courierObliqueCharMetrics map[GlyphName]CharMetrics
|
||||
var courierObliqueCharMetrics map[rune]CharMetrics
|
||||
|
@ -117,11 +117,11 @@ var helveticaOnce sync.Once
|
||||
|
||||
func initHelvetica() {
|
||||
// unpack font metrics
|
||||
helveticaCharMetrics = make(map[GlyphName]CharMetrics, len(type1CommonGlyphs))
|
||||
helveticaBoldCharMetrics = make(map[GlyphName]CharMetrics, len(type1CommonGlyphs))
|
||||
for i, glyph := range type1CommonGlyphs {
|
||||
helveticaCharMetrics[glyph] = CharMetrics{Wx: float64(helveticaWx[i])}
|
||||
helveticaBoldCharMetrics[glyph] = CharMetrics{Wx: float64(helveticaBoldWx[i])}
|
||||
helveticaCharMetrics = make(map[rune]CharMetrics, len(type1CommonRunes))
|
||||
helveticaBoldCharMetrics = make(map[rune]CharMetrics, len(type1CommonRunes))
|
||||
for i, r := range type1CommonRunes {
|
||||
helveticaCharMetrics[r] = CharMetrics{Wx: float64(helveticaWx[i])}
|
||||
helveticaBoldCharMetrics[r] = CharMetrics{Wx: float64(helveticaBoldWx[i])}
|
||||
}
|
||||
helveticaObliqueCharMetrics = helveticaCharMetrics
|
||||
helveticaBoldObliqueCharMetrics = helveticaBoldCharMetrics
|
||||
@ -129,19 +129,19 @@ func initHelvetica() {
|
||||
|
||||
// helveticaCharMetrics are the font metrics loaded from afms/Helvetica.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var helveticaCharMetrics map[GlyphName]CharMetrics
|
||||
var helveticaCharMetrics map[rune]CharMetrics
|
||||
|
||||
// helveticaBoldCharMetrics are the font metrics loaded from afms/Helvetica-Bold.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var helveticaBoldCharMetrics map[GlyphName]CharMetrics
|
||||
var helveticaBoldCharMetrics map[rune]CharMetrics
|
||||
|
||||
// helveticaBoldObliqueCharMetrics are the font metrics loaded from afms/Helvetica-BoldOblique.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var helveticaBoldObliqueCharMetrics map[GlyphName]CharMetrics
|
||||
var helveticaBoldObliqueCharMetrics map[rune]CharMetrics
|
||||
|
||||
// helveticaObliqueCharMetrics are the font metrics loaded from afms/Helvetica-Oblique.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var helveticaObliqueCharMetrics map[GlyphName]CharMetrics
|
||||
var helveticaObliqueCharMetrics map[rune]CharMetrics
|
||||
|
||||
// helveticaWx are the font metrics loaded from afms/Helvetica.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
|
@ -70,402 +70,402 @@ func NewFontZapfDingbats() StdFont {
|
||||
|
||||
// symbolCharMetrics are the font metrics loaded from afms/Symbol.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var symbolCharMetrics = map[GlyphName]CharMetrics{
|
||||
"Alpha": {Wx: 722.000000},
|
||||
"Beta": {Wx: 667.000000},
|
||||
"Chi": {Wx: 722.000000},
|
||||
"Delta": {Wx: 612.000000},
|
||||
"Epsilon": {Wx: 611.000000},
|
||||
"Eta": {Wx: 722.000000},
|
||||
"Euro": {Wx: 750.000000},
|
||||
"Gamma": {Wx: 603.000000},
|
||||
"Ifraktur": {Wx: 686.000000},
|
||||
"Iota": {Wx: 333.000000},
|
||||
"Kappa": {Wx: 722.000000},
|
||||
"Lambda": {Wx: 686.000000},
|
||||
"Mu": {Wx: 889.000000},
|
||||
"Nu": {Wx: 722.000000},
|
||||
"Omega": {Wx: 768.000000},
|
||||
"Omicron": {Wx: 722.000000},
|
||||
"Phi": {Wx: 763.000000},
|
||||
"Pi": {Wx: 768.000000},
|
||||
"Psi": {Wx: 795.000000},
|
||||
"Rfraktur": {Wx: 795.000000},
|
||||
"Rho": {Wx: 556.000000},
|
||||
"Sigma": {Wx: 592.000000},
|
||||
"Tau": {Wx: 611.000000},
|
||||
"Theta": {Wx: 741.000000},
|
||||
"Upsilon": {Wx: 690.000000},
|
||||
"Upsilon1": {Wx: 620.000000},
|
||||
"Xi": {Wx: 645.000000},
|
||||
"Zeta": {Wx: 611.000000},
|
||||
"aleph": {Wx: 823.000000},
|
||||
"alpha": {Wx: 631.000000},
|
||||
"ampersand": {Wx: 778.000000},
|
||||
"angle": {Wx: 768.000000},
|
||||
"angleleft": {Wx: 329.000000},
|
||||
"angleright": {Wx: 329.000000},
|
||||
"apple": {Wx: 790.000000},
|
||||
"approxequal": {Wx: 549.000000},
|
||||
"arrowboth": {Wx: 1042.000000},
|
||||
"arrowdblboth": {Wx: 1042.000000},
|
||||
"arrowdbldown": {Wx: 603.000000},
|
||||
"arrowdblleft": {Wx: 987.000000},
|
||||
"arrowdblright": {Wx: 987.000000},
|
||||
"arrowdblup": {Wx: 603.000000},
|
||||
"arrowdown": {Wx: 603.000000},
|
||||
"arrowhorizex": {Wx: 1000.000000},
|
||||
"arrowleft": {Wx: 987.000000},
|
||||
"arrowright": {Wx: 987.000000},
|
||||
"arrowup": {Wx: 603.000000},
|
||||
"arrowvertex": {Wx: 603.000000},
|
||||
"asteriskmath": {Wx: 500.000000},
|
||||
"bar": {Wx: 200.000000},
|
||||
"beta": {Wx: 549.000000},
|
||||
"braceex": {Wx: 494.000000},
|
||||
"braceleft": {Wx: 480.000000},
|
||||
"braceleftbt": {Wx: 494.000000},
|
||||
"braceleftmid": {Wx: 494.000000},
|
||||
"bracelefttp": {Wx: 494.000000},
|
||||
"braceright": {Wx: 480.000000},
|
||||
"bracerightbt": {Wx: 494.000000},
|
||||
"bracerightmid": {Wx: 494.000000},
|
||||
"bracerighttp": {Wx: 494.000000},
|
||||
"bracketleft": {Wx: 333.000000},
|
||||
"bracketleftbt": {Wx: 384.000000},
|
||||
"bracketleftex": {Wx: 384.000000},
|
||||
"bracketlefttp": {Wx: 384.000000},
|
||||
"bracketright": {Wx: 333.000000},
|
||||
"bracketrightbt": {Wx: 384.000000},
|
||||
"bracketrightex": {Wx: 384.000000},
|
||||
"bracketrighttp": {Wx: 384.000000},
|
||||
"bullet": {Wx: 460.000000},
|
||||
"carriagereturn": {Wx: 658.000000},
|
||||
"chi": {Wx: 549.000000},
|
||||
"circlemultiply": {Wx: 768.000000},
|
||||
"circleplus": {Wx: 768.000000},
|
||||
"club": {Wx: 753.000000},
|
||||
"colon": {Wx: 278.000000},
|
||||
"comma": {Wx: 250.000000},
|
||||
"congruent": {Wx: 549.000000},
|
||||
"copyrightsans": {Wx: 790.000000},
|
||||
"copyrightserif": {Wx: 790.000000},
|
||||
"degree": {Wx: 400.000000},
|
||||
"delta": {Wx: 494.000000},
|
||||
"diamond": {Wx: 753.000000},
|
||||
"divide": {Wx: 549.000000},
|
||||
"dotmath": {Wx: 250.000000},
|
||||
"eight": {Wx: 500.000000},
|
||||
"element": {Wx: 713.000000},
|
||||
"ellipsis": {Wx: 1000.000000},
|
||||
"emptyset": {Wx: 823.000000},
|
||||
"epsilon": {Wx: 439.000000},
|
||||
"equal": {Wx: 549.000000},
|
||||
"equivalence": {Wx: 549.000000},
|
||||
"eta": {Wx: 603.000000},
|
||||
"exclam": {Wx: 333.000000},
|
||||
"existential": {Wx: 549.000000},
|
||||
"five": {Wx: 500.000000},
|
||||
"florin": {Wx: 500.000000},
|
||||
"four": {Wx: 500.000000},
|
||||
"fraction": {Wx: 167.000000},
|
||||
"gamma": {Wx: 411.000000},
|
||||
"gradient": {Wx: 713.000000},
|
||||
"greater": {Wx: 549.000000},
|
||||
"greaterequal": {Wx: 549.000000},
|
||||
"heart": {Wx: 753.000000},
|
||||
"infinity": {Wx: 713.000000},
|
||||
"integral": {Wx: 274.000000},
|
||||
"integralbt": {Wx: 686.000000},
|
||||
"integralex": {Wx: 686.000000},
|
||||
"integraltp": {Wx: 686.000000},
|
||||
"intersection": {Wx: 768.000000},
|
||||
"iota": {Wx: 329.000000},
|
||||
"kappa": {Wx: 549.000000},
|
||||
"lambda": {Wx: 549.000000},
|
||||
"less": {Wx: 549.000000},
|
||||
"lessequal": {Wx: 549.000000},
|
||||
"logicaland": {Wx: 603.000000},
|
||||
"logicalnot": {Wx: 713.000000},
|
||||
"logicalor": {Wx: 603.000000},
|
||||
"lozenge": {Wx: 494.000000},
|
||||
"minus": {Wx: 549.000000},
|
||||
"minute": {Wx: 247.000000},
|
||||
"mu": {Wx: 576.000000},
|
||||
"multiply": {Wx: 549.000000},
|
||||
"nine": {Wx: 500.000000},
|
||||
"notelement": {Wx: 713.000000},
|
||||
"notequal": {Wx: 549.000000},
|
||||
"notsubset": {Wx: 713.000000},
|
||||
"nu": {Wx: 521.000000},
|
||||
"numbersign": {Wx: 500.000000},
|
||||
"omega": {Wx: 686.000000},
|
||||
"omega1": {Wx: 713.000000},
|
||||
"omicron": {Wx: 549.000000},
|
||||
"one": {Wx: 500.000000},
|
||||
"parenleft": {Wx: 333.000000},
|
||||
"parenleftbt": {Wx: 384.000000},
|
||||
"parenleftex": {Wx: 384.000000},
|
||||
"parenlefttp": {Wx: 384.000000},
|
||||
"parenright": {Wx: 333.000000},
|
||||
"parenrightbt": {Wx: 384.000000},
|
||||
"parenrightex": {Wx: 384.000000},
|
||||
"parenrighttp": {Wx: 384.000000},
|
||||
"partialdiff": {Wx: 494.000000},
|
||||
"percent": {Wx: 833.000000},
|
||||
"period": {Wx: 250.000000},
|
||||
"perpendicular": {Wx: 658.000000},
|
||||
"phi": {Wx: 521.000000},
|
||||
"phi1": {Wx: 603.000000},
|
||||
"pi": {Wx: 549.000000},
|
||||
"plus": {Wx: 549.000000},
|
||||
"plusminus": {Wx: 549.000000},
|
||||
"product": {Wx: 823.000000},
|
||||
"propersubset": {Wx: 713.000000},
|
||||
"propersuperset": {Wx: 713.000000},
|
||||
"proportional": {Wx: 713.000000},
|
||||
"psi": {Wx: 686.000000},
|
||||
"question": {Wx: 444.000000},
|
||||
"radical": {Wx: 549.000000},
|
||||
"radicalex": {Wx: 500.000000},
|
||||
"reflexsubset": {Wx: 713.000000},
|
||||
"reflexsuperset": {Wx: 713.000000},
|
||||
"registersans": {Wx: 790.000000},
|
||||
"registerserif": {Wx: 790.000000},
|
||||
"rho": {Wx: 549.000000},
|
||||
"second": {Wx: 411.000000},
|
||||
"semicolon": {Wx: 278.000000},
|
||||
"seven": {Wx: 500.000000},
|
||||
"sigma": {Wx: 603.000000},
|
||||
"sigma1": {Wx: 439.000000},
|
||||
"similar": {Wx: 549.000000},
|
||||
"six": {Wx: 500.000000},
|
||||
"slash": {Wx: 278.000000},
|
||||
"space": {Wx: 250.000000},
|
||||
"spade": {Wx: 753.000000},
|
||||
"suchthat": {Wx: 439.000000},
|
||||
"summation": {Wx: 713.000000},
|
||||
"tau": {Wx: 439.000000},
|
||||
"therefore": {Wx: 863.000000},
|
||||
"theta": {Wx: 521.000000},
|
||||
"theta1": {Wx: 631.000000},
|
||||
"three": {Wx: 500.000000},
|
||||
"trademarksans": {Wx: 786.000000},
|
||||
"trademarkserif": {Wx: 890.000000},
|
||||
"two": {Wx: 500.000000},
|
||||
"underscore": {Wx: 500.000000},
|
||||
"union": {Wx: 768.000000},
|
||||
"universal": {Wx: 713.000000},
|
||||
"upsilon": {Wx: 576.000000},
|
||||
"weierstrass": {Wx: 987.000000},
|
||||
"xi": {Wx: 493.000000},
|
||||
"zero": {Wx: 500.000000},
|
||||
"zeta": {Wx: 494.000000},
|
||||
var symbolCharMetrics = map[rune]CharMetrics{
|
||||
' ': {Wx: 250},
|
||||
'!': {Wx: 333},
|
||||
'#': {Wx: 500},
|
||||
'%': {Wx: 833},
|
||||
'&': {Wx: 778},
|
||||
'(': {Wx: 333},
|
||||
')': {Wx: 333},
|
||||
'+': {Wx: 549},
|
||||
',': {Wx: 250},
|
||||
'.': {Wx: 250},
|
||||
'/': {Wx: 278},
|
||||
'0': {Wx: 500},
|
||||
'1': {Wx: 500},
|
||||
'2': {Wx: 500},
|
||||
'3': {Wx: 500},
|
||||
'4': {Wx: 500},
|
||||
'5': {Wx: 500},
|
||||
'6': {Wx: 500},
|
||||
'7': {Wx: 500},
|
||||
'8': {Wx: 500},
|
||||
'9': {Wx: 500},
|
||||
':': {Wx: 278},
|
||||
';': {Wx: 278},
|
||||
'<': {Wx: 549},
|
||||
'=': {Wx: 549},
|
||||
'>': {Wx: 549},
|
||||
'?': {Wx: 444},
|
||||
'[': {Wx: 333},
|
||||
']': {Wx: 333},
|
||||
'_': {Wx: 500},
|
||||
'{': {Wx: 480},
|
||||
'|': {Wx: 200},
|
||||
'}': {Wx: 480},
|
||||
'¬': {Wx: 713},
|
||||
'°': {Wx: 400},
|
||||
'±': {Wx: 549},
|
||||
'µ': {Wx: 576},
|
||||
'×': {Wx: 549},
|
||||
'÷': {Wx: 549},
|
||||
'ƒ': {Wx: 500},
|
||||
'Α': {Wx: 722},
|
||||
'Β': {Wx: 667},
|
||||
'Γ': {Wx: 603},
|
||||
'Ε': {Wx: 611},
|
||||
'Ζ': {Wx: 611},
|
||||
'Η': {Wx: 722},
|
||||
'Θ': {Wx: 741},
|
||||
'Ι': {Wx: 333},
|
||||
'Κ': {Wx: 722},
|
||||
'Λ': {Wx: 686},
|
||||
'Μ': {Wx: 889},
|
||||
'Ν': {Wx: 722},
|
||||
'Ξ': {Wx: 645},
|
||||
'Ο': {Wx: 722},
|
||||
'Π': {Wx: 768},
|
||||
'Ρ': {Wx: 556},
|
||||
'Σ': {Wx: 592},
|
||||
'Τ': {Wx: 611},
|
||||
'Υ': {Wx: 690},
|
||||
'Φ': {Wx: 763},
|
||||
'Χ': {Wx: 722},
|
||||
'Ψ': {Wx: 795},
|
||||
'α': {Wx: 631},
|
||||
'β': {Wx: 549},
|
||||
'γ': {Wx: 411},
|
||||
'δ': {Wx: 494},
|
||||
'ε': {Wx: 439},
|
||||
'ζ': {Wx: 494},
|
||||
'η': {Wx: 603},
|
||||
'θ': {Wx: 521},
|
||||
'ι': {Wx: 329},
|
||||
'κ': {Wx: 549},
|
||||
'λ': {Wx: 549},
|
||||
'ν': {Wx: 521},
|
||||
'ξ': {Wx: 493},
|
||||
'ο': {Wx: 549},
|
||||
'π': {Wx: 549},
|
||||
'ρ': {Wx: 549},
|
||||
'ς': {Wx: 439},
|
||||
'σ': {Wx: 603},
|
||||
'τ': {Wx: 439},
|
||||
'υ': {Wx: 576},
|
||||
'φ': {Wx: 521},
|
||||
'χ': {Wx: 549},
|
||||
'ψ': {Wx: 686},
|
||||
'ω': {Wx: 686},
|
||||
'ϑ': {Wx: 631},
|
||||
'ϒ': {Wx: 620},
|
||||
'ϕ': {Wx: 603},
|
||||
'ϖ': {Wx: 713},
|
||||
'•': {Wx: 460},
|
||||
'…': {Wx: 1000},
|
||||
'′': {Wx: 247},
|
||||
'″': {Wx: 411},
|
||||
'⁄': {Wx: 167},
|
||||
'€': {Wx: 750},
|
||||
'ℑ': {Wx: 686},
|
||||
'℘': {Wx: 987},
|
||||
'ℜ': {Wx: 795},
|
||||
'Ω': {Wx: 768},
|
||||
'ℵ': {Wx: 823},
|
||||
'←': {Wx: 987},
|
||||
'↑': {Wx: 603},
|
||||
'→': {Wx: 987},
|
||||
'↓': {Wx: 603},
|
||||
'↔': {Wx: 1042},
|
||||
'↵': {Wx: 658},
|
||||
'⇐': {Wx: 987},
|
||||
'⇑': {Wx: 603},
|
||||
'⇒': {Wx: 987},
|
||||
'⇓': {Wx: 603},
|
||||
'⇔': {Wx: 1042},
|
||||
'∀': {Wx: 713},
|
||||
'∂': {Wx: 494},
|
||||
'∃': {Wx: 549},
|
||||
'∅': {Wx: 823},
|
||||
'∆': {Wx: 612},
|
||||
'∇': {Wx: 713},
|
||||
'∈': {Wx: 713},
|
||||
'∉': {Wx: 713},
|
||||
'∋': {Wx: 439},
|
||||
'∏': {Wx: 823},
|
||||
'∑': {Wx: 713},
|
||||
'−': {Wx: 549},
|
||||
'∗': {Wx: 500},
|
||||
'√': {Wx: 549},
|
||||
'∝': {Wx: 713},
|
||||
'∞': {Wx: 713},
|
||||
'∠': {Wx: 768},
|
||||
'∧': {Wx: 603},
|
||||
'∨': {Wx: 603},
|
||||
'∩': {Wx: 768},
|
||||
'∪': {Wx: 768},
|
||||
'∫': {Wx: 274},
|
||||
'∴': {Wx: 863},
|
||||
'∼': {Wx: 549},
|
||||
'≅': {Wx: 549},
|
||||
'≈': {Wx: 549},
|
||||
'≠': {Wx: 549},
|
||||
'≡': {Wx: 549},
|
||||
'≤': {Wx: 549},
|
||||
'≥': {Wx: 549},
|
||||
'⊂': {Wx: 713},
|
||||
'⊃': {Wx: 713},
|
||||
'⊄': {Wx: 713},
|
||||
'⊆': {Wx: 713},
|
||||
'⊇': {Wx: 713},
|
||||
'⊕': {Wx: 768},
|
||||
'⊗': {Wx: 768},
|
||||
'⊥': {Wx: 658},
|
||||
'⋅': {Wx: 250},
|
||||
'⌠': {Wx: 686},
|
||||
'⌡': {Wx: 686},
|
||||
'〈': {Wx: 329},
|
||||
'〉': {Wx: 329},
|
||||
'◊': {Wx: 494},
|
||||
'♠': {Wx: 753},
|
||||
'♣': {Wx: 753},
|
||||
'♥': {Wx: 753},
|
||||
'♦': {Wx: 753},
|
||||
'\uf6d9': {Wx: 790},
|
||||
'\uf6da': {Wx: 790},
|
||||
'\uf6db': {Wx: 890},
|
||||
'\uf8e5': {Wx: 500},
|
||||
'\uf8e6': {Wx: 603},
|
||||
'\uf8e7': {Wx: 1000},
|
||||
'\uf8e8': {Wx: 790},
|
||||
'\uf8e9': {Wx: 790},
|
||||
'\uf8ea': {Wx: 786},
|
||||
'\uf8eb': {Wx: 384},
|
||||
'\uf8ec': {Wx: 384},
|
||||
'\uf8ed': {Wx: 384},
|
||||
'\uf8ee': {Wx: 384},
|
||||
'\uf8ef': {Wx: 384},
|
||||
'\uf8f0': {Wx: 384},
|
||||
'\uf8f1': {Wx: 494},
|
||||
'\uf8f2': {Wx: 494},
|
||||
'\uf8f3': {Wx: 494},
|
||||
'\uf8f4': {Wx: 494},
|
||||
'\uf8f5': {Wx: 686},
|
||||
'\uf8f6': {Wx: 384},
|
||||
'\uf8f7': {Wx: 384},
|
||||
'\uf8f8': {Wx: 384},
|
||||
'\uf8f9': {Wx: 384},
|
||||
'\uf8fa': {Wx: 384},
|
||||
'\uf8fb': {Wx: 384},
|
||||
'\uf8fc': {Wx: 494},
|
||||
'\uf8fd': {Wx: 494},
|
||||
'\uf8fe': {Wx: 494},
|
||||
'\uf8ff': {Wx: 790},
|
||||
}
|
||||
|
||||
// zapfDingbatsCharMetrics are the font metrics loaded from afms/ZapfDingbats.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var zapfDingbatsCharMetrics = map[GlyphName]CharMetrics{
|
||||
"a1": {Wx: 974.000000},
|
||||
"a10": {Wx: 692.000000},
|
||||
"a100": {Wx: 668.000000},
|
||||
"a101": {Wx: 732.000000},
|
||||
"a102": {Wx: 544.000000},
|
||||
"a103": {Wx: 544.000000},
|
||||
"a104": {Wx: 910.000000},
|
||||
"a105": {Wx: 911.000000},
|
||||
"a106": {Wx: 667.000000},
|
||||
"a107": {Wx: 760.000000},
|
||||
"a108": {Wx: 760.000000},
|
||||
"a109": {Wx: 626.000000},
|
||||
"a11": {Wx: 960.000000},
|
||||
"a110": {Wx: 694.000000},
|
||||
"a111": {Wx: 595.000000},
|
||||
"a112": {Wx: 776.000000},
|
||||
"a117": {Wx: 690.000000},
|
||||
"a118": {Wx: 791.000000},
|
||||
"a119": {Wx: 790.000000},
|
||||
"a12": {Wx: 939.000000},
|
||||
"a120": {Wx: 788.000000},
|
||||
"a121": {Wx: 788.000000},
|
||||
"a122": {Wx: 788.000000},
|
||||
"a123": {Wx: 788.000000},
|
||||
"a124": {Wx: 788.000000},
|
||||
"a125": {Wx: 788.000000},
|
||||
"a126": {Wx: 788.000000},
|
||||
"a127": {Wx: 788.000000},
|
||||
"a128": {Wx: 788.000000},
|
||||
"a129": {Wx: 788.000000},
|
||||
"a13": {Wx: 549.000000},
|
||||
"a130": {Wx: 788.000000},
|
||||
"a131": {Wx: 788.000000},
|
||||
"a132": {Wx: 788.000000},
|
||||
"a133": {Wx: 788.000000},
|
||||
"a134": {Wx: 788.000000},
|
||||
"a135": {Wx: 788.000000},
|
||||
"a136": {Wx: 788.000000},
|
||||
"a137": {Wx: 788.000000},
|
||||
"a138": {Wx: 788.000000},
|
||||
"a139": {Wx: 788.000000},
|
||||
"a14": {Wx: 855.000000},
|
||||
"a140": {Wx: 788.000000},
|
||||
"a141": {Wx: 788.000000},
|
||||
"a142": {Wx: 788.000000},
|
||||
"a143": {Wx: 788.000000},
|
||||
"a144": {Wx: 788.000000},
|
||||
"a145": {Wx: 788.000000},
|
||||
"a146": {Wx: 788.000000},
|
||||
"a147": {Wx: 788.000000},
|
||||
"a148": {Wx: 788.000000},
|
||||
"a149": {Wx: 788.000000},
|
||||
"a15": {Wx: 911.000000},
|
||||
"a150": {Wx: 788.000000},
|
||||
"a151": {Wx: 788.000000},
|
||||
"a152": {Wx: 788.000000},
|
||||
"a153": {Wx: 788.000000},
|
||||
"a154": {Wx: 788.000000},
|
||||
"a155": {Wx: 788.000000},
|
||||
"a156": {Wx: 788.000000},
|
||||
"a157": {Wx: 788.000000},
|
||||
"a158": {Wx: 788.000000},
|
||||
"a159": {Wx: 788.000000},
|
||||
"a16": {Wx: 933.000000},
|
||||
"a160": {Wx: 894.000000},
|
||||
"a161": {Wx: 838.000000},
|
||||
"a162": {Wx: 924.000000},
|
||||
"a163": {Wx: 1016.000000},
|
||||
"a164": {Wx: 458.000000},
|
||||
"a165": {Wx: 924.000000},
|
||||
"a166": {Wx: 918.000000},
|
||||
"a167": {Wx: 927.000000},
|
||||
"a168": {Wx: 928.000000},
|
||||
"a169": {Wx: 928.000000},
|
||||
"a17": {Wx: 945.000000},
|
||||
"a170": {Wx: 834.000000},
|
||||
"a171": {Wx: 873.000000},
|
||||
"a172": {Wx: 828.000000},
|
||||
"a173": {Wx: 924.000000},
|
||||
"a174": {Wx: 917.000000},
|
||||
"a175": {Wx: 930.000000},
|
||||
"a176": {Wx: 931.000000},
|
||||
"a177": {Wx: 463.000000},
|
||||
"a178": {Wx: 883.000000},
|
||||
"a179": {Wx: 836.000000},
|
||||
"a18": {Wx: 974.000000},
|
||||
"a180": {Wx: 867.000000},
|
||||
"a181": {Wx: 696.000000},
|
||||
"a182": {Wx: 874.000000},
|
||||
"a183": {Wx: 760.000000},
|
||||
"a184": {Wx: 946.000000},
|
||||
"a185": {Wx: 865.000000},
|
||||
"a186": {Wx: 967.000000},
|
||||
"a187": {Wx: 831.000000},
|
||||
"a188": {Wx: 873.000000},
|
||||
"a189": {Wx: 927.000000},
|
||||
"a19": {Wx: 755.000000},
|
||||
"a190": {Wx: 970.000000},
|
||||
"a191": {Wx: 918.000000},
|
||||
"a192": {Wx: 748.000000},
|
||||
"a193": {Wx: 836.000000},
|
||||
"a194": {Wx: 771.000000},
|
||||
"a195": {Wx: 888.000000},
|
||||
"a196": {Wx: 748.000000},
|
||||
"a197": {Wx: 771.000000},
|
||||
"a198": {Wx: 888.000000},
|
||||
"a199": {Wx: 867.000000},
|
||||
"a2": {Wx: 961.000000},
|
||||
"a20": {Wx: 846.000000},
|
||||
"a200": {Wx: 696.000000},
|
||||
"a201": {Wx: 874.000000},
|
||||
"a202": {Wx: 974.000000},
|
||||
"a203": {Wx: 762.000000},
|
||||
"a204": {Wx: 759.000000},
|
||||
"a205": {Wx: 509.000000},
|
||||
"a206": {Wx: 410.000000},
|
||||
"a21": {Wx: 762.000000},
|
||||
"a22": {Wx: 761.000000},
|
||||
"a23": {Wx: 571.000000},
|
||||
"a24": {Wx: 677.000000},
|
||||
"a25": {Wx: 763.000000},
|
||||
"a26": {Wx: 760.000000},
|
||||
"a27": {Wx: 759.000000},
|
||||
"a28": {Wx: 754.000000},
|
||||
"a29": {Wx: 786.000000},
|
||||
"a3": {Wx: 980.000000},
|
||||
"a30": {Wx: 788.000000},
|
||||
"a31": {Wx: 788.000000},
|
||||
"a32": {Wx: 790.000000},
|
||||
"a33": {Wx: 793.000000},
|
||||
"a34": {Wx: 794.000000},
|
||||
"a35": {Wx: 816.000000},
|
||||
"a36": {Wx: 823.000000},
|
||||
"a37": {Wx: 789.000000},
|
||||
"a38": {Wx: 841.000000},
|
||||
"a39": {Wx: 823.000000},
|
||||
"a4": {Wx: 719.000000},
|
||||
"a40": {Wx: 833.000000},
|
||||
"a41": {Wx: 816.000000},
|
||||
"a42": {Wx: 831.000000},
|
||||
"a43": {Wx: 923.000000},
|
||||
"a44": {Wx: 744.000000},
|
||||
"a45": {Wx: 723.000000},
|
||||
"a46": {Wx: 749.000000},
|
||||
"a47": {Wx: 790.000000},
|
||||
"a48": {Wx: 792.000000},
|
||||
"a49": {Wx: 695.000000},
|
||||
"a5": {Wx: 789.000000},
|
||||
"a50": {Wx: 776.000000},
|
||||
"a51": {Wx: 768.000000},
|
||||
"a52": {Wx: 792.000000},
|
||||
"a53": {Wx: 759.000000},
|
||||
"a54": {Wx: 707.000000},
|
||||
"a55": {Wx: 708.000000},
|
||||
"a56": {Wx: 682.000000},
|
||||
"a57": {Wx: 701.000000},
|
||||
"a58": {Wx: 826.000000},
|
||||
"a59": {Wx: 815.000000},
|
||||
"a6": {Wx: 494.000000},
|
||||
"a60": {Wx: 789.000000},
|
||||
"a61": {Wx: 789.000000},
|
||||
"a62": {Wx: 707.000000},
|
||||
"a63": {Wx: 687.000000},
|
||||
"a64": {Wx: 696.000000},
|
||||
"a65": {Wx: 689.000000},
|
||||
"a66": {Wx: 786.000000},
|
||||
"a67": {Wx: 787.000000},
|
||||
"a68": {Wx: 713.000000},
|
||||
"a69": {Wx: 791.000000},
|
||||
"a7": {Wx: 552.000000},
|
||||
"a70": {Wx: 785.000000},
|
||||
"a71": {Wx: 791.000000},
|
||||
"a72": {Wx: 873.000000},
|
||||
"a73": {Wx: 761.000000},
|
||||
"a74": {Wx: 762.000000},
|
||||
"a75": {Wx: 759.000000},
|
||||
"a76": {Wx: 892.000000},
|
||||
"a77": {Wx: 892.000000},
|
||||
"a78": {Wx: 788.000000},
|
||||
"a79": {Wx: 784.000000},
|
||||
"a8": {Wx: 537.000000},
|
||||
"a81": {Wx: 438.000000},
|
||||
"a82": {Wx: 138.000000},
|
||||
"a83": {Wx: 277.000000},
|
||||
"a84": {Wx: 415.000000},
|
||||
"a85": {Wx: 509.000000},
|
||||
"a86": {Wx: 410.000000},
|
||||
"a87": {Wx: 234.000000},
|
||||
"a88": {Wx: 234.000000},
|
||||
"a89": {Wx: 390.000000},
|
||||
"a9": {Wx: 577.000000},
|
||||
"a90": {Wx: 390.000000},
|
||||
"a91": {Wx: 276.000000},
|
||||
"a92": {Wx: 276.000000},
|
||||
"a93": {Wx: 317.000000},
|
||||
"a94": {Wx: 317.000000},
|
||||
"a95": {Wx: 334.000000},
|
||||
"a96": {Wx: 334.000000},
|
||||
"a97": {Wx: 392.000000},
|
||||
"a98": {Wx: 392.000000},
|
||||
"a99": {Wx: 668.000000},
|
||||
"space": {Wx: 278.000000},
|
||||
var zapfDingbatsCharMetrics = map[rune]CharMetrics{
|
||||
' ': {Wx: 278},
|
||||
'→': {Wx: 838},
|
||||
'↔': {Wx: 1016},
|
||||
'↕': {Wx: 458},
|
||||
'①': {Wx: 788},
|
||||
'②': {Wx: 788},
|
||||
'③': {Wx: 788},
|
||||
'④': {Wx: 788},
|
||||
'⑤': {Wx: 788},
|
||||
'⑥': {Wx: 788},
|
||||
'⑦': {Wx: 788},
|
||||
'⑧': {Wx: 788},
|
||||
'⑨': {Wx: 788},
|
||||
'⑩': {Wx: 788},
|
||||
'■': {Wx: 761},
|
||||
'▲': {Wx: 892},
|
||||
'▼': {Wx: 892},
|
||||
'◆': {Wx: 788},
|
||||
'●': {Wx: 791},
|
||||
'◗': {Wx: 438},
|
||||
'★': {Wx: 816},
|
||||
'☎': {Wx: 719},
|
||||
'☛': {Wx: 960},
|
||||
'☞': {Wx: 939},
|
||||
'♠': {Wx: 626},
|
||||
'♣': {Wx: 776},
|
||||
'♥': {Wx: 694},
|
||||
'♦': {Wx: 595},
|
||||
'✁': {Wx: 974},
|
||||
'✂': {Wx: 961},
|
||||
'✃': {Wx: 974},
|
||||
'✄': {Wx: 980},
|
||||
'✆': {Wx: 789},
|
||||
'✇': {Wx: 790},
|
||||
'✈': {Wx: 791},
|
||||
'✉': {Wx: 690},
|
||||
'✌': {Wx: 549},
|
||||
'✍': {Wx: 855},
|
||||
'✎': {Wx: 911},
|
||||
'✏': {Wx: 933},
|
||||
'✐': {Wx: 911},
|
||||
'✑': {Wx: 945},
|
||||
'✒': {Wx: 974},
|
||||
'✓': {Wx: 755},
|
||||
'✔': {Wx: 846},
|
||||
'✕': {Wx: 762},
|
||||
'✖': {Wx: 761},
|
||||
'✗': {Wx: 571},
|
||||
'✘': {Wx: 677},
|
||||
'✙': {Wx: 763},
|
||||
'✚': {Wx: 760},
|
||||
'✛': {Wx: 759},
|
||||
'✜': {Wx: 754},
|
||||
'✝': {Wx: 494},
|
||||
'✞': {Wx: 552},
|
||||
'✟': {Wx: 537},
|
||||
'✠': {Wx: 577},
|
||||
'✡': {Wx: 692},
|
||||
'✢': {Wx: 786},
|
||||
'✣': {Wx: 788},
|
||||
'✤': {Wx: 788},
|
||||
'✥': {Wx: 790},
|
||||
'✦': {Wx: 793},
|
||||
'✧': {Wx: 794},
|
||||
'✩': {Wx: 823},
|
||||
'✪': {Wx: 789},
|
||||
'✫': {Wx: 841},
|
||||
'✬': {Wx: 823},
|
||||
'✭': {Wx: 833},
|
||||
'✮': {Wx: 816},
|
||||
'✯': {Wx: 831},
|
||||
'✰': {Wx: 923},
|
||||
'✱': {Wx: 744},
|
||||
'✲': {Wx: 723},
|
||||
'✳': {Wx: 749},
|
||||
'✴': {Wx: 790},
|
||||
'✵': {Wx: 792},
|
||||
'✶': {Wx: 695},
|
||||
'✷': {Wx: 776},
|
||||
'✸': {Wx: 768},
|
||||
'✹': {Wx: 792},
|
||||
'✺': {Wx: 759},
|
||||
'✻': {Wx: 707},
|
||||
'✼': {Wx: 708},
|
||||
'✽': {Wx: 682},
|
||||
'✾': {Wx: 701},
|
||||
'✿': {Wx: 826},
|
||||
'❀': {Wx: 815},
|
||||
'❁': {Wx: 789},
|
||||
'❂': {Wx: 789},
|
||||
'❃': {Wx: 707},
|
||||
'❄': {Wx: 687},
|
||||
'❅': {Wx: 696},
|
||||
'❆': {Wx: 689},
|
||||
'❇': {Wx: 786},
|
||||
'❈': {Wx: 787},
|
||||
'❉': {Wx: 713},
|
||||
'❊': {Wx: 791},
|
||||
'❋': {Wx: 785},
|
||||
'❍': {Wx: 873},
|
||||
'❏': {Wx: 762},
|
||||
'❐': {Wx: 762},
|
||||
'❑': {Wx: 759},
|
||||
'❒': {Wx: 759},
|
||||
'❖': {Wx: 784},
|
||||
'❘': {Wx: 138},
|
||||
'❙': {Wx: 277},
|
||||
'❚': {Wx: 415},
|
||||
'❛': {Wx: 392},
|
||||
'❜': {Wx: 392},
|
||||
'❝': {Wx: 668},
|
||||
'❞': {Wx: 668},
|
||||
'❡': {Wx: 732},
|
||||
'❢': {Wx: 544},
|
||||
'❣': {Wx: 544},
|
||||
'❤': {Wx: 910},
|
||||
'❥': {Wx: 667},
|
||||
'❦': {Wx: 760},
|
||||
'❧': {Wx: 760},
|
||||
'❶': {Wx: 788},
|
||||
'❷': {Wx: 788},
|
||||
'❸': {Wx: 788},
|
||||
'❹': {Wx: 788},
|
||||
'❺': {Wx: 788},
|
||||
'❻': {Wx: 788},
|
||||
'❼': {Wx: 788},
|
||||
'❽': {Wx: 788},
|
||||
'❾': {Wx: 788},
|
||||
'❿': {Wx: 788},
|
||||
'➀': {Wx: 788},
|
||||
'➁': {Wx: 788},
|
||||
'➂': {Wx: 788},
|
||||
'➃': {Wx: 788},
|
||||
'➄': {Wx: 788},
|
||||
'➅': {Wx: 788},
|
||||
'➆': {Wx: 788},
|
||||
'➇': {Wx: 788},
|
||||
'➈': {Wx: 788},
|
||||
'➉': {Wx: 788},
|
||||
'➊': {Wx: 788},
|
||||
'➋': {Wx: 788},
|
||||
'➌': {Wx: 788},
|
||||
'➍': {Wx: 788},
|
||||
'➎': {Wx: 788},
|
||||
'➏': {Wx: 788},
|
||||
'➐': {Wx: 788},
|
||||
'➑': {Wx: 788},
|
||||
'➒': {Wx: 788},
|
||||
'➓': {Wx: 788},
|
||||
'➔': {Wx: 894},
|
||||
'➘': {Wx: 748},
|
||||
'➙': {Wx: 924},
|
||||
'➚': {Wx: 748},
|
||||
'➛': {Wx: 918},
|
||||
'➜': {Wx: 927},
|
||||
'➝': {Wx: 928},
|
||||
'➞': {Wx: 928},
|
||||
'➟': {Wx: 834},
|
||||
'➠': {Wx: 873},
|
||||
'➡': {Wx: 828},
|
||||
'➢': {Wx: 924},
|
||||
'➣': {Wx: 924},
|
||||
'➤': {Wx: 917},
|
||||
'➥': {Wx: 930},
|
||||
'➦': {Wx: 931},
|
||||
'➧': {Wx: 463},
|
||||
'➨': {Wx: 883},
|
||||
'➩': {Wx: 836},
|
||||
'➪': {Wx: 836},
|
||||
'➫': {Wx: 867},
|
||||
'➬': {Wx: 867},
|
||||
'➭': {Wx: 696},
|
||||
'➮': {Wx: 696},
|
||||
'➯': {Wx: 874},
|
||||
'➱': {Wx: 874},
|
||||
'➲': {Wx: 760},
|
||||
'➳': {Wx: 946},
|
||||
'➴': {Wx: 771},
|
||||
'➵': {Wx: 865},
|
||||
'➶': {Wx: 771},
|
||||
'➷': {Wx: 888},
|
||||
'➸': {Wx: 967},
|
||||
'➹': {Wx: 888},
|
||||
'➺': {Wx: 831},
|
||||
'➻': {Wx: 873},
|
||||
'➼': {Wx: 927},
|
||||
'➽': {Wx: 970},
|
||||
'➾': {Wx: 918},
|
||||
'\uf8d7': {Wx: 390},
|
||||
'\uf8d8': {Wx: 390},
|
||||
'\uf8d9': {Wx: 317},
|
||||
'\uf8da': {Wx: 317},
|
||||
'\uf8db': {Wx: 276},
|
||||
'\uf8dc': {Wx: 276},
|
||||
'\uf8dd': {Wx: 509},
|
||||
'\uf8de': {Wx: 509},
|
||||
'\uf8df': {Wx: 410},
|
||||
'\uf8e0': {Wx: 410},
|
||||
'\uf8e1': {Wx: 234},
|
||||
'\uf8e2': {Wx: 234},
|
||||
'\uf8e3': {Wx: 334},
|
||||
'\uf8e4': {Wx: 334},
|
||||
}
|
||||
|
@ -118,33 +118,33 @@ var timesOnce sync.Once
|
||||
|
||||
func initTimes() {
|
||||
// unpack font metrics
|
||||
timesRomanCharMetrics = make(map[GlyphName]CharMetrics, len(type1CommonGlyphs))
|
||||
timesBoldCharMetrics = make(map[GlyphName]CharMetrics, len(type1CommonGlyphs))
|
||||
timesBoldItalicCharMetrics = make(map[GlyphName]CharMetrics, len(type1CommonGlyphs))
|
||||
timesItalicCharMetrics = make(map[GlyphName]CharMetrics, len(type1CommonGlyphs))
|
||||
for i, glyph := range type1CommonGlyphs {
|
||||
timesRomanCharMetrics[glyph] = CharMetrics{Wx: float64(timesRomanWx[i])}
|
||||
timesBoldCharMetrics[glyph] = CharMetrics{Wx: float64(timesBoldWx[i])}
|
||||
timesBoldItalicCharMetrics[glyph] = CharMetrics{Wx: float64(timesBoldItalicWx[i])}
|
||||
timesItalicCharMetrics[glyph] = CharMetrics{Wx: float64(timesItalicWx[i])}
|
||||
timesRomanCharMetrics = make(map[rune]CharMetrics, len(type1CommonRunes))
|
||||
timesBoldCharMetrics = make(map[rune]CharMetrics, len(type1CommonRunes))
|
||||
timesBoldItalicCharMetrics = make(map[rune]CharMetrics, len(type1CommonRunes))
|
||||
timesItalicCharMetrics = make(map[rune]CharMetrics, len(type1CommonRunes))
|
||||
for i, r := range type1CommonRunes {
|
||||
timesRomanCharMetrics[r] = CharMetrics{Wx: float64(timesRomanWx[i])}
|
||||
timesBoldCharMetrics[r] = CharMetrics{Wx: float64(timesBoldWx[i])}
|
||||
timesBoldItalicCharMetrics[r] = CharMetrics{Wx: float64(timesBoldItalicWx[i])}
|
||||
timesItalicCharMetrics[r] = CharMetrics{Wx: float64(timesItalicWx[i])}
|
||||
}
|
||||
}
|
||||
|
||||
// timesRomanCharMetrics are the font metrics loaded from afms/Times-Roman.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var timesRomanCharMetrics map[GlyphName]CharMetrics
|
||||
var timesRomanCharMetrics map[rune]CharMetrics
|
||||
|
||||
// timesBoldCharMetrics are the font metrics loaded from afms/Times-Bold.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var timesBoldCharMetrics map[GlyphName]CharMetrics
|
||||
var timesBoldCharMetrics map[rune]CharMetrics
|
||||
|
||||
// timesBoldItalicCharMetrics are the font metrics loaded from afms/Times-BoldItalic.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var timesBoldItalicCharMetrics map[GlyphName]CharMetrics
|
||||
var timesBoldItalicCharMetrics map[rune]CharMetrics
|
||||
|
||||
// timesItalicCharMetrics font metrics loaded from afms/Times-Italic.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
var timesItalicCharMetrics map[GlyphName]CharMetrics
|
||||
var timesItalicCharMetrics map[rune]CharMetrics
|
||||
|
||||
// timesRomanWx are the font metrics loaded from afms/Times-Roman.afm.
|
||||
// See afms/MustRead.html for license information.
|
||||
|
@ -45,8 +45,10 @@ import (
|
||||
)
|
||||
|
||||
// MakeEncoder returns an encoder built from the tables in `rec`.
|
||||
func (ttf *TtfType) MakeEncoder() (*textencoding.SimpleEncoder, error) {
|
||||
func (ttf *TtfType) MakeEncoder() (textencoding.SimpleEncoder, error) {
|
||||
encoding := make(map[textencoding.CharCode]GlyphName)
|
||||
// TODO(dennwc): this is a bit strange, since TTF may contain more than 256 characters
|
||||
// should probably make a different encoder here
|
||||
for code := textencoding.CharCode(0); code <= 256; code++ {
|
||||
r := rune(code) // TODO(dennwc): make sure this conversion is valid
|
||||
gid, ok := ttf.Chars[r]
|
||||
@ -93,11 +95,14 @@ type TtfType struct {
|
||||
UnderlineThickness int16
|
||||
Xmin, Ymin, Xmax, Ymax int16
|
||||
CapHeight int16
|
||||
Widths []uint16
|
||||
// Widths is a list of glyph widths indexed by GID.
|
||||
Widths []uint16
|
||||
|
||||
// Chars maps rune values (unicode) to GIDs (the indexes in GlyphNames). i.e. GlyphNames[Chars[r]] is
|
||||
// the glyph corresponding to rune r.
|
||||
//
|
||||
// TODO(dennwc): CharCode is currently defined as uint16, but some tables may store 32 bit charcodes
|
||||
// not the case right now, but make sure to update it once we support those tables
|
||||
// TODO(dennwc,peterwilliams97): it should map char codes to GIDs
|
||||
Chars map[rune]GID
|
||||
// GlyphNames is a list of glyphs from the "post" section of the TrueType file.
|
||||
@ -117,6 +122,9 @@ func (ttf *TtfType) MakeToUnicode() *cmap.CMap {
|
||||
glyph := ttf.GlyphNames[gid]
|
||||
|
||||
// TODO(dennwc): 'code' is already a rune; do we need this extra lookup?
|
||||
// TODO(dennwc): this cannot be done here; glyphNames might be empty
|
||||
// the parent font may specify a different encoding
|
||||
// so we should remap on a higher level
|
||||
r, ok := textencoding.GlyphToRune(glyph)
|
||||
if !ok {
|
||||
common.Log.Debug("No rune. code=0x%04x glyph=%q", code, glyph)
|
||||
|
@ -5,7 +5,6 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
@ -84,8 +83,8 @@ endobj
|
||||
t.Errorf("Failed: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(testcase)
|
||||
fmt.Println(outputs)
|
||||
t.Log(testcase)
|
||||
t.Log(outputs)
|
||||
|
||||
if len(outputs) != len(testcase.Expected) {
|
||||
t.Errorf("Failed, output length mismatch")
|
||||
@ -99,5 +98,5 @@ endobj
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%s", stream.Stream)
|
||||
t.Logf("%s", stream.Stream)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user