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.
All parsing code for C++98/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.pcf", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
pcf_font_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.magic() // => get magic
#ifndef PCF_FONT_H_
#define PCF_FONT_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include "bytes_with_io.h"
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
class bytes_with_io_t;
/**
* 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).
* \sa https://fontforge.org/docs/techref/pcf-format.html Source
*/
class pcf_font_t : public kaitai::kstruct {
public:
class table_t;
class format_t;
enum types_t {
TYPES_PROPERTIES = 1,
TYPES_ACCELERATORS = 2,
TYPES_METRICS = 4,
TYPES_BITMAPS = 8,
TYPES_INK_METRICS = 16,
TYPES_BDF_ENCODINGS = 32,
TYPES_SWIDTHS = 64,
TYPES_GLYPH_NAMES = 128,
TYPES_BDF_ACCELERATORS = 256
};
pcf_font_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~pcf_font_t();
/**
* 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.
*/
class table_t : public kaitai::kstruct {
public:
class swidths_t;
class properties_t;
class bdf_encodings_t;
class glyph_names_t;
class bitmaps_t;
table_t(kaitai::kstream* p__io, pcf_font_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~table_t();
/**
* Table containing scalable widths of characters.
* \sa https://fontforge.org/docs/techref/pcf-format.html#the-scalable-widths-table Source
*/
class swidths_t : public kaitai::kstruct {
public:
swidths_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~swidths_t();
private:
format_t* m_format;
uint32_t m_num_glyphs;
std::vector<uint32_t>* m_swidths;
pcf_font_t* m__root;
pcf_font_t::table_t* m__parent;
public:
format_t* format() const { return m_format; }
uint32_t num_glyphs() const { return m_num_glyphs; }
/**
* The scalable width of a character is the width of the corresponding
* PostScript character in em-units (1/1000ths of an em).
*/
std::vector<uint32_t>* swidths() const { return m_swidths; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t::table_t* _parent() const { return m__parent; }
};
/**
* Array of properties (key-value pairs), used to convey different X11
* settings of a font. Key is always an X font atom.
* \sa https://fontforge.org/docs/techref/pcf-format.html#properties-table Source
*/
class properties_t : public kaitai::kstruct {
public:
class prop_t;
properties_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~properties_t();
/**
* 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.
*/
class prop_t : public kaitai::kstruct {
public:
prop_t(kaitai::kstream* p__io, pcf_font_t::table_t::properties_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~prop_t();
private:
bool f_name;
std::string m_name;
public:
/**
* Name of the property addressed in the strings buffer.
*/
std::string name();
private:
bool f_str_value;
std::string m_str_value;
bool n_str_value;
public:
bool _is_null_str_value() { str_value(); return n_str_value; };
private:
public:
/**
* Value of the property addressed in the strings
* buffer, if this is a string value.
*/
std::string str_value();
private:
bool f_int_value;
uint32_t m_int_value;
bool n_int_value;
public:
bool _is_null_int_value() { int_value(); return n_int_value; };
private:
public:
/**
* Value of the property, if this is an integer value.
*/
uint32_t int_value();
private:
uint32_t m_ofs_name;
uint8_t m_is_string;
uint32_t m_value_or_ofs_value;
pcf_font_t* m__root;
pcf_font_t::table_t::properties_t* m__parent;
public:
/**
* Offset to name in the strings buffer.
*/
uint32_t ofs_name() const { return m_ofs_name; }
/**
* Designates if value is an integer (zero) or a string (non-zero).
*/
uint8_t is_string() const { return m_is_string; }
/**
* 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.
*/
uint32_t value_or_ofs_value() const { return m_value_or_ofs_value; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t::table_t::properties_t* _parent() const { return m__parent; }
};
private:
format_t* m_format;
uint32_t m_num_props;
std::vector<prop_t*>* m_props;
std::string m_padding;
uint32_t m_len_strings;
bytes_with_io_t* m_strings;
pcf_font_t* m__root;
pcf_font_t::table_t* m__parent;
std::string m__raw_strings;
kaitai::kstream* m__io__raw_strings;
public:
format_t* format() const { return m_format; }
uint32_t num_props() const { return m_num_props; }
std::vector<prop_t*>* props() const { return m_props; }
std::string padding() const { return m_padding; }
uint32_t len_strings() const { return m_len_strings; }
/**
* Strings buffer. Never used directly, but instead is
* addressed by offsets from the properties.
*/
bytes_with_io_t* strings() const { return m_strings; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t::table_t* _parent() const { return m__parent; }
std::string _raw_strings() const { return m__raw_strings; }
kaitai::kstream* _io__raw_strings() const { return m__io__raw_strings; }
};
/**
* 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`.
* \sa https://fontforge.org/docs/techref/pcf-format.html#the-encoding-table Source
*/
class bdf_encodings_t : public kaitai::kstruct {
public:
bdf_encodings_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~bdf_encodings_t();
private:
format_t* m_format;
uint16_t m_min_char_or_byte2;
uint16_t m_max_char_or_byte2;
uint16_t m_min_byte1;
uint16_t m_max_byte1;
uint16_t m_default_char;
std::vector<uint16_t>* m_glyph_indexes;
pcf_font_t* m__root;
pcf_font_t::table_t* m__parent;
public:
format_t* format() const { return m_format; }
uint16_t min_char_or_byte2() const { return m_min_char_or_byte2; }
uint16_t max_char_or_byte2() const { return m_max_char_or_byte2; }
uint16_t min_byte1() const { return m_min_byte1; }
uint16_t max_byte1() const { return m_max_byte1; }
uint16_t default_char() const { return m_default_char; }
std::vector<uint16_t>* glyph_indexes() const { return m_glyph_indexes; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t::table_t* _parent() const { return m__parent; }
};
/**
* Table containing character names for every glyph.
* \sa https://fontforge.org/docs/techref/pcf-format.html#the-glyph-names-table Source
*/
class glyph_names_t : public kaitai::kstruct {
public:
class string_ref_t;
glyph_names_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~glyph_names_t();
class string_ref_t : public kaitai::kstruct {
public:
string_ref_t(kaitai::kstream* p__io, pcf_font_t::table_t::glyph_names_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~string_ref_t();
private:
bool f_value;
std::string m_value;
public:
std::string value();
private:
uint32_t m_ofs_string;
pcf_font_t* m__root;
pcf_font_t::table_t::glyph_names_t* m__parent;
public:
uint32_t ofs_string() const { return m_ofs_string; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t::table_t::glyph_names_t* _parent() const { return m__parent; }
};
private:
format_t* m_format;
uint32_t m_num_glyphs;
std::vector<string_ref_t*>* m_names;
uint32_t m_len_strings;
bytes_with_io_t* m_strings;
pcf_font_t* m__root;
pcf_font_t::table_t* m__parent;
std::string m__raw_strings;
kaitai::kstream* m__io__raw_strings;
public:
format_t* format() const { return m_format; }
uint32_t num_glyphs() const { return m_num_glyphs; }
/**
* Glyph names are represented as string references in strings buffer.
*/
std::vector<string_ref_t*>* names() const { return m_names; }
uint32_t len_strings() const { return m_len_strings; }
/**
* Strings buffer which contains all glyph names.
*/
bytes_with_io_t* strings() const { return m_strings; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t::table_t* _parent() const { return m__parent; }
std::string _raw_strings() const { return m__raw_strings; }
kaitai::kstream* _io__raw_strings() const { return m__io__raw_strings; }
};
/**
* Table containing uncompressed glyph bitmaps.
* \sa https://fontforge.org/docs/techref/pcf-format.html#the-bitmap-table Source
*/
class bitmaps_t : public kaitai::kstruct {
public:
bitmaps_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~bitmaps_t();
private:
format_t* m_format;
uint32_t m_num_glyphs;
std::vector<uint32_t>* m_offsets;
std::vector<uint32_t>* m_bitmap_sizes;
pcf_font_t* m__root;
pcf_font_t::table_t* m__parent;
public:
format_t* format() const { return m_format; }
uint32_t num_glyphs() const { return m_num_glyphs; }
std::vector<uint32_t>* offsets() const { return m_offsets; }
std::vector<uint32_t>* bitmap_sizes() const { return m_bitmap_sizes; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t::table_t* _parent() const { return m__parent; }
};
private:
bool f_body;
kaitai::kstruct* m_body;
bool n_body;
public:
bool _is_null_body() { body(); return n_body; };
private:
public:
kaitai::kstruct* body();
private:
types_t m_type;
format_t* m_format;
uint32_t m_len_body;
uint32_t m_ofs_body;
pcf_font_t* m__root;
pcf_font_t* m__parent;
std::string m__raw_body;
kaitai::kstream* m__io__raw_body;
public:
types_t type() const { return m_type; }
format_t* format() const { return m_format; }
uint32_t len_body() const { return m_len_body; }
uint32_t ofs_body() const { return m_ofs_body; }
pcf_font_t* _root() const { return m__root; }
pcf_font_t* _parent() const { return m__parent; }
std::string _raw_body() const { return m__raw_body; }
kaitai::kstream* _io__raw_body() const { return m__io__raw_body; }
};
/**
* 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.
* \sa https://fontforge.org/docs/techref/pcf-format.html#file-header Source
*/
class format_t : public kaitai::kstruct {
public:
format_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, pcf_font_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~format_t();
private:
uint64_t m_padding1;
uint64_t m_scan_unit_mask;
bool m_is_most_significant_bit_first;
bool m_is_big_endian;
uint64_t m_glyph_pad_mask;
uint8_t m_format;
uint16_t m_padding;
pcf_font_t* m__root;
kaitai::kstruct* m__parent;
public:
uint64_t padding1() const { return m_padding1; }
uint64_t scan_unit_mask() const { return m_scan_unit_mask; }
bool is_most_significant_bit_first() const { return m_is_most_significant_bit_first; }
/**
* If set, then all integers in the table are treated as big-endian
*/
bool is_big_endian() const { return m_is_big_endian; }
uint64_t glyph_pad_mask() const { return m_glyph_pad_mask; }
uint8_t format() const { return m_format; }
uint16_t padding() const { return m_padding; }
pcf_font_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
private:
std::string m_magic;
uint32_t m_num_tables;
std::vector<table_t*>* m_tables;
pcf_font_t* m__root;
kaitai::kstruct* m__parent;
public:
std::string magic() const { return m_magic; }
uint32_t num_tables() const { return m_num_tables; }
std::vector<table_t*>* tables() const { return m_tables; }
pcf_font_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // PCF_FONT_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "pcf_font.h"
#include "kaitai/exceptions.h"
pcf_font_t::pcf_font_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_tables = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::_read() {
m_magic = m__io->read_bytes(4);
if (!(magic() == std::string("\x01\x66\x63\x70", 4))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x01\x66\x63\x70", 4), magic(), _io(), std::string("/seq/0"));
}
m_num_tables = m__io->read_u4le();
m_tables = new std::vector<table_t*>();
const int l_tables = num_tables();
for (int i = 0; i < l_tables; i++) {
m_tables->push_back(new table_t(m__io, this, m__root));
}
}
pcf_font_t::~pcf_font_t() {
_clean_up();
}
void pcf_font_t::_clean_up() {
if (m_tables) {
for (std::vector<table_t*>::iterator it = m_tables->begin(); it != m_tables->end(); ++it) {
delete *it;
}
delete m_tables; m_tables = 0;
}
}
pcf_font_t::table_t::table_t(kaitai::kstream* p__io, pcf_font_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_format = 0;
m__io__raw_body = 0;
f_body = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::_read() {
m_type = static_cast<pcf_font_t::types_t>(m__io->read_u4le());
m_format = new format_t(m__io, this, m__root);
m_len_body = m__io->read_u4le();
m_ofs_body = m__io->read_u4le();
}
pcf_font_t::table_t::~table_t() {
_clean_up();
}
void pcf_font_t::table_t::_clean_up() {
if (m_format) {
delete m_format; m_format = 0;
}
if (f_body && !n_body) {
if (m__io__raw_body) {
delete m__io__raw_body; m__io__raw_body = 0;
}
if (m_body) {
delete m_body; m_body = 0;
}
}
}
pcf_font_t::table_t::swidths_t::swidths_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_format = 0;
m_swidths = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::swidths_t::_read() {
m_format = new format_t(m__io, this, m__root);
m_num_glyphs = m__io->read_u4le();
m_swidths = new std::vector<uint32_t>();
const int l_swidths = num_glyphs();
for (int i = 0; i < l_swidths; i++) {
m_swidths->push_back(m__io->read_u4le());
}
}
pcf_font_t::table_t::swidths_t::~swidths_t() {
_clean_up();
}
void pcf_font_t::table_t::swidths_t::_clean_up() {
if (m_format) {
delete m_format; m_format = 0;
}
if (m_swidths) {
delete m_swidths; m_swidths = 0;
}
}
pcf_font_t::table_t::properties_t::properties_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_format = 0;
m_props = 0;
m_strings = 0;
m__io__raw_strings = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::properties_t::_read() {
m_format = new format_t(m__io, this, m__root);
m_num_props = m__io->read_u4le();
m_props = new std::vector<prop_t*>();
const int l_props = num_props();
for (int i = 0; i < l_props; i++) {
m_props->push_back(new prop_t(m__io, this, m__root));
}
m_padding = m__io->read_bytes((((num_props() & 3) == 0) ? (0) : ((4 - (num_props() & 3)))));
m_len_strings = m__io->read_u4le();
m__raw_strings = m__io->read_bytes(len_strings());
m__io__raw_strings = new kaitai::kstream(m__raw_strings);
m_strings = new bytes_with_io_t(m__io__raw_strings);
}
pcf_font_t::table_t::properties_t::~properties_t() {
_clean_up();
}
void pcf_font_t::table_t::properties_t::_clean_up() {
if (m_format) {
delete m_format; m_format = 0;
}
if (m_props) {
for (std::vector<prop_t*>::iterator it = m_props->begin(); it != m_props->end(); ++it) {
delete *it;
}
delete m_props; m_props = 0;
}
if (m__io__raw_strings) {
delete m__io__raw_strings; m__io__raw_strings = 0;
}
if (m_strings) {
delete m_strings; m_strings = 0;
}
}
pcf_font_t::table_t::properties_t::prop_t::prop_t(kaitai::kstream* p__io, pcf_font_t::table_t::properties_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_name = false;
f_str_value = false;
f_int_value = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::properties_t::prop_t::_read() {
m_ofs_name = m__io->read_u4le();
m_is_string = m__io->read_u1();
m_value_or_ofs_value = m__io->read_u4le();
}
pcf_font_t::table_t::properties_t::prop_t::~prop_t() {
_clean_up();
}
void pcf_font_t::table_t::properties_t::prop_t::_clean_up() {
if (f_name) {
}
if (f_str_value && !n_str_value) {
}
}
std::string pcf_font_t::table_t::properties_t::prop_t::name() {
if (f_name)
return m_name;
kaitai::kstream *io = _parent()->strings()->_io();
std::streampos _pos = io->pos();
io->seek(ofs_name());
m_name = kaitai::kstream::bytes_to_str(io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
io->seek(_pos);
f_name = true;
return m_name;
}
std::string pcf_font_t::table_t::properties_t::prop_t::str_value() {
if (f_str_value)
return m_str_value;
n_str_value = true;
if (is_string() != 0) {
n_str_value = false;
kaitai::kstream *io = _parent()->strings()->_io();
std::streampos _pos = io->pos();
io->seek(value_or_ofs_value());
m_str_value = kaitai::kstream::bytes_to_str(io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
io->seek(_pos);
f_str_value = true;
}
return m_str_value;
}
uint32_t pcf_font_t::table_t::properties_t::prop_t::int_value() {
if (f_int_value)
return m_int_value;
n_int_value = true;
if (is_string() == 0) {
n_int_value = false;
m_int_value = value_or_ofs_value();
}
f_int_value = true;
return m_int_value;
}
pcf_font_t::table_t::bdf_encodings_t::bdf_encodings_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_format = 0;
m_glyph_indexes = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::bdf_encodings_t::_read() {
m_format = new format_t(m__io, this, m__root);
m_min_char_or_byte2 = m__io->read_u2le();
m_max_char_or_byte2 = m__io->read_u2le();
m_min_byte1 = m__io->read_u2le();
m_max_byte1 = m__io->read_u2le();
m_default_char = m__io->read_u2le();
m_glyph_indexes = new std::vector<uint16_t>();
const int l_glyph_indexes = (((max_char_or_byte2() - min_char_or_byte2()) + 1) * ((max_byte1() - min_byte1()) + 1));
for (int i = 0; i < l_glyph_indexes; i++) {
m_glyph_indexes->push_back(m__io->read_u2le());
}
}
pcf_font_t::table_t::bdf_encodings_t::~bdf_encodings_t() {
_clean_up();
}
void pcf_font_t::table_t::bdf_encodings_t::_clean_up() {
if (m_format) {
delete m_format; m_format = 0;
}
if (m_glyph_indexes) {
delete m_glyph_indexes; m_glyph_indexes = 0;
}
}
pcf_font_t::table_t::glyph_names_t::glyph_names_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_format = 0;
m_names = 0;
m_strings = 0;
m__io__raw_strings = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::glyph_names_t::_read() {
m_format = new format_t(m__io, this, m__root);
m_num_glyphs = m__io->read_u4le();
m_names = new std::vector<string_ref_t*>();
const int l_names = num_glyphs();
for (int i = 0; i < l_names; i++) {
m_names->push_back(new string_ref_t(m__io, this, m__root));
}
m_len_strings = m__io->read_u4le();
m__raw_strings = m__io->read_bytes(len_strings());
m__io__raw_strings = new kaitai::kstream(m__raw_strings);
m_strings = new bytes_with_io_t(m__io__raw_strings);
}
pcf_font_t::table_t::glyph_names_t::~glyph_names_t() {
_clean_up();
}
void pcf_font_t::table_t::glyph_names_t::_clean_up() {
if (m_format) {
delete m_format; m_format = 0;
}
if (m_names) {
for (std::vector<string_ref_t*>::iterator it = m_names->begin(); it != m_names->end(); ++it) {
delete *it;
}
delete m_names; m_names = 0;
}
if (m__io__raw_strings) {
delete m__io__raw_strings; m__io__raw_strings = 0;
}
if (m_strings) {
delete m_strings; m_strings = 0;
}
}
pcf_font_t::table_t::glyph_names_t::string_ref_t::string_ref_t(kaitai::kstream* p__io, pcf_font_t::table_t::glyph_names_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_value = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::glyph_names_t::string_ref_t::_read() {
m_ofs_string = m__io->read_u4le();
}
pcf_font_t::table_t::glyph_names_t::string_ref_t::~string_ref_t() {
_clean_up();
}
void pcf_font_t::table_t::glyph_names_t::string_ref_t::_clean_up() {
if (f_value) {
}
}
std::string pcf_font_t::table_t::glyph_names_t::string_ref_t::value() {
if (f_value)
return m_value;
kaitai::kstream *io = _parent()->strings()->_io();
std::streampos _pos = io->pos();
io->seek(ofs_string());
m_value = kaitai::kstream::bytes_to_str(io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
io->seek(_pos);
f_value = true;
return m_value;
}
pcf_font_t::table_t::bitmaps_t::bitmaps_t(kaitai::kstream* p__io, pcf_font_t::table_t* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_format = 0;
m_offsets = 0;
m_bitmap_sizes = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::table_t::bitmaps_t::_read() {
m_format = new format_t(m__io, this, m__root);
m_num_glyphs = m__io->read_u4le();
m_offsets = new std::vector<uint32_t>();
const int l_offsets = num_glyphs();
for (int i = 0; i < l_offsets; i++) {
m_offsets->push_back(m__io->read_u4le());
}
m_bitmap_sizes = new std::vector<uint32_t>();
const int l_bitmap_sizes = 4;
for (int i = 0; i < l_bitmap_sizes; i++) {
m_bitmap_sizes->push_back(m__io->read_u4le());
}
}
pcf_font_t::table_t::bitmaps_t::~bitmaps_t() {
_clean_up();
}
void pcf_font_t::table_t::bitmaps_t::_clean_up() {
if (m_format) {
delete m_format; m_format = 0;
}
if (m_offsets) {
delete m_offsets; m_offsets = 0;
}
if (m_bitmap_sizes) {
delete m_bitmap_sizes; m_bitmap_sizes = 0;
}
}
kaitai::kstruct* pcf_font_t::table_t::body() {
if (f_body)
return m_body;
std::streampos _pos = m__io->pos();
m__io->seek(ofs_body());
n_body = true;
switch (type()) {
case pcf_font_t::TYPES_PROPERTIES: {
n_body = false;
m__raw_body = m__io->read_bytes(len_body());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new properties_t(m__io__raw_body, this, m__root);
break;
}
case pcf_font_t::TYPES_BDF_ENCODINGS: {
n_body = false;
m__raw_body = m__io->read_bytes(len_body());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new bdf_encodings_t(m__io__raw_body, this, m__root);
break;
}
case pcf_font_t::TYPES_SWIDTHS: {
n_body = false;
m__raw_body = m__io->read_bytes(len_body());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new swidths_t(m__io__raw_body, this, m__root);
break;
}
case pcf_font_t::TYPES_GLYPH_NAMES: {
n_body = false;
m__raw_body = m__io->read_bytes(len_body());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new glyph_names_t(m__io__raw_body, this, m__root);
break;
}
case pcf_font_t::TYPES_BITMAPS: {
n_body = false;
m__raw_body = m__io->read_bytes(len_body());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new bitmaps_t(m__io__raw_body, this, m__root);
break;
}
default: {
m__raw_body = m__io->read_bytes(len_body());
break;
}
}
m__io->seek(_pos);
f_body = true;
return m_body;
}
pcf_font_t::format_t::format_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, pcf_font_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void pcf_font_t::format_t::_read() {
m_padding1 = m__io->read_bits_int_be(2);
m_scan_unit_mask = m__io->read_bits_int_be(2);
m_is_most_significant_bit_first = m__io->read_bits_int_be(1);
m_is_big_endian = m__io->read_bits_int_be(1);
m_glyph_pad_mask = m__io->read_bits_int_be(2);
m__io->align_to_byte();
m_format = m__io->read_u1();
m_padding = m__io->read_u2le();
}
pcf_font_t::format_t::~format_t() {
_clean_up();
}
void pcf_font_t::format_t::_clean_up() {
}