Portable Compiled Format (PCF) font is a bitmap font format originating from X11 Window System. It matches BDF format (which is text-based) closely, but instead being binary and platform-independent (as opposed to previously used SNF binary format) due to introduced features to handle different endianness and bit order.
The overall composition of the format is straightforward: it's more or less classic directory of type-offset-size pointers, pointing to what PCF format calls "tables". Each table carries a certain piece of information related to the font (metadata properties, metrics, bitmaps, mapping of glyphs to characters, etc).
This page hosts a formal specification of Portable Compiled Format (PCF) font using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"bytes"
"io"
)
/**
* Portable Compiled Format (PCF) font is a bitmap font format
* originating from X11 Window System. It matches BDF format (which is
* text-based) closely, but instead being binary and
* platform-independent (as opposed to previously used SNF binary
* format) due to introduced features to handle different endianness
* and bit order.
*
* The overall composition of the format is straightforward: it's more
* or less classic directory of type-offset-size pointers, pointing to
* what PCF format calls "tables". Each table carries a certain
* piece of information related to the font (metadata properties,
* metrics, bitmaps, mapping of glyphs to characters, etc).
* @see <a href="https://fontforge.org/docs/techref/pcf-format.html">Source</a>
*/
type PcfFont_Types int
const (
PcfFont_Types__Properties PcfFont_Types = 1
PcfFont_Types__Accelerators PcfFont_Types = 2
PcfFont_Types__Metrics PcfFont_Types = 4
PcfFont_Types__Bitmaps PcfFont_Types = 8
PcfFont_Types__InkMetrics PcfFont_Types = 16
PcfFont_Types__BdfEncodings PcfFont_Types = 32
PcfFont_Types__Swidths PcfFont_Types = 64
PcfFont_Types__GlyphNames PcfFont_Types = 128
PcfFont_Types__BdfAccelerators PcfFont_Types = 256
)
var values_PcfFont_Types = map[PcfFont_Types]struct{}{1: {}, 2: {}, 4: {}, 8: {}, 16: {}, 32: {}, 64: {}, 128: {}, 256: {}}
func (v PcfFont_Types) isDefined() bool {
_, ok := values_PcfFont_Types[v]
return ok
}
type PcfFont struct {
Magic []byte
NumTables uint32
Tables []*PcfFont_Table
_io *kaitai.Stream
_root *PcfFont
_parent kaitai.Struct
}
func NewPcfFont() *PcfFont {
return &PcfFont{
}
}
func (this PcfFont) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont) Read(io *kaitai.Stream, parent kaitai.Struct, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp1, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp1 = tmp1
this.Magic = tmp1
if !(bytes.Equal(this.Magic, []uint8{1, 102, 99, 112})) {
return kaitai.NewValidationNotEqualError([]uint8{1, 102, 99, 112}, this.Magic, this._io, "/seq/0")
}
tmp2, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumTables = uint32(tmp2)
for i := 0; i < int(this.NumTables); i++ {
_ = i
tmp3 := NewPcfFont_Table()
err = tmp3.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Tables = append(this.Tables, tmp3)
}
return err
}
/**
* Table format specifier, always 4 bytes. Original implementation treats
* it as always little-endian and makes liberal use of bitmasking to parse
* various parts of it.
*
* TODO: this format specification recognizes endianness and bit
* order format bits, but it does not really takes any parsing
* decisions based on them.
* @see <a href="https://fontforge.org/docs/techref/pcf-format.html#file-header">Source</a>
*/
type PcfFont_Format struct {
Padding1 uint64
ScanUnitMask uint64
IsMostSignificantBitFirst bool
IsBigEndian bool
GlyphPadMask uint64
Format uint8
Padding uint16
_io *kaitai.Stream
_root *PcfFont
_parent kaitai.Struct
}
func NewPcfFont_Format() *PcfFont_Format {
return &PcfFont_Format{
}
}
func (this PcfFont_Format) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Format) Read(io *kaitai.Stream, parent kaitai.Struct, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp4, err := this._io.ReadBitsIntBe(2)
if err != nil {
return err
}
this.Padding1 = tmp4
tmp5, err := this._io.ReadBitsIntBe(2)
if err != nil {
return err
}
this.ScanUnitMask = tmp5
tmp6, err := this._io.ReadBitsIntBe(1)
if err != nil {
return err
}
this.IsMostSignificantBitFirst = tmp6 != 0
tmp7, err := this._io.ReadBitsIntBe(1)
if err != nil {
return err
}
this.IsBigEndian = tmp7 != 0
tmp8, err := this._io.ReadBitsIntBe(2)
if err != nil {
return err
}
this.GlyphPadMask = tmp8
this._io.AlignToByte()
tmp9, err := this._io.ReadU1()
if err != nil {
return err
}
this.Format = tmp9
tmp10, err := this._io.ReadU2le()
if err != nil {
return err
}
this.Padding = uint16(tmp10)
return err
}
/**
* If set, then all integers in the table are treated as big-endian
*/
/**
* Table offers a offset + length pointer to a particular
* table. "Type" of table references certain enum. Applications can
* ignore enum values which they don't support.
*/
type PcfFont_Table struct {
Type PcfFont_Types
Format *PcfFont_Format
LenBody uint32
OfsBody uint32
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont
_raw_body []byte
_f_body bool
body interface{}
}
func NewPcfFont_Table() *PcfFont_Table {
return &PcfFont_Table{
}
}
func (this PcfFont_Table) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table) Read(io *kaitai.Stream, parent *PcfFont, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp11, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Type = PcfFont_Types(tmp11)
tmp12 := NewPcfFont_Format()
err = tmp12.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Format = tmp12
tmp13, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenBody = uint32(tmp13)
tmp14, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsBody = uint32(tmp14)
return err
}
func (this *PcfFont_Table) Body() (v interface{}, err error) {
if (this._f_body) {
return this.body, nil
}
this._f_body = true
_pos, err := this._io.Pos()
if err != nil {
return nil, err
}
_, err = this._io.Seek(int64(this.OfsBody), io.SeekStart)
if err != nil {
return nil, err
}
switch (this.Type) {
case PcfFont_Types__BdfEncodings:
tmp15, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return nil, err
}
tmp15 = tmp15
this._raw_body = tmp15
_io__raw_body := kaitai.NewStream(bytes.NewReader(this._raw_body))
tmp16 := NewPcfFont_Table_BdfEncodings()
err = tmp16.Read(_io__raw_body, this, this._root)
if err != nil {
return nil, err
}
this.body = tmp16
case PcfFont_Types__Bitmaps:
tmp17, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return nil, err
}
tmp17 = tmp17
this._raw_body = tmp17
_io__raw_body := kaitai.NewStream(bytes.NewReader(this._raw_body))
tmp18 := NewPcfFont_Table_Bitmaps()
err = tmp18.Read(_io__raw_body, this, this._root)
if err != nil {
return nil, err
}
this.body = tmp18
case PcfFont_Types__GlyphNames:
tmp19, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return nil, err
}
tmp19 = tmp19
this._raw_body = tmp19
_io__raw_body := kaitai.NewStream(bytes.NewReader(this._raw_body))
tmp20 := NewPcfFont_Table_GlyphNames()
err = tmp20.Read(_io__raw_body, this, this._root)
if err != nil {
return nil, err
}
this.body = tmp20
case PcfFont_Types__Properties:
tmp21, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return nil, err
}
tmp21 = tmp21
this._raw_body = tmp21
_io__raw_body := kaitai.NewStream(bytes.NewReader(this._raw_body))
tmp22 := NewPcfFont_Table_Properties()
err = tmp22.Read(_io__raw_body, this, this._root)
if err != nil {
return nil, err
}
this.body = tmp22
case PcfFont_Types__Swidths:
tmp23, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return nil, err
}
tmp23 = tmp23
this._raw_body = tmp23
_io__raw_body := kaitai.NewStream(bytes.NewReader(this._raw_body))
tmp24 := NewPcfFont_Table_Swidths()
err = tmp24.Read(_io__raw_body, this, this._root)
if err != nil {
return nil, err
}
this.body = tmp24
default:
tmp25, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return nil, err
}
tmp25 = tmp25
this._raw_body = tmp25
}
_, err = this._io.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.body, nil
}
/**
* Table that allows mapping of character codes to glyphs present in the
* font. Supports 1-byte and 2-byte character codes.
*
* Note that this mapping is agnostic to character encoding itself - it
* can represent ASCII, Unicode (ISO/IEC 10646), various single-byte
* national encodings, etc. If application cares about it, normally
* encoding will be specified in `properties` table, in the properties named
* `CHARSET_REGISTRY` / `CHARSET_ENCODING`.
* @see <a href="https://fontforge.org/docs/techref/pcf-format.html#the-encoding-table">Source</a>
*/
type PcfFont_Table_BdfEncodings struct {
Format *PcfFont_Format
MinCharOrByte2 uint16
MaxCharOrByte2 uint16
MinByte1 uint16
MaxByte1 uint16
DefaultChar uint16
GlyphIndexes []uint16
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont_Table
}
func NewPcfFont_Table_BdfEncodings() *PcfFont_Table_BdfEncodings {
return &PcfFont_Table_BdfEncodings{
}
}
func (this PcfFont_Table_BdfEncodings) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table_BdfEncodings) Read(io *kaitai.Stream, parent *PcfFont_Table, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp26 := NewPcfFont_Format()
err = tmp26.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Format = tmp26
tmp27, err := this._io.ReadU2le()
if err != nil {
return err
}
this.MinCharOrByte2 = uint16(tmp27)
tmp28, err := this._io.ReadU2le()
if err != nil {
return err
}
this.MaxCharOrByte2 = uint16(tmp28)
tmp29, err := this._io.ReadU2le()
if err != nil {
return err
}
this.MinByte1 = uint16(tmp29)
tmp30, err := this._io.ReadU2le()
if err != nil {
return err
}
this.MaxByte1 = uint16(tmp30)
tmp31, err := this._io.ReadU2le()
if err != nil {
return err
}
this.DefaultChar = uint16(tmp31)
for i := 0; i < int(((this.MaxCharOrByte2 - this.MinCharOrByte2) + 1) * ((this.MaxByte1 - this.MinByte1) + 1)); i++ {
_ = i
tmp32, err := this._io.ReadU2le()
if err != nil {
return err
}
this.GlyphIndexes = append(this.GlyphIndexes, tmp32)
}
return err
}
/**
* Table containing uncompressed glyph bitmaps.
* @see <a href="https://fontforge.org/docs/techref/pcf-format.html#the-bitmap-table">Source</a>
*/
type PcfFont_Table_Bitmaps struct {
Format *PcfFont_Format
NumGlyphs uint32
Offsets []uint32
BitmapSizes []uint32
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont_Table
}
func NewPcfFont_Table_Bitmaps() *PcfFont_Table_Bitmaps {
return &PcfFont_Table_Bitmaps{
}
}
func (this PcfFont_Table_Bitmaps) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table_Bitmaps) Read(io *kaitai.Stream, parent *PcfFont_Table, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp33 := NewPcfFont_Format()
err = tmp33.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Format = tmp33
tmp34, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumGlyphs = uint32(tmp34)
for i := 0; i < int(this.NumGlyphs); i++ {
_ = i
tmp35, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Offsets = append(this.Offsets, tmp35)
}
for i := 0; i < int(4); i++ {
_ = i
tmp36, err := this._io.ReadU4le()
if err != nil {
return err
}
this.BitmapSizes = append(this.BitmapSizes, tmp36)
}
return err
}
/**
* Table containing character names for every glyph.
* @see <a href="https://fontforge.org/docs/techref/pcf-format.html#the-glyph-names-table">Source</a>
*/
type PcfFont_Table_GlyphNames struct {
Format *PcfFont_Format
NumGlyphs uint32
Names []*PcfFont_Table_GlyphNames_StringRef
LenStrings uint32
Strings *BytesWithIo
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont_Table
_raw_Strings []byte
}
func NewPcfFont_Table_GlyphNames() *PcfFont_Table_GlyphNames {
return &PcfFont_Table_GlyphNames{
}
}
func (this PcfFont_Table_GlyphNames) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table_GlyphNames) Read(io *kaitai.Stream, parent *PcfFont_Table, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp37 := NewPcfFont_Format()
err = tmp37.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Format = tmp37
tmp38, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumGlyphs = uint32(tmp38)
for i := 0; i < int(this.NumGlyphs); i++ {
_ = i
tmp39 := NewPcfFont_Table_GlyphNames_StringRef()
err = tmp39.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Names = append(this.Names, tmp39)
}
tmp40, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenStrings = uint32(tmp40)
tmp41, err := this._io.ReadBytes(int(this.LenStrings))
if err != nil {
return err
}
tmp41 = tmp41
this._raw_Strings = tmp41
_io__raw_Strings := kaitai.NewStream(bytes.NewReader(this._raw_Strings))
tmp42 := NewBytesWithIo()
err = tmp42.Read(_io__raw_Strings, nil, nil)
if err != nil {
return err
}
this.Strings = tmp42
return err
}
/**
* Glyph names are represented as string references in strings buffer.
*/
/**
* Strings buffer which contains all glyph names.
*/
type PcfFont_Table_GlyphNames_StringRef struct {
OfsString uint32
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont_Table_GlyphNames
_f_value bool
value string
}
func NewPcfFont_Table_GlyphNames_StringRef() *PcfFont_Table_GlyphNames_StringRef {
return &PcfFont_Table_GlyphNames_StringRef{
}
}
func (this PcfFont_Table_GlyphNames_StringRef) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table_GlyphNames_StringRef) Read(io *kaitai.Stream, parent *PcfFont_Table_GlyphNames, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp43, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsString = uint32(tmp43)
return err
}
func (this *PcfFont_Table_GlyphNames_StringRef) Value() (v string, err error) {
if (this._f_value) {
return this.value, nil
}
this._f_value = true
thisIo := this._parent.Strings._io
_pos, err := thisIo.Pos()
if err != nil {
return "", err
}
_, err = thisIo.Seek(int64(this.OfsString), io.SeekStart)
if err != nil {
return "", err
}
tmp44, err := thisIo.ReadBytesTerm(0, false, true, true)
if err != nil {
return "", err
}
this.value = string(tmp44)
_, err = thisIo.Seek(_pos, io.SeekStart)
if err != nil {
return "", err
}
return this.value, nil
}
/**
* Array of properties (key-value pairs), used to convey different X11
* settings of a font. Key is always an X font atom.
* @see <a href="https://fontforge.org/docs/techref/pcf-format.html#properties-table">Source</a>
*/
type PcfFont_Table_Properties struct {
Format *PcfFont_Format
NumProps uint32
Props []*PcfFont_Table_Properties_Prop
Padding []byte
LenStrings uint32
Strings *BytesWithIo
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont_Table
_raw_Strings []byte
}
func NewPcfFont_Table_Properties() *PcfFont_Table_Properties {
return &PcfFont_Table_Properties{
}
}
func (this PcfFont_Table_Properties) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table_Properties) Read(io *kaitai.Stream, parent *PcfFont_Table, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp45 := NewPcfFont_Format()
err = tmp45.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Format = tmp45
tmp46, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumProps = uint32(tmp46)
for i := 0; i < int(this.NumProps); i++ {
_ = i
tmp47 := NewPcfFont_Table_Properties_Prop()
err = tmp47.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Props = append(this.Props, tmp47)
}
var tmp48 int8;
if (this.NumProps & 3 == 0) {
tmp48 = 0
} else {
tmp48 = 4 - this.NumProps & 3
}
tmp49, err := this._io.ReadBytes(int(tmp48))
if err != nil {
return err
}
tmp49 = tmp49
this.Padding = tmp49
tmp50, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenStrings = uint32(tmp50)
tmp51, err := this._io.ReadBytes(int(this.LenStrings))
if err != nil {
return err
}
tmp51 = tmp51
this._raw_Strings = tmp51
_io__raw_Strings := kaitai.NewStream(bytes.NewReader(this._raw_Strings))
tmp52 := NewBytesWithIo()
err = tmp52.Read(_io__raw_Strings, nil, nil)
if err != nil {
return err
}
this.Strings = tmp52
return err
}
/**
* Strings buffer. Never used directly, but instead is
* addressed by offsets from the properties.
*/
/**
* Property is a key-value pair, "key" being always a
* string and "value" being either a string or a 32-bit
* integer based on an additinal flag (`is_string`).
*
* Simple offset-based mechanism is employed to keep this
* type's sequence fixed-sized and thus have simple access
* to property key/value by index.
*/
type PcfFont_Table_Properties_Prop struct {
OfsName uint32
IsString uint8
ValueOrOfsValue uint32
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont_Table_Properties
_f_intValue bool
intValue uint32
_f_name bool
name string
_f_strValue bool
strValue string
}
func NewPcfFont_Table_Properties_Prop() *PcfFont_Table_Properties_Prop {
return &PcfFont_Table_Properties_Prop{
}
}
func (this PcfFont_Table_Properties_Prop) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table_Properties_Prop) Read(io *kaitai.Stream, parent *PcfFont_Table_Properties, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp53, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsName = uint32(tmp53)
tmp54, err := this._io.ReadU1()
if err != nil {
return err
}
this.IsString = tmp54
tmp55, err := this._io.ReadU4le()
if err != nil {
return err
}
this.ValueOrOfsValue = uint32(tmp55)
return err
}
/**
* Value of the property, if this is an integer value.
*/
func (this *PcfFont_Table_Properties_Prop) IntValue() (v uint32, err error) {
if (this._f_intValue) {
return this.intValue, nil
}
this._f_intValue = true
if (this.IsString == 0) {
this.intValue = uint32(this.ValueOrOfsValue)
}
return this.intValue, nil
}
/**
* Name of the property addressed in the strings buffer.
*/
func (this *PcfFont_Table_Properties_Prop) Name() (v string, err error) {
if (this._f_name) {
return this.name, nil
}
this._f_name = true
thisIo := this._parent.Strings._io
_pos, err := thisIo.Pos()
if err != nil {
return "", err
}
_, err = thisIo.Seek(int64(this.OfsName), io.SeekStart)
if err != nil {
return "", err
}
tmp56, err := thisIo.ReadBytesTerm(0, false, true, true)
if err != nil {
return "", err
}
this.name = string(tmp56)
_, err = thisIo.Seek(_pos, io.SeekStart)
if err != nil {
return "", err
}
return this.name, nil
}
/**
* Value of the property addressed in the strings
* buffer, if this is a string value.
*/
func (this *PcfFont_Table_Properties_Prop) StrValue() (v string, err error) {
if (this._f_strValue) {
return this.strValue, nil
}
this._f_strValue = true
if (this.IsString != 0) {
thisIo := this._parent.Strings._io
_pos, err := thisIo.Pos()
if err != nil {
return "", err
}
_, err = thisIo.Seek(int64(this.ValueOrOfsValue), io.SeekStart)
if err != nil {
return "", err
}
tmp57, err := thisIo.ReadBytesTerm(0, false, true, true)
if err != nil {
return "", err
}
this.strValue = string(tmp57)
_, err = thisIo.Seek(_pos, io.SeekStart)
if err != nil {
return "", err
}
}
return this.strValue, nil
}
/**
* Offset to name in the strings buffer.
*/
/**
* Designates if value is an integer (zero) or a string (non-zero).
*/
/**
* If the value is an integer (`is_string` is false),
* then it's stored here. If the value is a string
* (`is_string` is true), then it stores offset to the
* value in the strings buffer.
*/
/**
* Table containing scalable widths of characters.
* @see <a href="https://fontforge.org/docs/techref/pcf-format.html#the-scalable-widths-table">Source</a>
*/
type PcfFont_Table_Swidths struct {
Format *PcfFont_Format
NumGlyphs uint32
Swidths []uint32
_io *kaitai.Stream
_root *PcfFont
_parent *PcfFont_Table
}
func NewPcfFont_Table_Swidths() *PcfFont_Table_Swidths {
return &PcfFont_Table_Swidths{
}
}
func (this PcfFont_Table_Swidths) IO_() *kaitai.Stream {
return this._io
}
func (this *PcfFont_Table_Swidths) Read(io *kaitai.Stream, parent *PcfFont_Table, root *PcfFont) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp58 := NewPcfFont_Format()
err = tmp58.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Format = tmp58
tmp59, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumGlyphs = uint32(tmp59)
for i := 0; i < int(this.NumGlyphs); i++ {
_ = i
tmp60, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Swidths = append(this.Swidths, tmp60)
}
return err
}
/**
* The scalable width of a character is the width of the corresponding
* PostScript character in em-units (1/1000ths of an em).
*/