Merge pull request #281 from dennwc/encodings

Refactor encodings
This commit is contained in:
Gunnsteinn Hall 2019-01-05 17:27:04 +00:00 committed by GitHub
commit 098019ac2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1608 additions and 2810 deletions

19
Gopkg.lock generated
View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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]
}
}
}

View File

@ -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))
}
}
}

View File

@ -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))...)
}
}

View File

@ -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
}

View File

@ -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")
}
}
}
}

View 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)
}

View File

@ -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)
}

View File

@ -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)
}
})
}
}

View File

@ -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

View 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: 'ˇ',
}

View 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: '➾',
}

View 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: 'ß',
}

View File

@ -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)
}
}
}

View 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: 'ÿ',
}

View File

@ -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

View File

@ -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
}

View File

@ -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()
}

View File

@ -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"

View File

@ -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
}

View File

@ -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
}

View File

@ -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:

View File

@ -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
}

View File

@ -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(),
}
}

View File

@ -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
}

View File

@ -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`.

View File

@ -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',
}

View File

@ -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

View File

@ -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.

View File

@ -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},
}

View File

@ -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.

View File

@ -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)

View File

@ -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)
}