mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
980e05cc99
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.
176 lines
5.9 KiB
Python
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)
|