2018-12-07 19:25:48 +02:00
|
|
|
|
/*
|
|
|
|
|
* This file is subject to the terms and conditions defined in
|
|
|
|
|
* file 'LICENSE.md', which is part of this source code package.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package fonts
|
|
|
|
|
|
|
|
|
|
import (
|
2019-05-16 23:44:51 +03:00
|
|
|
|
"github.com/unidoc/unipdf/v3/core"
|
|
|
|
|
"github.com/unidoc/unipdf/v3/internal/textencoding"
|
2018-12-07 19:25:48 +02:00
|
|
|
|
)
|
|
|
|
|
|
2018-12-19 16:55:27 +05:00
|
|
|
|
// StdFontName is a name of a standard font.
|
|
|
|
|
type StdFontName string
|
|
|
|
|
|
2018-12-27 12:17:28 +02:00
|
|
|
|
// FontWeight specified font weight.
|
|
|
|
|
type FontWeight int
|
|
|
|
|
|
|
|
|
|
// Font weights
|
|
|
|
|
const (
|
|
|
|
|
FontWeightMedium FontWeight = iota // Medium
|
|
|
|
|
FontWeightBold // Bold
|
|
|
|
|
FontWeightRoman // Roman
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Descriptor describes geometric properties of a font.
|
|
|
|
|
type Descriptor struct {
|
|
|
|
|
Name StdFontName
|
|
|
|
|
Family string
|
|
|
|
|
Weight FontWeight
|
|
|
|
|
Flags uint
|
|
|
|
|
BBox [4]float64
|
|
|
|
|
ItalicAngle float64
|
|
|
|
|
Ascent float64
|
|
|
|
|
Descent float64
|
|
|
|
|
CapHeight float64
|
|
|
|
|
XHeight float64
|
|
|
|
|
StemV float64
|
|
|
|
|
StemH float64
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 16:55:27 +05:00
|
|
|
|
var stdFonts = make(map[StdFontName]func() StdFont)
|
2018-12-19 13:43:09 +05:00
|
|
|
|
|
2018-12-27 12:17:28 +02:00
|
|
|
|
// IsStdFont check if a name is registered for a standard font.
|
|
|
|
|
func IsStdFont(name StdFontName) bool {
|
|
|
|
|
_, ok := stdFonts[name]
|
|
|
|
|
return ok
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 13:43:09 +05:00
|
|
|
|
// NewStdFontByName creates a new StdFont by registered name. See RegisterStdFont.
|
2018-12-19 16:55:27 +05:00
|
|
|
|
func NewStdFontByName(name StdFontName) (StdFont, bool) {
|
2018-12-19 13:43:09 +05:00
|
|
|
|
fnc, ok := stdFonts[name]
|
|
|
|
|
if !ok {
|
|
|
|
|
return StdFont{}, false
|
|
|
|
|
}
|
|
|
|
|
return fnc(), true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RegisterStdFont registers a given StdFont constructor by font name. Font can then be created with NewStdFontByName.
|
2018-12-27 12:17:28 +02:00
|
|
|
|
func RegisterStdFont(name StdFontName, fnc func() StdFont, aliases ...StdFontName) {
|
2018-12-19 13:43:09 +05:00
|
|
|
|
if _, ok := stdFonts[name]; ok {
|
2018-12-19 16:55:27 +05:00
|
|
|
|
panic("font already registered: " + string(name))
|
2018-12-19 13:43:09 +05:00
|
|
|
|
}
|
|
|
|
|
stdFonts[name] = fnc
|
2018-12-27 12:17:28 +02:00
|
|
|
|
for _, alias := range aliases {
|
|
|
|
|
RegisterStdFont(alias, fnc)
|
|
|
|
|
}
|
2018-12-19 13:43:09 +05:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-15 18:40:48 +05:00
|
|
|
|
var _ Font = StdFont{}
|
2018-12-07 19:25:48 +02:00
|
|
|
|
|
2018-12-15 18:40:48 +05:00
|
|
|
|
// StdFont represents one of the built-in fonts and it is assumed that every reader has access to it.
|
|
|
|
|
type StdFont struct {
|
2018-12-27 12:17:28 +02:00
|
|
|
|
desc Descriptor
|
2019-01-01 22:40:11 +02:00
|
|
|
|
metrics map[rune]CharMetrics
|
2018-12-30 16:18:56 +02:00
|
|
|
|
encoder textencoding.TextEncoder
|
2018-12-07 19:25:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 00:57:10 +00:00
|
|
|
|
// NewStdFont returns a new instance of the font with a default encoder set (StandardEncoding).
|
2019-01-01 22:40:11 +02:00
|
|
|
|
func NewStdFont(desc Descriptor, metrics map[rune]CharMetrics) StdFont {
|
2019-03-26 00:57:10 +00:00
|
|
|
|
return NewStdFontWithEncoding(desc, metrics, textencoding.NewStandardEncoder())
|
2018-12-07 19:25:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-15 18:40:48 +05:00
|
|
|
|
// NewStdFontWithEncoding returns a new instance of the font with a specified encoder.
|
2019-01-01 22:40:11 +02:00
|
|
|
|
func NewStdFontWithEncoding(desc Descriptor, metrics map[rune]CharMetrics, encoder textencoding.TextEncoder) StdFont {
|
2019-04-02 20:57:08 +03:00
|
|
|
|
var nbsp rune = 0xA0
|
|
|
|
|
if _, ok := metrics[nbsp]; !ok {
|
|
|
|
|
// Use same metrics for 0xA0 (no-break space) and 0x20 (space).
|
|
|
|
|
metrics[nbsp] = metrics[0x20]
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-15 18:40:48 +05:00
|
|
|
|
return StdFont{
|
2018-12-27 12:17:28 +02:00
|
|
|
|
desc: desc,
|
2018-12-07 19:25:48 +02:00
|
|
|
|
metrics: metrics,
|
|
|
|
|
encoder: encoder,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Name returns a PDF name of the font.
|
2018-12-15 18:40:48 +05:00
|
|
|
|
func (font StdFont) Name() string {
|
2018-12-27 12:17:28 +02:00
|
|
|
|
return string(font.desc.Name)
|
2018-12-07 19:25:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Encoder returns the font's text encoder.
|
2018-12-15 18:40:48 +05:00
|
|
|
|
func (font StdFont) Encoder() textencoding.TextEncoder {
|
2018-12-07 19:25:48 +02:00
|
|
|
|
return font.encoder
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-28 01:38:48 +02:00
|
|
|
|
// GetRuneMetrics returns character metrics for a given rune.
|
|
|
|
|
func (font StdFont) GetRuneMetrics(r rune) (CharMetrics, bool) {
|
2019-01-01 22:40:11 +02:00
|
|
|
|
metrics, has := font.metrics[r]
|
|
|
|
|
return metrics, has
|
2018-12-07 19:25:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 13:43:09 +05:00
|
|
|
|
// GetMetricsTable is a method specific to standard fonts. It returns the metrics table of all glyphs.
|
|
|
|
|
// Caller should not modify the table.
|
2019-01-01 22:40:11 +02:00
|
|
|
|
func (font StdFont) GetMetricsTable() map[rune]CharMetrics {
|
2018-12-19 13:43:09 +05:00
|
|
|
|
return font.metrics
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-27 12:17:28 +02:00
|
|
|
|
// Descriptor returns a font descriptor.
|
|
|
|
|
func (font StdFont) Descriptor() Descriptor {
|
|
|
|
|
return font.desc
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 19:25:48 +02:00
|
|
|
|
// ToPdfObject returns a primitive PDF object representation of the font.
|
2018-12-15 18:40:48 +05:00
|
|
|
|
func (font StdFont) ToPdfObject() core.PdfObject {
|
2018-12-07 19:25:48 +02:00
|
|
|
|
fontDict := core.MakeDict()
|
|
|
|
|
fontDict.Set("Type", core.MakeName("Font"))
|
|
|
|
|
fontDict.Set("Subtype", core.MakeName("Type1"))
|
2018-12-19 16:55:27 +05:00
|
|
|
|
fontDict.Set("BaseFont", core.MakeName(font.Name()))
|
2018-12-07 19:25:48 +02:00
|
|
|
|
fontDict.Set("Encoding", font.encoder.ToPdfObject())
|
|
|
|
|
|
|
|
|
|
return core.MakeIndirectObject(fontDict)
|
|
|
|
|
}
|
2018-12-07 21:33:15 +02:00
|
|
|
|
|
2019-01-01 22:40:11 +02:00
|
|
|
|
// 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',
|
2018-12-07 21:33:15 +02:00
|
|
|
|
}
|