SickGear/lib/hachoir/parser/misc/pcf.py
JackDandy 980e05cc99 Change Hachoir can't support PY2 so backport their PY3 to prevent a need for system dependant external binaries like mediainfo.
Backported 400 revisions from rev 1de4961-8897c5b (2018-2014).
Move core/benchmark, core/cmd_line, core/memory, core/profiler and core/timeout to core/optional/*
Remove metadata/qt*

PORT: Version 2.0a3 (inline with 3.0a3 @ f80c7d5).
Basic Support for XMP Packets.
tga: improvements to adhere more closely to the spec.
pdf: slightly improved parsing.
rar: fix TypeError on unknown block types.
Add MacRoman win32 codepage.
tiff/exif: support SubIFDs and tiled images.
Add method to export metadata in dictionary.
mpeg_video: don't attempt to parse Stream past length.
mpeg_video: parse ESCR correctly, add SCR value.
Change centralise CustomFragments.
field: don't set parser class if class is None, to enable autodetect.
field: add value/display for CustomFragment.
parser: inline warning to enable tracebacks in debug mode.
Fix empty bytestrings in makePrintable.
Fix contentSize in jpeg.py to account for image_data blocks.
Fix the ELF parser.
Enhance the AR archive parser.
elf parser: fix wrong wrong fields order in parsing little endian section flags.
elf parser: add s390 as a machine type.
Flesh out mp4 parser.

PORT: Version 2.0a1 (inline with 3.0a1).
Major refactoring and PEP8.
Fix ResourceWarning warnings on files. Add a close() method and support for the context manager protocol ("with obj: ...") to parsers, input and output streams.
metadata: get comment from ZIP.
Support for InputIOStream.read(0).
Fix sizeGe when size is None.
Remove unused new_seekable_field_set file.
Remove parser Mapsforge .map.
Remove parser Parallel Realities Starfighter .pak files.
sevenzip: fix for newer archives.
java: update access flags and modifiers for Java 1.7 and update description text for most recent Java.
Support ustar prefix field in tar archives.
Remove file_system* parsers.
Remove misc parsers 3d0, 3ds, gnome_keyring, msoffice*, mstask, ole*, word*.
Remove program parsers macho, nds, prc.
Support non-8bit Character subclasses.
Python parser supports Python 3.7.
Enhance mpeg_ts parser to support MTS/M2TS.
Support for creation date in tiff.
Change don't hardcode errno constant.

PORT: 1.9.1
Internal Only: The following are legacy reference to upstream commit messages.
Relevant changes up to b0a115f8.
Use integer division.
Replace HACHOIR_ERRORS with Exception.
Fix metadata.Data: make it sortable.
Import fixes from e7de492.
PORT: Version 2.0a1 (inline with 3.0a1 @ e9f8fad).
Replace hachoir.core.field with hachoir.field
Replace hachoir.core.stream with hachoir.stream
Remove the compatibility module for PY1.5 to PY2.5.
metadata: support TIFF picture.
metadata: fix string normalization.
metadata: fix datetime regex Fix hachoir bug #57.
FileFromInputStream: fix comparison between None and an int.
InputIOStream: open the file in binary mode.
2018-03-28 00:43:11 +01:00

176 lines
5.9 KiB
Python

"""
X11 Portable Compiled Font (pcf) parser.
Documents:
- Format for X11 pcf bitmap font files
http://fontforge.sourceforge.net/pcf-format.html
(file is based on the X11 sources)
Author: Victor Stinner
Creation date: 2007-03-20
"""
from hachoir.parser import Parser
from hachoir.field import (FieldSet, Enum,
UInt8, UInt32, Bytes, RawBytes, NullBytes,
Bit, Bits, PaddingBits, CString)
from hachoir.core.endian import LITTLE_ENDIAN, BIG_ENDIAN
from hachoir.core.text_handler import textHandler, hexadecimal, filesizeHandler
from hachoir.core.tools import paddingSize
class TOC(FieldSet):
TYPE_NAME = {
0x00000001: "Properties",
0x00000002: "Accelerators",
0x00000004: "Metrics",
0x00000008: "Bitmaps",
0x00000010: "Ink metrics",
0x00000020: "BDF encodings",
0x00000040: "SWidths",
0x00000080: "Glyph names",
0x00000100: "BDF accelerators",
}
FORMAT_NAME = {
0x00000000: "Default",
0x00000200: "Ink bounds",
0x00000100: "Accelerator W ink bounds",
# 0x00000200: "Compressed metrics",
}
def createFields(self):
yield Enum(UInt32(self, "type"), self.TYPE_NAME)
yield UInt32(self, "format")
yield filesizeHandler(UInt32(self, "size"))
yield UInt32(self, "offset")
def createDescription(self):
return "%s at %s (%s)" % (
self["type"].display, self["offset"].value, self["size"].display)
class PropertiesFormat(FieldSet):
static_size = 32
endian = LITTLE_ENDIAN
def createFields(self):
yield Bits(self, "reserved[]", 2)
yield Bit(self, "byte_big_endian")
yield Bit(self, "bit_big_endian")
yield Bits(self, "scan_unit", 2)
yield textHandler(PaddingBits(self, "reserved[]", 26), hexadecimal)
class Property(FieldSet):
def createFields(self):
yield UInt32(self, "name_offset")
yield UInt8(self, "is_string")
yield UInt32(self, "value_offset")
def createDescription(self):
# FIXME: Use link or any better way to read name value
name = self["../name[%s]" % (self.index - 2)].value
return "Property %s" % name
class GlyphNames(FieldSet):
def __init__(self, parent, name, toc, description, size=None):
FieldSet.__init__(self, parent, name, description, size=size)
self.toc = toc
if self["format/byte_big_endian"].value:
self.endian = BIG_ENDIAN
else:
self.endian = LITTLE_ENDIAN
def createFields(self):
yield PropertiesFormat(self, "format")
yield UInt32(self, "count")
offsets = []
for index in xrange(self["count"].value):
offset = UInt32(self, "offset[]")
yield offset
offsets.append(offset.value)
yield UInt32(self, "total_str_length")
offsets.sort()
offset0 = self.current_size // 8
for offset in offsets:
padding = self.seekByte(offset0 + offset)
if padding:
yield padding
yield CString(self, "name[]")
padding = (self.size - self.current_size) // 8
if padding:
yield NullBytes(self, "end_padding", padding)
class Properties(GlyphNames):
def createFields(self):
yield PropertiesFormat(self, "format")
yield UInt32(self, "nb_prop")
properties = []
for index in xrange(self["nb_prop"].value):
property = Property(self, "property[]")
yield property
properties.append(property)
padding = paddingSize(self.current_size // 8, 4)
if padding:
yield NullBytes(self, "padding", padding)
yield UInt32(self, "total_str_length")
properties.sort(key=lambda entry: entry["name_offset"].value)
offset0 = self.current_size // 8
for property in properties:
padding = self.seekByte(offset0 + property["name_offset"].value)
if padding:
yield padding
yield CString(self, "name[]", "Name of %s" % property.name)
if property["is_string"].value:
yield CString(self, "value[]", "Value of %s" % property.name)
padding = (self.size - self.current_size) // 8
if padding:
yield NullBytes(self, "end_padding", padding)
class PcfFile(Parser):
MAGIC = "\1fcp"
PARSER_TAGS = {
"id": "pcf",
"category": "misc",
"file_ext": ("pcf",),
"magic": ((MAGIC, 0),),
"min_size": 32, # FIXME
"description": "X11 Portable Compiled Font (pcf)",
}
endian = LITTLE_ENDIAN
def validate(self):
if self["signature"].value != self.MAGIC:
return "Invalid signature"
return True
def createFields(self):
yield Bytes(self, "signature", 4, r'File signature ("\1pcf")')
yield UInt32(self, "nb_toc")
entries = []
for index in xrange(self["nb_toc"].value):
entry = TOC(self, "toc[]")
yield entry
entries.append(entry)
entries.sort(key=lambda entry: entry["offset"].value)
for entry in entries:
size = entry["size"].value
padding = self.seekByte(entry["offset"].value)
if padding:
yield padding
maxsize = (self.size - self.current_size) // 8
if maxsize < size:
self.warning("Truncate content of %s to %s bytes (was %s)" % (entry.path, maxsize, size))
size = maxsize
if not size:
continue
if entry["type"].value == 1:
yield Properties(self, "properties", entry, "Properties", size=size * 8)
elif entry["type"].value == 128:
yield GlyphNames(self, "glyph_names", entry, "Glyph names", size=size * 8)
else:
yield RawBytes(self, "data[]", size, "Content of %s" % entry.path)