222 lines
7.9 KiB
Python
Executable file
222 lines
7.9 KiB
Python
Executable file
from xml.sax.saxutils import quoteattr
|
|
from fontTools.ttLib import TTFont, TTLibError
|
|
from extractor.tools import RelaxedInfo
|
|
from extractor.formats.opentype import extractOpenTypeInfo, extractOpenTypeGlyphs, extractOpenTypeKerning
|
|
|
|
try:
|
|
from xml.etree import cElementTree as ElementTree
|
|
except ImportError:
|
|
from xml.etree import ElementTree
|
|
|
|
# ----------------
|
|
# Public Functions
|
|
# ----------------
|
|
|
|
def isWOFF(pathOrFile):
|
|
flavor = None
|
|
try:
|
|
font = TTFont(pathOrFile)
|
|
flavor = font.flavor
|
|
del font
|
|
except TTLibError:
|
|
return False
|
|
return flavor in ("woff", "woff2")
|
|
|
|
def extractFontFromWOFF(pathOrFile, destination, doGlyphs=True, doInfo=True, doKerning=True, customFunctions=[]):
|
|
source = TTFont(pathOrFile)
|
|
if doInfo:
|
|
extractWOFFInfo(source, destination)
|
|
if doGlyphs:
|
|
extractWOFFGlyphs(source, destination)
|
|
if doKerning:
|
|
kerning, groups = extractWOFFKerning(source, destination)
|
|
destination.groups.update(groups)
|
|
destination.kerning.clear()
|
|
destination.kerning.update(kerning)
|
|
for function in customFunctions:
|
|
function(source, destination)
|
|
source.close()
|
|
|
|
# ----------------
|
|
# Specific Imports
|
|
# ----------------
|
|
|
|
def extractWOFFInfo(source, destination):
|
|
info = RelaxedInfo(destination.info)
|
|
info.woffMajorVersion = source.flavorData.majorVersion
|
|
info.woffMinorVersion = source.flavorData.minorVersion
|
|
_extractWOFFMetadata(source.flavorData, info)
|
|
return extractOpenTypeInfo(source, destination)
|
|
|
|
def extractWOFFGlyphs(source, destination):
|
|
return extractOpenTypeGlyphs(source, destination)
|
|
|
|
def extractWOFFKerning(source, destination):
|
|
return extractOpenTypeKerning(source, destination)
|
|
|
|
# --------
|
|
# Metadata
|
|
# --------
|
|
|
|
def _extractWOFFMetadata(source, destination):
|
|
if source.metaData is None:
|
|
return
|
|
metadata = ElementTree.fromstring(source.metaData)
|
|
for element in metadata:
|
|
if element.tag == "uniqueid":
|
|
_extractWOFFMetadataUniqueID(element, destination)
|
|
elif element.tag == "vendor":
|
|
_extractWOFFMetadataVendor(element, destination)
|
|
elif element.tag == "credits":
|
|
_extractWOFFMetadataCredits(element, destination)
|
|
elif element.tag == "description":
|
|
_extractWOFFMetadataDescription(element, destination)
|
|
elif element.tag == "license":
|
|
_extractWOFFMetadataLicense(element, destination)
|
|
elif element.tag == "copyright":
|
|
_extractWOFFMetadataCopyright(element, destination)
|
|
elif element.tag == "trademark":
|
|
_extractWOFFMetadataTrademark(element, destination)
|
|
elif element.tag == "licensee":
|
|
_extractWOFFMetadataLicensee(element, destination)
|
|
elif element.tag == "extension":
|
|
_extractWOFFMetadataExtension(element, destination)
|
|
|
|
def _extractWOFFMetadataUniqueID(element, destination):
|
|
destination.woffMetadataUniqueID = _extractWOFFMetadataDict(element, ("id",))
|
|
|
|
def _extractWOFFMetadataVendor(element, destination):
|
|
attributes = ("name", "url", "dir", "class")
|
|
record = _extractWOFFMetadataDict(element, attributes)
|
|
destination.woffMetadataVendor = record
|
|
|
|
def _extractWOFFMetadataCredits(element, destination):
|
|
attributes = ("name", "url", "role", "dir", "class")
|
|
credits = []
|
|
for subElement in element:
|
|
if subElement.tag == "credit":
|
|
record = _extractWOFFMetadataDict(subElement, attributes)
|
|
credits.append(record)
|
|
destination.woffMetadataCredits = dict(credits=credits)
|
|
|
|
def _extractWOFFMetadataDescription(element, destination):
|
|
description = _extractWOFFMetadataDict(element, ("url",))
|
|
textRecords = _extractWOFFMetadataText(element)
|
|
if textRecords:
|
|
description["text"] = textRecords
|
|
destination.woffMetadataDescription = description
|
|
|
|
def _extractWOFFMetadataLicense(element, destination):
|
|
license = _extractWOFFMetadataDict(element, ("url", "id"))
|
|
textRecords = _extractWOFFMetadataText(element)
|
|
if textRecords:
|
|
license["text"] = textRecords
|
|
destination.woffMetadataLicense = license
|
|
|
|
def _extractWOFFMetadataCopyright(element, destination):
|
|
copyright = {}
|
|
textRecords = _extractWOFFMetadataText(element)
|
|
if textRecords:
|
|
copyright["text"] = textRecords
|
|
destination.woffMetadataCopyright = copyright
|
|
|
|
def _extractWOFFMetadataTrademark(element, destination):
|
|
trademark = {}
|
|
textRecords = _extractWOFFMetadataText(element)
|
|
if textRecords:
|
|
trademark["text"] = textRecords
|
|
destination.woffMetadataTrademark = trademark
|
|
|
|
def _extractWOFFMetadataLicensee(element, destination):
|
|
destination.woffMetadataLicensee = _extractWOFFMetadataDict(element, ("name", "dir", "class"))
|
|
|
|
def _extractWOFFMetadataExtension(element, destination):
|
|
extension = _extractWOFFMetadataDict(element, ("id",))
|
|
for subElement in element:
|
|
if subElement.tag == "name":
|
|
if "names" not in extension:
|
|
extension["names"] = []
|
|
name = _extractWOFFMetadataExtensionName(subElement)
|
|
extension["names"].append(name)
|
|
elif subElement.tag == "item":
|
|
if "items" not in extension:
|
|
extension["items"] = []
|
|
item = _extractWOFFMetadataExtensionItem(subElement)
|
|
extension["items"].append(item)
|
|
extensions = []
|
|
if destination.woffMetadataExtensions:
|
|
extensions.extend(destination.woffMetadataExtensions)
|
|
destination.woffMetadataExtensions = extensions + [extension]
|
|
|
|
def _extractWOFFMetadataExtensionItem(element):
|
|
item = _extractWOFFMetadataDict(element, ("id",))
|
|
for subElement in element:
|
|
if subElement.tag == "name":
|
|
if "names" not in item:
|
|
item["names"] = []
|
|
name = _extractWOFFMetadataExtensionName(subElement)
|
|
item["names"].append(name)
|
|
elif subElement.tag == "value":
|
|
if "values" not in item:
|
|
item["values"] = []
|
|
name = _extractWOFFMetadataExtensionValue(subElement)
|
|
item["values"].append(name)
|
|
return item
|
|
|
|
def _extractWOFFMetadataExtensionName(element):
|
|
name = _extractWOFFMetadataDict(element, ("dir", "class"))
|
|
language = _extractWOFFMetadataLanguage(element)
|
|
if language is not None:
|
|
name["language"] = language
|
|
name["text"] = _flattenWOFFMetadataString(element)
|
|
return name
|
|
|
|
def _extractWOFFMetadataExtensionValue(element):
|
|
return _extractWOFFMetadataExtensionName(element)
|
|
|
|
# support
|
|
|
|
def _extractWOFFMetadataDict(element, attributes):
|
|
record = {}
|
|
for attribute in attributes:
|
|
value = element.attrib.get(attribute)
|
|
if value is not None:
|
|
record[attribute] = value
|
|
return record
|
|
|
|
def _extractWOFFMetadataText(element):
|
|
records = []
|
|
attributes = ("dir", "class")
|
|
for subElement in element:
|
|
record = _extractWOFFMetadataDict(subElement, attributes)
|
|
# text
|
|
record["text"] = _flattenWOFFMetadataString(subElement)
|
|
# language
|
|
language = _extractWOFFMetadataLanguage(subElement)
|
|
if language is not None:
|
|
record["language"] = language
|
|
records.append(record)
|
|
return records
|
|
|
|
def _extractWOFFMetadataLanguage(element):
|
|
language = element.attrib.get("{http://www.w3.org/XML/1998/namespace}lang")
|
|
if language is None:
|
|
language = element.attrib.get("lang")
|
|
return language
|
|
|
|
def _flattenWOFFMetadataString(element, sub=False):
|
|
text = element.text.strip()
|
|
for subElement in element:
|
|
text += _flattenWOFFMetadataString(subElement, sub=True)
|
|
if element.tail:
|
|
text += element.tail.strip()
|
|
if sub:
|
|
attrib = ["%s=%s" % (key, quoteattr(value)) for key, value in element.attrib.items()]
|
|
attrib = " ".join(attrib)
|
|
if attrib:
|
|
start = "<%s %s>" % (element.tag, attrib)
|
|
else:
|
|
start = "<%s>" % (element.tag)
|
|
end = "</%s>" % (element.tag)
|
|
text = start + text + end
|
|
return text
|