Last active
April 12, 2018 12:48
-
-
Save ebraminio/3b1c91ce605cc93dba59d984ecece7b7 to your computer and use it in GitHub Desktop.
dfont and resourcefork parsing, ported fonttools code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Derived from fonttools, all rights of this goes to fonttools projects | |
from fontTools.misc import sstruct | |
import struct | |
ResourceForkHeader = """ | |
> # big endian | |
dataOffset: L | |
mapOffset: L | |
dataLen: L | |
mapLen: L | |
""" | |
ResourceForkHeaderSize = sstruct.calcsize(ResourceForkHeader) | |
ResourceMapHeader = """ | |
> # big endian | |
attr: H | |
typeListOffset: H | |
nameListOffset: H | |
""" | |
ResourceMapHeaderSize = sstruct.calcsize(ResourceMapHeader) | |
ResourceTypeItem = """ | |
> # big endian | |
type: 4s | |
numRes: H | |
refListOffset: H | |
""" | |
ResourceTypeItemSize = sstruct.calcsize(ResourceTypeItem) | |
ResourceRefItem = """ | |
> # big endian | |
id: h | |
nameOffset: h | |
attr: B | |
dataOffset: 3s | |
reserved: L | |
""" | |
ResourceRefItemSize = sstruct.calcsize(ResourceRefItem) | |
from fontTools.misc.py23 import * | |
import struct | |
from fontTools.misc import sstruct | |
from collections import OrderedDict | |
try: | |
from collections.abc import MutableMapping | |
except ImportError: | |
from UserDict import DictMixin as MutableMapping | |
_resources = OrderedDict() | |
with open('/System/Library/Fonts/Courier.dfont', 'rb') as datafork: | |
data = datafork.read() | |
file = BytesIO(data) | |
# _readHeaderAndMap | |
file.seek(0) | |
headerData = file.read(ResourceForkHeaderSize) | |
header = sstruct.unpack(ResourceForkHeader, headerData) | |
# seek to resource map, skip reserved | |
mapOffset = header['mapOffset'] + 22 | |
print (mapOffset) | |
file.seek(mapOffset) | |
resourceMapData = file.read(ResourceMapHeaderSize) | |
resourceMap = sstruct.unpack(ResourceMapHeader, resourceMapData) | |
absTypeListOffset = header['mapOffset'] + resourceMap['typeListOffset'] | |
absNameListOffset = header['mapOffset'] + resourceMap['nameListOffset'] | |
dataOffset = header['dataOffset'] | |
# _readTypeList | |
file.seek(absTypeListOffset) | |
numTypesData = file.read(2) | |
numTypes, = struct.unpack('>H', numTypesData) | |
print ('numTypes:', numTypes) | |
absTypeListOffset2 = absTypeListOffset + 2 | |
for i in range(numTypes + 1): | |
resTypeItemOffset = absTypeListOffset2 + ResourceTypeItemSize * i | |
file.seek(resTypeItemOffset) | |
resTypeItemData = file.read(ResourceTypeItemSize) | |
item = sstruct.unpack(ResourceTypeItem, resTypeItemData) | |
print ('Item: ', item) | |
resType = tostr(item['type'], encoding='mac-roman') | |
refListOffset = absTypeListOffset + item['refListOffset'] | |
numRes = item['numRes'] + 1 | |
# _readReferenceList | |
resources = [] | |
for i in range(numRes): | |
refOffset = refListOffset + ResourceRefItemSize * i | |
file.seek(refOffset) | |
refData = file.read(ResourceRefItemSize) | |
#res = Resource(resType).decompile(refData, self) | |
resItem = sstruct.unpack(ResourceRefItem, refData) | |
# interpret 3-byte dataOffset as (padded) ULONG to unpack it with struct | |
dataOffset2, = struct.unpack('>L', bytesjoin([b"\0", resItem['dataOffset']])) | |
absDataOffset = dataOffset + dataOffset2 | |
file.seek(absDataOffset) | |
dataLength, = struct.unpack(">L", file.read(4)) | |
data = file.read(dataLength) | |
print ('res:', resItem) | |
res = {"type": resType, "data": data, "attr": resItem['attr'], "id": resItem['id']} | |
if resItem['nameOffset'] == -1: | |
resources.append(res) | |
continue | |
absNameOffset = absNameListOffset + resItem['nameOffset'] | |
file.seek(absNameOffset) | |
nameLength, = struct.unpack('B', file.read(1)) | |
name, = struct.unpack('>%ss' % nameLength, file.read(nameLength)) | |
res['name'] = tostr(name, encoding='mac-roman') | |
resources.append(res) | |
_resources[resType] = resources | |
#_resources['sfnt'][0] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment