Blame Lib/fontTools/ttLib/tables/_n_a_m_e.py

rpm-build 6a2e4c
# -*- coding: utf-8 -*-
rpm-build 6a2e4c
from __future__ import print_function, division, absolute_import
rpm-build 6a2e4c
from __future__ import unicode_literals
rpm-build 6a2e4c
from fontTools.misc.py23 import *
rpm-build 6a2e4c
from fontTools.misc import sstruct
rpm-build 6a2e4c
from fontTools.misc.textTools import safeEval
rpm-build 6a2e4c
from fontTools.misc.encodingTools import getEncoding
rpm-build 6a2e4c
from fontTools.ttLib import newTable
rpm-build 6a2e4c
from . import DefaultTable
rpm-build 6a2e4c
import struct
rpm-build 6a2e4c
import logging
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
log = logging.getLogger(__name__)
rpm-build 6a2e4c
rpm-build 6a2e4c
nameRecordFormat = """
rpm-build 6a2e4c
		>	# big endian
rpm-build 6a2e4c
		platformID:	H
rpm-build 6a2e4c
		platEncID:	H
rpm-build 6a2e4c
		langID:		H
rpm-build 6a2e4c
		nameID:		H
rpm-build 6a2e4c
		length:		H
rpm-build 6a2e4c
		offset:		H
rpm-build 6a2e4c
"""
rpm-build 6a2e4c
rpm-build 6a2e4c
nameRecordSize = sstruct.calcsize(nameRecordFormat)
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
class table__n_a_m_e(DefaultTable.DefaultTable):
rpm-build 6a2e4c
	dependencies = ["ltag"]
rpm-build 6a2e4c
rpm-build 6a2e4c
	def decompile(self, data, ttFont):
rpm-build 6a2e4c
		format, n, stringOffset = struct.unpack(b">HHH", data[:6])
rpm-build 6a2e4c
		expectedStringOffset = 6 + n * nameRecordSize
rpm-build 6a2e4c
		if stringOffset != expectedStringOffset:
rpm-build 6a2e4c
			log.error(
rpm-build 6a2e4c
				"'name' table stringOffset incorrect. Expected: %s; Actual: %s",
rpm-build 6a2e4c
				expectedStringOffset, stringOffset)
rpm-build 6a2e4c
		stringData = data[stringOffset:]
rpm-build 6a2e4c
		data = data[6:]
rpm-build 6a2e4c
		self.names = []
rpm-build 6a2e4c
		for i in range(n):
rpm-build 6a2e4c
			if len(data) < 12:
rpm-build 6a2e4c
				log.error('skipping malformed name record #%d', i)
rpm-build 6a2e4c
				continue
rpm-build 6a2e4c
			name, data = sstruct.unpack2(nameRecordFormat, data, NameRecord())
rpm-build 6a2e4c
			name.string = stringData[name.offset:name.offset+name.length]
rpm-build 6a2e4c
			if name.offset + name.length > len(stringData):
rpm-build 6a2e4c
				log.error('skipping malformed name record #%d', i)
rpm-build 6a2e4c
				continue
rpm-build 6a2e4c
			assert len(name.string) == name.length
rpm-build 6a2e4c
			#if (name.platEncID, name.platformID) in ((0, 0), (1, 3)):
rpm-build 6a2e4c
			#	if len(name.string) % 2:
rpm-build 6a2e4c
			#		print "2-byte string doesn't have even length!"
rpm-build 6a2e4c
			#		print name.__dict__
rpm-build 6a2e4c
			del name.offset, name.length
rpm-build 6a2e4c
			self.names.append(name)
rpm-build 6a2e4c
rpm-build 6a2e4c
	def compile(self, ttFont):
rpm-build 6a2e4c
		if not hasattr(self, "names"):
rpm-build 6a2e4c
			# only happens when there are NO name table entries read
rpm-build 6a2e4c
			# from the TTX file
rpm-build 6a2e4c
			self.names = []
rpm-build 6a2e4c
		names = self.names
rpm-build 6a2e4c
		names.sort() # sort according to the spec; see NameRecord.__lt__()
rpm-build 6a2e4c
		stringData = b""
rpm-build 6a2e4c
		format = 0
rpm-build 6a2e4c
		n = len(names)
rpm-build 6a2e4c
		stringOffset = 6 + n * sstruct.calcsize(nameRecordFormat)
rpm-build 6a2e4c
		data = struct.pack(b">HHH", format, n, stringOffset)
rpm-build 6a2e4c
		lastoffset = 0
rpm-build 6a2e4c
		done = {}  # remember the data so we can reuse the "pointers"
rpm-build 6a2e4c
		for name in names:
rpm-build 6a2e4c
			string = name.toBytes()
rpm-build 6a2e4c
			if string in done:
rpm-build 6a2e4c
				name.offset, name.length = done[string]
rpm-build 6a2e4c
			else:
rpm-build 6a2e4c
				name.offset, name.length = done[string] = len(stringData), len(string)
rpm-build 6a2e4c
				stringData = bytesjoin([stringData, string])
rpm-build 6a2e4c
			data = data + sstruct.pack(nameRecordFormat, name)
rpm-build 6a2e4c
		return data + stringData
rpm-build 6a2e4c
rpm-build 6a2e4c
	def toXML(self, writer, ttFont):
rpm-build 6a2e4c
		for name in self.names:
rpm-build 6a2e4c
			name.toXML(writer, ttFont)
rpm-build 6a2e4c
rpm-build 6a2e4c
	def fromXML(self, name, attrs, content, ttFont):
rpm-build 6a2e4c
		if name != "namerecord":
rpm-build 6a2e4c
			return # ignore unknown tags
rpm-build 6a2e4c
		if not hasattr(self, "names"):
rpm-build 6a2e4c
			self.names = []
rpm-build 6a2e4c
		name = NameRecord()
rpm-build 6a2e4c
		self.names.append(name)
rpm-build 6a2e4c
		name.fromXML(name, attrs, content, ttFont)
rpm-build 6a2e4c
rpm-build 6a2e4c
	def getName(self, nameID, platformID, platEncID, langID=None):
rpm-build 6a2e4c
		for namerecord in self.names:
rpm-build 6a2e4c
			if (	namerecord.nameID == nameID and
rpm-build 6a2e4c
					namerecord.platformID == platformID and
rpm-build 6a2e4c
					namerecord.platEncID == platEncID):
rpm-build 6a2e4c
				if langID is None or namerecord.langID == langID:
rpm-build 6a2e4c
					return namerecord
rpm-build 6a2e4c
		return None # not found
rpm-build 6a2e4c
rpm-build 6a2e4c
	def getDebugName(self, nameID):
rpm-build 6a2e4c
		englishName = someName = None
rpm-build 6a2e4c
		for name in self.names:
rpm-build 6a2e4c
			if name.nameID != nameID:
rpm-build 6a2e4c
				continue
rpm-build 6a2e4c
			try:
rpm-build 6a2e4c
				unistr = name.toUnicode()
rpm-build 6a2e4c
			except UnicodeDecodeError:
rpm-build 6a2e4c
				continue
rpm-build 6a2e4c
rpm-build 6a2e4c
			someName = unistr
rpm-build 6a2e4c
			if (name.platformID, name.langID) in ((1, 0), (3, 0x409)):
rpm-build 6a2e4c
				englishName = unistr
rpm-build 6a2e4c
				break
rpm-build 6a2e4c
		if englishName:
rpm-build 6a2e4c
			return englishName
rpm-build 6a2e4c
		elif someName:
rpm-build 6a2e4c
			return someName
rpm-build 6a2e4c
		else:
rpm-build 6a2e4c
			return None
rpm-build 6a2e4c
rpm-build 6a2e4c
	def setName(self, string, nameID, platformID, platEncID, langID):
rpm-build 6a2e4c
		""" Set the 'string' for the name record identified by 'nameID', 'platformID',
rpm-build 6a2e4c
		'platEncID' and 'langID'. If a record with that nameID doesn't exist, create it
rpm-build 6a2e4c
		and append to the name table.
rpm-build 6a2e4c
rpm-build 6a2e4c
		'string' can be of type `str` (`unicode` in PY2) or `bytes`. In the latter case,
rpm-build 6a2e4c
		it is assumed to be already encoded with the correct plaform-specific encoding
rpm-build 6a2e4c
		identified by the (platformID, platEncID, langID) triplet. A warning is issued
rpm-build 6a2e4c
		to prevent unexpected results.
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		if not hasattr(self, 'names'):
rpm-build 6a2e4c
			self.names = []
rpm-build 6a2e4c
		if not isinstance(string, unicode):
rpm-build 6a2e4c
			if isinstance(string, bytes):
rpm-build 6a2e4c
				log.warning(
rpm-build 6a2e4c
					"name string is bytes, ensure it's correctly encoded: %r", string)
rpm-build 6a2e4c
			else:
rpm-build 6a2e4c
				raise TypeError(
rpm-build 6a2e4c
					"expected unicode or bytes, found %s: %r" % (
rpm-build 6a2e4c
						type(string).__name__, string))
rpm-build 6a2e4c
		namerecord = self.getName(nameID, platformID, platEncID, langID)
rpm-build 6a2e4c
		if namerecord:
rpm-build 6a2e4c
			namerecord.string = string
rpm-build 6a2e4c
		else:
rpm-build 6a2e4c
			self.names.append(makeName(string, nameID, platformID, platEncID, langID))
rpm-build 6a2e4c
rpm-build 6a2e4c
	def _findUnusedNameID(self, minNameID=256):
rpm-build 6a2e4c
		"""Finds an unused name id.
rpm-build 6a2e4c
rpm-build 6a2e4c
		The nameID is assigned in the range between 'minNameID' and 32767 (inclusive),
rpm-build 6a2e4c
		following the last nameID in the name table.
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		names = getattr(self, 'names', [])
rpm-build 6a2e4c
		nameID = 1 + max([n.nameID for n in names] + [minNameID - 1])
rpm-build 6a2e4c
		if nameID > 32767:
rpm-build 6a2e4c
			raise ValueError("nameID must be less than 32768")
rpm-build 6a2e4c
		return nameID
rpm-build 6a2e4c
rpm-build 6a2e4c
	def addMultilingualName(self, names, ttFont=None, nameID=None):
rpm-build 6a2e4c
		"""Add a multilingual name, returning its name ID
rpm-build 6a2e4c
rpm-build 6a2e4c
		'names' is a dictionary with the name in multiple languages,
rpm-build 6a2e4c
		such as {'en': 'Pale', 'de': 'Blaß', 'de-CH': 'Blass'}.
rpm-build 6a2e4c
		The keys can be arbitrary IETF BCP 47 language codes;
rpm-build 6a2e4c
		the values are Unicode strings.
rpm-build 6a2e4c
rpm-build 6a2e4c
		'ttFont' is the TTFont to which the names are added, or None.
rpm-build 6a2e4c
		If present, the font's 'ltag' table can get populated
rpm-build 6a2e4c
		to store exotic language codes, which allows encoding
rpm-build 6a2e4c
		names that otherwise cannot get encoded at all.
rpm-build 6a2e4c
rpm-build 6a2e4c
		'nameID' is the name ID to be used, or None to let the library
rpm-build 6a2e4c
		pick an unused name ID.
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		if not hasattr(self, 'names'):
rpm-build 6a2e4c
			self.names = []
rpm-build 6a2e4c
		if nameID is None:
rpm-build 6a2e4c
			nameID = self._findUnusedNameID()
rpm-build 6a2e4c
		# TODO: Should minimize BCP 47 language codes.
rpm-build 6a2e4c
		# https://github.com/fonttools/fonttools/issues/930
rpm-build 6a2e4c
		for lang, name in sorted(names.items()):
rpm-build 6a2e4c
			# Apple platforms have been recognizing Windows names
rpm-build 6a2e4c
			# since early OSX (~2001), so we only add names
rpm-build 6a2e4c
			# for the Macintosh platform when we cannot not make
rpm-build 6a2e4c
			# a Windows name. This can happen for exotic BCP47
rpm-build 6a2e4c
			# language tags that have no Windows language code.
rpm-build 6a2e4c
			windowsName = _makeWindowsName(name, nameID, lang)
rpm-build 6a2e4c
			if windowsName is not None:
rpm-build 6a2e4c
				self.names.append(windowsName)
rpm-build 6a2e4c
			else:
rpm-build 6a2e4c
				macName = _makeMacName(name, nameID, lang, ttFont)
rpm-build 6a2e4c
				if macName is not None:
rpm-build 6a2e4c
					self.names.append(macName)
rpm-build 6a2e4c
		return nameID
rpm-build 6a2e4c
rpm-build 6a2e4c
	def addName(self, string, platforms=((1, 0, 0), (3, 1, 0x409)), minNameID=255):
rpm-build 6a2e4c
		""" Add a new name record containing 'string' for each (platformID, platEncID,
rpm-build 6a2e4c
		langID) tuple specified in the 'platforms' list.
rpm-build 6a2e4c
rpm-build 6a2e4c
		The nameID is assigned in the range between 'minNameID'+1 and 32767 (inclusive),
rpm-build 6a2e4c
		following the last nameID in the name table.
rpm-build 6a2e4c
		If no 'platforms' are specified, two English name records are added, one for the
rpm-build 6a2e4c
		Macintosh (platformID=0), and one for the Windows platform (3).
rpm-build 6a2e4c
rpm-build 6a2e4c
		The 'string' must be a Unicode string, so it can be encoded with different,
rpm-build 6a2e4c
		platform-specific encodings.
rpm-build 6a2e4c
rpm-build 6a2e4c
		Return the new nameID.
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		assert len(platforms) > 0, \
rpm-build 6a2e4c
			"'platforms' must contain at least one (platformID, platEncID, langID) tuple"
rpm-build 6a2e4c
		if not hasattr(self, 'names'):
rpm-build 6a2e4c
			self.names = []
rpm-build 6a2e4c
		if not isinstance(string, unicode):
rpm-build 6a2e4c
			raise TypeError(
rpm-build 6a2e4c
				"expected %s, found %s: %r" % (
rpm-build 6a2e4c
					unicode.__name__, type(string).__name__,string ))
rpm-build 6a2e4c
		nameID = self._findUnusedNameID(minNameID + 1)
rpm-build 6a2e4c
		for platformID, platEncID, langID in platforms:
rpm-build 6a2e4c
			self.names.append(makeName(string, nameID, platformID, platEncID, langID))
rpm-build 6a2e4c
		return nameID
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
def makeName(string, nameID, platformID, platEncID, langID):
rpm-build 6a2e4c
	name = NameRecord()
rpm-build 6a2e4c
	name.string, name.nameID, name.platformID, name.platEncID, name.langID = (
rpm-build 6a2e4c
		string, nameID, platformID, platEncID, langID)
rpm-build 6a2e4c
	return name
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
def _makeWindowsName(name, nameID, language):
rpm-build 6a2e4c
	"""Create a NameRecord for the Microsoft Windows platform
rpm-build 6a2e4c
rpm-build 6a2e4c
	'language' is an arbitrary IETF BCP 47 language identifier such
rpm-build 6a2e4c
	as 'en', 'de-CH', 'de-AT-1901', or 'fa-Latn'. If Microsoft Windows
rpm-build 6a2e4c
	does not support the desired language, the result will be None.
rpm-build 6a2e4c
	Future versions of fonttools might return a NameRecord for the
rpm-build 6a2e4c
	OpenType 'name' table format 1, but this is not implemented yet.
rpm-build 6a2e4c
	"""
rpm-build 6a2e4c
	langID = _WINDOWS_LANGUAGE_CODES.get(language.lower())
rpm-build 6a2e4c
	if langID is not None:
rpm-build 6a2e4c
		return makeName(name, nameID, 3, 1, langID)
rpm-build 6a2e4c
	else:
rpm-build 6a2e4c
		log.warning("cannot add Windows name in language %s "
rpm-build 6a2e4c
		            "because fonttools does not yet support "
rpm-build 6a2e4c
		            "name table format 1" % language)
rpm-build 6a2e4c
		return None
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
def _makeMacName(name, nameID, language, font=None):
rpm-build 6a2e4c
	"""Create a NameRecord for Apple platforms
rpm-build 6a2e4c
rpm-build 6a2e4c
	'language' is an arbitrary IETF BCP 47 language identifier such
rpm-build 6a2e4c
	as 'en', 'de-CH', 'de-AT-1901', or 'fa-Latn'. When possible, we
rpm-build 6a2e4c
	create a Macintosh NameRecord that is understood by old applications
rpm-build 6a2e4c
	(platform ID 1 and an old-style Macintosh language enum). If this
rpm-build 6a2e4c
	is not possible, we create a Unicode NameRecord (platform ID 0)
rpm-build 6a2e4c
	whose language points to the font’s 'ltag' table. The latter
rpm-build 6a2e4c
	can encode any string in any language, but legacy applications
rpm-build 6a2e4c
	might not recognize the format (in which case they will ignore
rpm-build 6a2e4c
	those names).
rpm-build 6a2e4c
rpm-build 6a2e4c
	'font' should be the TTFont for which you want to create a name.
rpm-build 6a2e4c
	If 'font' is None, we only return NameRecords for legacy Macintosh;
rpm-build 6a2e4c
	in that case, the result will be None for names that need to
rpm-build 6a2e4c
	be encoded with an 'ltag' table.
rpm-build 6a2e4c
rpm-build 6a2e4c
	See the section “The language identifier” in Apple’s specification:
rpm-build 6a2e4c
	https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html
rpm-build 6a2e4c
	"""
rpm-build 6a2e4c
	macLang = _MAC_LANGUAGE_CODES.get(language.lower())
rpm-build 6a2e4c
	macScript = _MAC_LANGUAGE_TO_SCRIPT.get(macLang)
rpm-build 6a2e4c
	if macLang is not None and macScript is not None:
rpm-build 6a2e4c
		encoding = getEncoding(1, macScript, macLang, default="ascii")
rpm-build 6a2e4c
		# Check if we can actually encode this name. If we can't,
rpm-build 6a2e4c
		# for example because we have no support for the legacy
rpm-build 6a2e4c
		# encoding, or because the name string contains Unicode
rpm-build 6a2e4c
		# characters that the legacy encoding cannot represent,
rpm-build 6a2e4c
		# we fall back to encoding the name in Unicode and put
rpm-build 6a2e4c
		# the language tag into the ltag table.
rpm-build 6a2e4c
		try:
rpm-build 6a2e4c
			_ = tobytes(name, encoding, errors="strict")
rpm-build 6a2e4c
			return makeName(name, nameID, 1, macScript, macLang)
rpm-build 6a2e4c
		except UnicodeEncodeError:
rpm-build 6a2e4c
			pass
rpm-build 6a2e4c
	if font is not None:
rpm-build 6a2e4c
		ltag = font.tables.get("ltag")
rpm-build 6a2e4c
		if ltag is None:
rpm-build 6a2e4c
			ltag = font["ltag"] = newTable("ltag")
rpm-build 6a2e4c
		# 0 = Unicode; 4 = “Unicode 2.0 or later semantics (non-BMP characters allowed)”
rpm-build 6a2e4c
		# “The preferred platform-specific code for Unicode would be 3 or 4.”
rpm-build 6a2e4c
		# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html
rpm-build 6a2e4c
		return makeName(name, nameID, 0, 4, ltag.addTag(language))
rpm-build 6a2e4c
	else:
rpm-build 6a2e4c
		log.warning("cannot store language %s into 'ltag' table "
rpm-build 6a2e4c
		            "without having access to the TTFont object" %
rpm-build 6a2e4c
		            language)
rpm-build 6a2e4c
		return None
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
class NameRecord(object):
rpm-build 6a2e4c
rpm-build 6a2e4c
	def getEncoding(self, default='ascii'):
rpm-build 6a2e4c
		"""Returns the Python encoding name for this name entry based on its platformID,
rpm-build 6a2e4c
		platEncID, and langID.  If encoding for these values is not known, by default
rpm-build 6a2e4c
		'ascii' is returned.  That can be overriden by passing a value to the default
rpm-build 6a2e4c
		argument.
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		return getEncoding(self.platformID, self.platEncID, self.langID, default)
rpm-build 6a2e4c
rpm-build 6a2e4c
	def encodingIsUnicodeCompatible(self):
rpm-build 6a2e4c
		return self.getEncoding(None) in ['utf_16_be', 'ucs2be', 'ascii', 'latin1']
rpm-build 6a2e4c
rpm-build 6a2e4c
	def __str__(self):
rpm-build 6a2e4c
		return self.toStr(errors='backslashreplace')
rpm-build 6a2e4c
rpm-build 6a2e4c
	def isUnicode(self):
rpm-build 6a2e4c
		return (self.platformID == 0 or
rpm-build 6a2e4c
			(self.platformID == 3 and self.platEncID in [0, 1, 10]))
rpm-build 6a2e4c
rpm-build 6a2e4c
	def toUnicode(self, errors='strict'):
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		If self.string is a Unicode string, return it; otherwise try decoding the
rpm-build 6a2e4c
		bytes in self.string to a Unicode string using the encoding of this
rpm-build 6a2e4c
		entry as returned by self.getEncoding(); Note that  self.getEncoding()
rpm-build 6a2e4c
		returns 'ascii' if the encoding is unknown to the library.
rpm-build 6a2e4c
rpm-build 6a2e4c
		Certain heuristics are performed to recover data from bytes that are
rpm-build 6a2e4c
		ill-formed in the chosen encoding, or that otherwise look misencoded
rpm-build 6a2e4c
		(mostly around bad UTF-16BE encoded bytes, or bytes that look like UTF-16BE
rpm-build 6a2e4c
		but marked otherwise).  If the bytes are ill-formed and the heuristics fail,
rpm-build 6a2e4c
		the error is handled according to the errors parameter to this function, which is
rpm-build 6a2e4c
		passed to the underlying decode() function; by default it throws a
rpm-build 6a2e4c
		UnicodeDecodeError exception.
rpm-build 6a2e4c
rpm-build 6a2e4c
		Note: The mentioned heuristics mean that roundtripping a font to XML and back
rpm-build 6a2e4c
		to binary might recover some misencoded data whereas just loading the font
rpm-build 6a2e4c
		and saving it back will not change them.
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		def isascii(b):
rpm-build 6a2e4c
			return (b >= 0x20 and b <= 0x7E) or b in [0x09, 0x0A, 0x0D]
rpm-build 6a2e4c
		encoding = self.getEncoding()
rpm-build 6a2e4c
		string = self.string
rpm-build 6a2e4c
rpm-build 6a2e4c
		if encoding == 'utf_16_be' and len(string) % 2 == 1:
rpm-build 6a2e4c
			# Recover badly encoded UTF-16 strings that have an odd number of bytes:
rpm-build 6a2e4c
			# - If the last byte is zero, drop it.  Otherwise,
rpm-build 6a2e4c
			# - If all the odd bytes are zero and all the even bytes are ASCII,
rpm-build 6a2e4c
			#   prepend one zero byte.  Otherwise,
rpm-build 6a2e4c
			# - If first byte is zero and all other bytes are ASCII, insert zero
rpm-build 6a2e4c
			#   bytes between consecutive ASCII bytes.
rpm-build 6a2e4c
			#
rpm-build 6a2e4c
			# (Yes, I've seen all of these in the wild... sigh)
rpm-build 6a2e4c
			if byteord(string[-1]) == 0:
rpm-build 6a2e4c
				string = string[:-1]
rpm-build 6a2e4c
			elif all(byteord(b) == 0 if i % 2 else isascii(byteord(b)) for i,b in enumerate(string)):
rpm-build 6a2e4c
				string = b'\0' + string
rpm-build 6a2e4c
			elif byteord(string[0]) == 0 and all(isascii(byteord(b)) for b in string[1:]):
rpm-build 6a2e4c
				string = bytesjoin(b'\0'+bytechr(byteord(b)) for b in string[1:])
rpm-build 6a2e4c
rpm-build 6a2e4c
		string = tounicode(string, encoding=encoding, errors=errors)
rpm-build 6a2e4c
rpm-build 6a2e4c
		# If decoded strings still looks like UTF-16BE, it suggests a double-encoding.
rpm-build 6a2e4c
		# Fix it up.
rpm-build 6a2e4c
		if all(ord(c) == 0 if i % 2 == 0 else isascii(ord(c)) for i,c in enumerate(string)):
rpm-build 6a2e4c
			# If string claims to be Mac encoding, but looks like UTF-16BE with ASCII text,
rpm-build 6a2e4c
			# narrow it down.
rpm-build 6a2e4c
			string = ''.join(c for c in string[1::2])
rpm-build 6a2e4c
rpm-build 6a2e4c
		return string
rpm-build 6a2e4c
rpm-build 6a2e4c
	def toBytes(self, errors='strict'):
rpm-build 6a2e4c
		""" If self.string is a bytes object, return it; otherwise try encoding
rpm-build 6a2e4c
		the Unicode string in self.string to bytes using the encoding of this
rpm-build 6a2e4c
		entry as returned by self.getEncoding(); Note that self.getEncoding()
rpm-build 6a2e4c
		returns 'ascii' if the encoding is unknown to the library.
rpm-build 6a2e4c
rpm-build 6a2e4c
		If the Unicode string cannot be encoded to bytes in the chosen encoding,
rpm-build 6a2e4c
		the error is handled according to the errors parameter to this function,
rpm-build 6a2e4c
		which is passed to the underlying encode() function; by default it throws a
rpm-build 6a2e4c
		UnicodeEncodeError exception.
rpm-build 6a2e4c
		"""
rpm-build 6a2e4c
		return tobytes(self.string, encoding=self.getEncoding(), errors=errors)
rpm-build 6a2e4c
rpm-build 6a2e4c
	def toStr(self, errors='strict'):
rpm-build 6a2e4c
		if str == bytes:
rpm-build 6a2e4c
			# python 2
rpm-build 6a2e4c
			return self.toBytes(errors)
rpm-build 6a2e4c
		else:
rpm-build 6a2e4c
			# python 3
rpm-build 6a2e4c
			return self.toUnicode(errors)
rpm-build 6a2e4c
rpm-build 6a2e4c
	def toXML(self, writer, ttFont):
rpm-build 6a2e4c
		try:
rpm-build 6a2e4c
			unistr = self.toUnicode()
rpm-build 6a2e4c
		except UnicodeDecodeError:
rpm-build 6a2e4c
			unistr = None
rpm-build 6a2e4c
		attrs = [
rpm-build 6a2e4c
				("nameID", self.nameID),
rpm-build 6a2e4c
				("platformID", self.platformID),
rpm-build 6a2e4c
				("platEncID", self.platEncID),
rpm-build 6a2e4c
				("langID", hex(self.langID)),
rpm-build 6a2e4c
			]
rpm-build 6a2e4c
rpm-build 6a2e4c
		if unistr is None or not self.encodingIsUnicodeCompatible():
rpm-build 6a2e4c
			attrs.append(("unicode", unistr is not None))
rpm-build 6a2e4c
rpm-build 6a2e4c
		writer.begintag("namerecord", attrs)
rpm-build 6a2e4c
		writer.newline()
rpm-build 6a2e4c
		if unistr is not None:
rpm-build 6a2e4c
			writer.write(unistr)
rpm-build 6a2e4c
		else:
rpm-build 6a2e4c
			writer.write8bit(self.string)
rpm-build 6a2e4c
		writer.newline()
rpm-build 6a2e4c
		writer.endtag("namerecord")
rpm-build 6a2e4c
		writer.newline()
rpm-build 6a2e4c
rpm-build 6a2e4c
	def fromXML(self, name, attrs, content, ttFont):
rpm-build 6a2e4c
		self.nameID = safeEval(attrs["nameID"])
rpm-build 6a2e4c
		self.platformID = safeEval(attrs["platformID"])
rpm-build 6a2e4c
		self.platEncID = safeEval(attrs["platEncID"])
rpm-build 6a2e4c
		self.langID =  safeEval(attrs["langID"])
rpm-build 6a2e4c
		s = strjoin(content).strip()
rpm-build 6a2e4c
		encoding = self.getEncoding()
rpm-build 6a2e4c
		if self.encodingIsUnicodeCompatible() or safeEval(attrs.get("unicode", "False")):
rpm-build 6a2e4c
			self.string = s.encode(encoding)
rpm-build 6a2e4c
		else:
rpm-build 6a2e4c
			# This is the inverse of write8bit...
rpm-build 6a2e4c
			self.string = s.encode("latin1")
rpm-build 6a2e4c
rpm-build 6a2e4c
	def __lt__(self, other):
rpm-build 6a2e4c
		if type(self) != type(other):
rpm-build 6a2e4c
			return NotImplemented
rpm-build 6a2e4c
rpm-build 6a2e4c
		# implemented so that list.sort() sorts according to the spec.
rpm-build 6a2e4c
		selfTuple = (
rpm-build 6a2e4c
			getattr(self, "platformID", None),
rpm-build 6a2e4c
			getattr(self, "platEncID", None),
rpm-build 6a2e4c
			getattr(self, "langID", None),
rpm-build 6a2e4c
			getattr(self, "nameID", None),
rpm-build 6a2e4c
			getattr(self, "string", None),
rpm-build 6a2e4c
		)
rpm-build 6a2e4c
		otherTuple = (
rpm-build 6a2e4c
			getattr(other, "platformID", None),
rpm-build 6a2e4c
			getattr(other, "platEncID", None),
rpm-build 6a2e4c
			getattr(other, "langID", None),
rpm-build 6a2e4c
			getattr(other, "nameID", None),
rpm-build 6a2e4c
			getattr(other, "string", None),
rpm-build 6a2e4c
		)
rpm-build 6a2e4c
		return selfTuple < otherTuple
rpm-build 6a2e4c
rpm-build 6a2e4c
	def __repr__(self):
rpm-build 6a2e4c
		return "<NameRecord NameID=%d; PlatformID=%d; LanguageID=%d>" % (
rpm-build 6a2e4c
				self.nameID, self.platformID, self.langID)
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
# Windows language ID → IETF BCP-47 language tag
rpm-build 6a2e4c
#
rpm-build 6a2e4c
# While Microsoft indicates a region/country for all its language
rpm-build 6a2e4c
# IDs, we follow Unicode practice by omitting “most likely subtags”
rpm-build 6a2e4c
# as per Unicode CLDR. For example, English is simply “en” and not
rpm-build 6a2e4c
# “en-Latn” because according to Unicode, the default script
rpm-build 6a2e4c
# for English is Latin.
rpm-build 6a2e4c
#
rpm-build 6a2e4c
# http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html
rpm-build 6a2e4c
# http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
rpm-build 6a2e4c
_WINDOWS_LANGUAGES = {
rpm-build 6a2e4c
    0x0436: 'af',
rpm-build 6a2e4c
    0x041C: 'sq',
rpm-build 6a2e4c
    0x0484: 'gsw',
rpm-build 6a2e4c
    0x045E: 'am',
rpm-build 6a2e4c
    0x1401: 'ar-DZ',
rpm-build 6a2e4c
    0x3C01: 'ar-BH',
rpm-build 6a2e4c
    0x0C01: 'ar',
rpm-build 6a2e4c
    0x0801: 'ar-IQ',
rpm-build 6a2e4c
    0x2C01: 'ar-JO',
rpm-build 6a2e4c
    0x3401: 'ar-KW',
rpm-build 6a2e4c
    0x3001: 'ar-LB',
rpm-build 6a2e4c
    0x1001: 'ar-LY',
rpm-build 6a2e4c
    0x1801: 'ary',
rpm-build 6a2e4c
    0x2001: 'ar-OM',
rpm-build 6a2e4c
    0x4001: 'ar-QA',
rpm-build 6a2e4c
    0x0401: 'ar-SA',
rpm-build 6a2e4c
    0x2801: 'ar-SY',
rpm-build 6a2e4c
    0x1C01: 'aeb',
rpm-build 6a2e4c
    0x3801: 'ar-AE',
rpm-build 6a2e4c
    0x2401: 'ar-YE',
rpm-build 6a2e4c
    0x042B: 'hy',
rpm-build 6a2e4c
    0x044D: 'as',
rpm-build 6a2e4c
    0x082C: 'az-Cyrl',
rpm-build 6a2e4c
    0x042C: 'az',
rpm-build 6a2e4c
    0x046D: 'ba',
rpm-build 6a2e4c
    0x042D: 'eu',
rpm-build 6a2e4c
    0x0423: 'be',
rpm-build 6a2e4c
    0x0845: 'bn',
rpm-build 6a2e4c
    0x0445: 'bn-IN',
rpm-build 6a2e4c
    0x201A: 'bs-Cyrl',
rpm-build 6a2e4c
    0x141A: 'bs',
rpm-build 6a2e4c
    0x047E: 'br',
rpm-build 6a2e4c
    0x0402: 'bg',
rpm-build 6a2e4c
    0x0403: 'ca',
rpm-build 6a2e4c
    0x0C04: 'zh-HK',
rpm-build 6a2e4c
    0x1404: 'zh-MO',
rpm-build 6a2e4c
    0x0804: 'zh',
rpm-build 6a2e4c
    0x1004: 'zh-SG',
rpm-build 6a2e4c
    0x0404: 'zh-TW',
rpm-build 6a2e4c
    0x0483: 'co',
rpm-build 6a2e4c
    0x041A: 'hr',
rpm-build 6a2e4c
    0x101A: 'hr-BA',
rpm-build 6a2e4c
    0x0405: 'cs',
rpm-build 6a2e4c
    0x0406: 'da',
rpm-build 6a2e4c
    0x048C: 'prs',
rpm-build 6a2e4c
    0x0465: 'dv',
rpm-build 6a2e4c
    0x0813: 'nl-BE',
rpm-build 6a2e4c
    0x0413: 'nl',
rpm-build 6a2e4c
    0x0C09: 'en-AU',
rpm-build 6a2e4c
    0x2809: 'en-BZ',
rpm-build 6a2e4c
    0x1009: 'en-CA',
rpm-build 6a2e4c
    0x2409: 'en-029',
rpm-build 6a2e4c
    0x4009: 'en-IN',
rpm-build 6a2e4c
    0x1809: 'en-IE',
rpm-build 6a2e4c
    0x2009: 'en-JM',
rpm-build 6a2e4c
    0x4409: 'en-MY',
rpm-build 6a2e4c
    0x1409: 'en-NZ',
rpm-build 6a2e4c
    0x3409: 'en-PH',
rpm-build 6a2e4c
    0x4809: 'en-SG',
rpm-build 6a2e4c
    0x1C09: 'en-ZA',
rpm-build 6a2e4c
    0x2C09: 'en-TT',
rpm-build 6a2e4c
    0x0809: 'en-GB',
rpm-build 6a2e4c
    0x0409: 'en',
rpm-build 6a2e4c
    0x3009: 'en-ZW',
rpm-build 6a2e4c
    0x0425: 'et',
rpm-build 6a2e4c
    0x0438: 'fo',
rpm-build 6a2e4c
    0x0464: 'fil',
rpm-build 6a2e4c
    0x040B: 'fi',
rpm-build 6a2e4c
    0x080C: 'fr-BE',
rpm-build 6a2e4c
    0x0C0C: 'fr-CA',
rpm-build 6a2e4c
    0x040C: 'fr',
rpm-build 6a2e4c
    0x140C: 'fr-LU',
rpm-build 6a2e4c
    0x180C: 'fr-MC',
rpm-build 6a2e4c
    0x100C: 'fr-CH',
rpm-build 6a2e4c
    0x0462: 'fy',
rpm-build 6a2e4c
    0x0456: 'gl',
rpm-build 6a2e4c
    0x0437: 'ka',
rpm-build 6a2e4c
    0x0C07: 'de-AT',
rpm-build 6a2e4c
    0x0407: 'de',
rpm-build 6a2e4c
    0x1407: 'de-LI',
rpm-build 6a2e4c
    0x1007: 'de-LU',
rpm-build 6a2e4c
    0x0807: 'de-CH',
rpm-build 6a2e4c
    0x0408: 'el',
rpm-build 6a2e4c
    0x046F: 'kl',
rpm-build 6a2e4c
    0x0447: 'gu',
rpm-build 6a2e4c
    0x0468: 'ha',
rpm-build 6a2e4c
    0x040D: 'he',
rpm-build 6a2e4c
    0x0439: 'hi',
rpm-build 6a2e4c
    0x040E: 'hu',
rpm-build 6a2e4c
    0x040F: 'is',
rpm-build 6a2e4c
    0x0470: 'ig',
rpm-build 6a2e4c
    0x0421: 'id',
rpm-build 6a2e4c
    0x045D: 'iu',
rpm-build 6a2e4c
    0x085D: 'iu-Latn',
rpm-build 6a2e4c
    0x083C: 'ga',
rpm-build 6a2e4c
    0x0434: 'xh',
rpm-build 6a2e4c
    0x0435: 'zu',
rpm-build 6a2e4c
    0x0410: 'it',
rpm-build 6a2e4c
    0x0810: 'it-CH',
rpm-build 6a2e4c
    0x0411: 'ja',
rpm-build 6a2e4c
    0x044B: 'kn',
rpm-build 6a2e4c
    0x043F: 'kk',
rpm-build 6a2e4c
    0x0453: 'km',
rpm-build 6a2e4c
    0x0486: 'quc',
rpm-build 6a2e4c
    0x0487: 'rw',
rpm-build 6a2e4c
    0x0441: 'sw',
rpm-build 6a2e4c
    0x0457: 'kok',
rpm-build 6a2e4c
    0x0412: 'ko',
rpm-build 6a2e4c
    0x0440: 'ky',
rpm-build 6a2e4c
    0x0454: 'lo',
rpm-build 6a2e4c
    0x0426: 'lv',
rpm-build 6a2e4c
    0x0427: 'lt',
rpm-build 6a2e4c
    0x082E: 'dsb',
rpm-build 6a2e4c
    0x046E: 'lb',
rpm-build 6a2e4c
    0x042F: 'mk',
rpm-build 6a2e4c
    0x083E: 'ms-BN',
rpm-build 6a2e4c
    0x043E: 'ms',
rpm-build 6a2e4c
    0x044C: 'ml',
rpm-build 6a2e4c
    0x043A: 'mt',
rpm-build 6a2e4c
    0x0481: 'mi',
rpm-build 6a2e4c
    0x047A: 'arn',
rpm-build 6a2e4c
    0x044E: 'mr',
rpm-build 6a2e4c
    0x047C: 'moh',
rpm-build 6a2e4c
    0x0450: 'mn',
rpm-build 6a2e4c
    0x0850: 'mn-CN',
rpm-build 6a2e4c
    0x0461: 'ne',
rpm-build 6a2e4c
    0x0414: 'nb',
rpm-build 6a2e4c
    0x0814: 'nn',
rpm-build 6a2e4c
    0x0482: 'oc',
rpm-build 6a2e4c
    0x0448: 'or',
rpm-build 6a2e4c
    0x0463: 'ps',
rpm-build 6a2e4c
    0x0415: 'pl',
rpm-build 6a2e4c
    0x0416: 'pt',
rpm-build 6a2e4c
    0x0816: 'pt-PT',
rpm-build 6a2e4c
    0x0446: 'pa',
rpm-build 6a2e4c
    0x046B: 'qu-BO',
rpm-build 6a2e4c
    0x086B: 'qu-EC',
rpm-build 6a2e4c
    0x0C6B: 'qu',
rpm-build 6a2e4c
    0x0418: 'ro',
rpm-build 6a2e4c
    0x0417: 'rm',
rpm-build 6a2e4c
    0x0419: 'ru',
rpm-build 6a2e4c
    0x243B: 'smn',
rpm-build 6a2e4c
    0x103B: 'smj-NO',
rpm-build 6a2e4c
    0x143B: 'smj',
rpm-build 6a2e4c
    0x0C3B: 'se-FI',
rpm-build 6a2e4c
    0x043B: 'se',
rpm-build 6a2e4c
    0x083B: 'se-SE',
rpm-build 6a2e4c
    0x203B: 'sms',
rpm-build 6a2e4c
    0x183B: 'sma-NO',
rpm-build 6a2e4c
    0x1C3B: 'sms',
rpm-build 6a2e4c
    0x044F: 'sa',
rpm-build 6a2e4c
    0x1C1A: 'sr-Cyrl-BA',
rpm-build 6a2e4c
    0x0C1A: 'sr',
rpm-build 6a2e4c
    0x181A: 'sr-Latn-BA',
rpm-build 6a2e4c
    0x081A: 'sr-Latn',
rpm-build 6a2e4c
    0x046C: 'nso',
rpm-build 6a2e4c
    0x0432: 'tn',
rpm-build 6a2e4c
    0x045B: 'si',
rpm-build 6a2e4c
    0x041B: 'sk',
rpm-build 6a2e4c
    0x0424: 'sl',
rpm-build 6a2e4c
    0x2C0A: 'es-AR',
rpm-build 6a2e4c
    0x400A: 'es-BO',
rpm-build 6a2e4c
    0x340A: 'es-CL',
rpm-build 6a2e4c
    0x240A: 'es-CO',
rpm-build 6a2e4c
    0x140A: 'es-CR',
rpm-build 6a2e4c
    0x1C0A: 'es-DO',
rpm-build 6a2e4c
    0x300A: 'es-EC',
rpm-build 6a2e4c
    0x440A: 'es-SV',
rpm-build 6a2e4c
    0x100A: 'es-GT',
rpm-build 6a2e4c
    0x480A: 'es-HN',
rpm-build 6a2e4c
    0x080A: 'es-MX',
rpm-build 6a2e4c
    0x4C0A: 'es-NI',
rpm-build 6a2e4c
    0x180A: 'es-PA',
rpm-build 6a2e4c
    0x3C0A: 'es-PY',
rpm-build 6a2e4c
    0x280A: 'es-PE',
rpm-build 6a2e4c
    0x500A: 'es-PR',
rpm-build 6a2e4c
rpm-build 6a2e4c
    # Microsoft has defined two different language codes for
rpm-build 6a2e4c
    # “Spanish with modern sorting” and “Spanish with traditional
rpm-build 6a2e4c
    # sorting”. This makes sense for collation APIs, and it would be
rpm-build 6a2e4c
    # possible to express this in BCP 47 language tags via Unicode
rpm-build 6a2e4c
    # extensions (eg., “es-u-co-trad” is “Spanish with traditional
rpm-build 6a2e4c
    # sorting”). However, for storing names in fonts, this distinction
rpm-build 6a2e4c
    # does not make sense, so we use “es” in both cases.
rpm-build 6a2e4c
    0x0C0A: 'es',
rpm-build 6a2e4c
    0x040A: 'es',
rpm-build 6a2e4c
rpm-build 6a2e4c
    0x540A: 'es-US',
rpm-build 6a2e4c
    0x380A: 'es-UY',
rpm-build 6a2e4c
    0x200A: 'es-VE',
rpm-build 6a2e4c
    0x081D: 'sv-FI',
rpm-build 6a2e4c
    0x041D: 'sv',
rpm-build 6a2e4c
    0x045A: 'syr',
rpm-build 6a2e4c
    0x0428: 'tg',
rpm-build 6a2e4c
    0x085F: 'tzm',
rpm-build 6a2e4c
    0x0449: 'ta',
rpm-build 6a2e4c
    0x0444: 'tt',
rpm-build 6a2e4c
    0x044A: 'te',
rpm-build 6a2e4c
    0x041E: 'th',
rpm-build 6a2e4c
    0x0451: 'bo',
rpm-build 6a2e4c
    0x041F: 'tr',
rpm-build 6a2e4c
    0x0442: 'tk',
rpm-build 6a2e4c
    0x0480: 'ug',
rpm-build 6a2e4c
    0x0422: 'uk',
rpm-build 6a2e4c
    0x042E: 'hsb',
rpm-build 6a2e4c
    0x0420: 'ur',
rpm-build 6a2e4c
    0x0843: 'uz-Cyrl',
rpm-build 6a2e4c
    0x0443: 'uz',
rpm-build 6a2e4c
    0x042A: 'vi',
rpm-build 6a2e4c
    0x0452: 'cy',
rpm-build 6a2e4c
    0x0488: 'wo',
rpm-build 6a2e4c
    0x0485: 'sah',
rpm-build 6a2e4c
    0x0478: 'ii',
rpm-build 6a2e4c
    0x046A: 'yo',
rpm-build 6a2e4c
}
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
_MAC_LANGUAGES = {
rpm-build 6a2e4c
    0: 'en',
rpm-build 6a2e4c
    1: 'fr',
rpm-build 6a2e4c
    2: 'de',
rpm-build 6a2e4c
    3: 'it',
rpm-build 6a2e4c
    4: 'nl',
rpm-build 6a2e4c
    5: 'sv',
rpm-build 6a2e4c
    6: 'es',
rpm-build 6a2e4c
    7: 'da',
rpm-build 6a2e4c
    8: 'pt',
rpm-build 6a2e4c
    9: 'no',
rpm-build 6a2e4c
    10: 'he',
rpm-build 6a2e4c
    11: 'ja',
rpm-build 6a2e4c
    12: 'ar',
rpm-build 6a2e4c
    13: 'fi',
rpm-build 6a2e4c
    14: 'el',
rpm-build 6a2e4c
    15: 'is',
rpm-build 6a2e4c
    16: 'mt',
rpm-build 6a2e4c
    17: 'tr',
rpm-build 6a2e4c
    18: 'hr',
rpm-build 6a2e4c
    19: 'zh-Hant',
rpm-build 6a2e4c
    20: 'ur',
rpm-build 6a2e4c
    21: 'hi',
rpm-build 6a2e4c
    22: 'th',
rpm-build 6a2e4c
    23: 'ko',
rpm-build 6a2e4c
    24: 'lt',
rpm-build 6a2e4c
    25: 'pl',
rpm-build 6a2e4c
    26: 'hu',
rpm-build 6a2e4c
    27: 'es',
rpm-build 6a2e4c
    28: 'lv',
rpm-build 6a2e4c
    29: 'se',
rpm-build 6a2e4c
    30: 'fo',
rpm-build 6a2e4c
    31: 'fa',
rpm-build 6a2e4c
    32: 'ru',
rpm-build 6a2e4c
    33: 'zh',
rpm-build 6a2e4c
    34: 'nl-BE',
rpm-build 6a2e4c
    35: 'ga',
rpm-build 6a2e4c
    36: 'sq',
rpm-build 6a2e4c
    37: 'ro',
rpm-build 6a2e4c
    38: 'cz',
rpm-build 6a2e4c
    39: 'sk',
rpm-build 6a2e4c
    40: 'sl',
rpm-build 6a2e4c
    41: 'yi',
rpm-build 6a2e4c
    42: 'sr',
rpm-build 6a2e4c
    43: 'mk',
rpm-build 6a2e4c
    44: 'bg',
rpm-build 6a2e4c
    45: 'uk',
rpm-build 6a2e4c
    46: 'be',
rpm-build 6a2e4c
    47: 'uz',
rpm-build 6a2e4c
    48: 'kk',
rpm-build 6a2e4c
    49: 'az-Cyrl',
rpm-build 6a2e4c
    50: 'az-Arab',
rpm-build 6a2e4c
    51: 'hy',
rpm-build 6a2e4c
    52: 'ka',
rpm-build 6a2e4c
    53: 'mo',
rpm-build 6a2e4c
    54: 'ky',
rpm-build 6a2e4c
    55: 'tg',
rpm-build 6a2e4c
    56: 'tk',
rpm-build 6a2e4c
    57: 'mn-CN',
rpm-build 6a2e4c
    58: 'mn',
rpm-build 6a2e4c
    59: 'ps',
rpm-build 6a2e4c
    60: 'ks',
rpm-build 6a2e4c
    61: 'ku',
rpm-build 6a2e4c
    62: 'sd',
rpm-build 6a2e4c
    63: 'bo',
rpm-build 6a2e4c
    64: 'ne',
rpm-build 6a2e4c
    65: 'sa',
rpm-build 6a2e4c
    66: 'mr',
rpm-build 6a2e4c
    67: 'bn',
rpm-build 6a2e4c
    68: 'as',
rpm-build 6a2e4c
    69: 'gu',
rpm-build 6a2e4c
    70: 'pa',
rpm-build 6a2e4c
    71: 'or',
rpm-build 6a2e4c
    72: 'ml',
rpm-build 6a2e4c
    73: 'kn',
rpm-build 6a2e4c
    74: 'ta',
rpm-build 6a2e4c
    75: 'te',
rpm-build 6a2e4c
    76: 'si',
rpm-build 6a2e4c
    77: 'my',
rpm-build 6a2e4c
    78: 'km',
rpm-build 6a2e4c
    79: 'lo',
rpm-build 6a2e4c
    80: 'vi',
rpm-build 6a2e4c
    81: 'id',
rpm-build 6a2e4c
    82: 'tl',
rpm-build 6a2e4c
    83: 'ms',
rpm-build 6a2e4c
    84: 'ms-Arab',
rpm-build 6a2e4c
    85: 'am',
rpm-build 6a2e4c
    86: 'ti',
rpm-build 6a2e4c
    87: 'om',
rpm-build 6a2e4c
    88: 'so',
rpm-build 6a2e4c
    89: 'sw',
rpm-build 6a2e4c
    90: 'rw',
rpm-build 6a2e4c
    91: 'rn',
rpm-build 6a2e4c
    92: 'ny',
rpm-build 6a2e4c
    93: 'mg',
rpm-build 6a2e4c
    94: 'eo',
rpm-build 6a2e4c
    128: 'cy',
rpm-build 6a2e4c
    129: 'eu',
rpm-build 6a2e4c
    130: 'ca',
rpm-build 6a2e4c
    131: 'la',
rpm-build 6a2e4c
    132: 'qu',
rpm-build 6a2e4c
    133: 'gn',
rpm-build 6a2e4c
    134: 'ay',
rpm-build 6a2e4c
    135: 'tt',
rpm-build 6a2e4c
    136: 'ug',
rpm-build 6a2e4c
    137: 'dz',
rpm-build 6a2e4c
    138: 'jv',
rpm-build 6a2e4c
    139: 'su',
rpm-build 6a2e4c
    140: 'gl',
rpm-build 6a2e4c
    141: 'af',
rpm-build 6a2e4c
    142: 'br',
rpm-build 6a2e4c
    143: 'iu',
rpm-build 6a2e4c
    144: 'gd',
rpm-build 6a2e4c
    145: 'gv',
rpm-build 6a2e4c
    146: 'ga',
rpm-build 6a2e4c
    147: 'to',
rpm-build 6a2e4c
    148: 'el-polyton',
rpm-build 6a2e4c
    149: 'kl',
rpm-build 6a2e4c
    150: 'az',
rpm-build 6a2e4c
    151: 'nn',
rpm-build 6a2e4c
}
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
_WINDOWS_LANGUAGE_CODES = {lang.lower(): code for code, lang in _WINDOWS_LANGUAGES.items()}
rpm-build 6a2e4c
_MAC_LANGUAGE_CODES = {lang.lower(): code for code, lang in _MAC_LANGUAGES.items()}
rpm-build 6a2e4c
rpm-build 6a2e4c
rpm-build 6a2e4c
# MacOS language ID → MacOS script ID
rpm-build 6a2e4c
#
rpm-build 6a2e4c
# Note that the script ID is not sufficient to determine what encoding
rpm-build 6a2e4c
# to use in TrueType files. For some languages, MacOS used a modification
rpm-build 6a2e4c
# of a mainstream script. For example, an Icelandic name would be stored
rpm-build 6a2e4c
# with smRoman in the TrueType naming table, but the actual encoding
rpm-build 6a2e4c
# is a special Icelandic version of the normal Macintosh Roman encoding.
rpm-build 6a2e4c
# As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal
rpm-build 6a2e4c
# Syllables but MacOS had run out of available script codes, so this was
rpm-build 6a2e4c
# done as a (pretty radical) “modification” of Ethiopic.
rpm-build 6a2e4c
#
rpm-build 6a2e4c
# http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
rpm-build 6a2e4c
_MAC_LANGUAGE_TO_SCRIPT = {
rpm-build 6a2e4c
    0: 0,  # langEnglish → smRoman
rpm-build 6a2e4c
    1: 0,  # langFrench → smRoman
rpm-build 6a2e4c
    2: 0,  # langGerman → smRoman
rpm-build 6a2e4c
    3: 0,  # langItalian → smRoman
rpm-build 6a2e4c
    4: 0,  # langDutch → smRoman
rpm-build 6a2e4c
    5: 0,  # langSwedish → smRoman
rpm-build 6a2e4c
    6: 0,  # langSpanish → smRoman
rpm-build 6a2e4c
    7: 0,  # langDanish → smRoman
rpm-build 6a2e4c
    8: 0,  # langPortuguese → smRoman
rpm-build 6a2e4c
    9: 0,  # langNorwegian → smRoman
rpm-build 6a2e4c
    10: 5,  # langHebrew → smHebrew
rpm-build 6a2e4c
    11: 1,  # langJapanese → smJapanese
rpm-build 6a2e4c
    12: 4,  # langArabic → smArabic
rpm-build 6a2e4c
    13: 0,  # langFinnish → smRoman
rpm-build 6a2e4c
    14: 6,  # langGreek → smGreek
rpm-build 6a2e4c
    15: 0,  # langIcelandic → smRoman (modified)
rpm-build 6a2e4c
    16: 0,  # langMaltese → smRoman
rpm-build 6a2e4c
    17: 0,  # langTurkish → smRoman (modified)
rpm-build 6a2e4c
    18: 0,  # langCroatian → smRoman (modified)
rpm-build 6a2e4c
    19: 2,  # langTradChinese → smTradChinese
rpm-build 6a2e4c
    20: 4,  # langUrdu → smArabic
rpm-build 6a2e4c
    21: 9,  # langHindi → smDevanagari
rpm-build 6a2e4c
    22: 21,  # langThai → smThai
rpm-build 6a2e4c
    23: 3,  # langKorean → smKorean
rpm-build 6a2e4c
    24: 29,  # langLithuanian → smCentralEuroRoman
rpm-build 6a2e4c
    25: 29,  # langPolish → smCentralEuroRoman
rpm-build 6a2e4c
    26: 29,  # langHungarian → smCentralEuroRoman
rpm-build 6a2e4c
    27: 29,  # langEstonian → smCentralEuroRoman
rpm-build 6a2e4c
    28: 29,  # langLatvian → smCentralEuroRoman
rpm-build 6a2e4c
    29: 0,  # langSami → smRoman
rpm-build 6a2e4c
    30: 0,  # langFaroese → smRoman (modified)
rpm-build 6a2e4c
    31: 4,  # langFarsi → smArabic (modified)
rpm-build 6a2e4c
    32: 7,  # langRussian → smCyrillic
rpm-build 6a2e4c
    33: 25,  # langSimpChinese → smSimpChinese
rpm-build 6a2e4c
    34: 0,  # langFlemish → smRoman
rpm-build 6a2e4c
    35: 0,  # langIrishGaelic → smRoman (modified)
rpm-build 6a2e4c
    36: 0,  # langAlbanian → smRoman
rpm-build 6a2e4c
    37: 0,  # langRomanian → smRoman (modified)
rpm-build 6a2e4c
    38: 29,  # langCzech → smCentralEuroRoman
rpm-build 6a2e4c
    39: 29,  # langSlovak → smCentralEuroRoman
rpm-build 6a2e4c
    40: 0,  # langSlovenian → smRoman (modified)
rpm-build 6a2e4c
    41: 5,  # langYiddish → smHebrew
rpm-build 6a2e4c
    42: 7,  # langSerbian → smCyrillic
rpm-build 6a2e4c
    43: 7,  # langMacedonian → smCyrillic
rpm-build 6a2e4c
    44: 7,  # langBulgarian → smCyrillic
rpm-build 6a2e4c
    45: 7,  # langUkrainian → smCyrillic (modified)
rpm-build 6a2e4c
    46: 7,  # langByelorussian → smCyrillic
rpm-build 6a2e4c
    47: 7,  # langUzbek → smCyrillic
rpm-build 6a2e4c
    48: 7,  # langKazakh → smCyrillic
rpm-build 6a2e4c
    49: 7,  # langAzerbaijani → smCyrillic
rpm-build 6a2e4c
    50: 4,  # langAzerbaijanAr → smArabic
rpm-build 6a2e4c
    51: 24,  # langArmenian → smArmenian
rpm-build 6a2e4c
    52: 23,  # langGeorgian → smGeorgian
rpm-build 6a2e4c
    53: 7,  # langMoldavian → smCyrillic
rpm-build 6a2e4c
    54: 7,  # langKirghiz → smCyrillic
rpm-build 6a2e4c
    55: 7,  # langTajiki → smCyrillic
rpm-build 6a2e4c
    56: 7,  # langTurkmen → smCyrillic
rpm-build 6a2e4c
    57: 27,  # langMongolian → smMongolian
rpm-build 6a2e4c
    58: 7,  # langMongolianCyr → smCyrillic
rpm-build 6a2e4c
    59: 4,  # langPashto → smArabic
rpm-build 6a2e4c
    60: 4,  # langKurdish → smArabic
rpm-build 6a2e4c
    61: 4,  # langKashmiri → smArabic
rpm-build 6a2e4c
    62: 4,  # langSindhi → smArabic
rpm-build 6a2e4c
    63: 26,  # langTibetan → smTibetan
rpm-build 6a2e4c
    64: 9,  # langNepali → smDevanagari
rpm-build 6a2e4c
    65: 9,  # langSanskrit → smDevanagari
rpm-build 6a2e4c
    66: 9,  # langMarathi → smDevanagari
rpm-build 6a2e4c
    67: 13,  # langBengali → smBengali
rpm-build 6a2e4c
    68: 13,  # langAssamese → smBengali
rpm-build 6a2e4c
    69: 11,  # langGujarati → smGujarati
rpm-build 6a2e4c
    70: 10,  # langPunjabi → smGurmukhi
rpm-build 6a2e4c
    71: 12,  # langOriya → smOriya
rpm-build 6a2e4c
    72: 17,  # langMalayalam → smMalayalam
rpm-build 6a2e4c
    73: 16,  # langKannada → smKannada
rpm-build 6a2e4c
    74: 14,  # langTamil → smTamil
rpm-build 6a2e4c
    75: 15,  # langTelugu → smTelugu
rpm-build 6a2e4c
    76: 18,  # langSinhalese → smSinhalese
rpm-build 6a2e4c
    77: 19,  # langBurmese → smBurmese
rpm-build 6a2e4c
    78: 20,  # langKhmer → smKhmer
rpm-build 6a2e4c
    79: 22,  # langLao → smLao
rpm-build 6a2e4c
    80: 30,  # langVietnamese → smVietnamese
rpm-build 6a2e4c
    81: 0,  # langIndonesian → smRoman
rpm-build 6a2e4c
    82: 0,  # langTagalog → smRoman
rpm-build 6a2e4c
    83: 0,  # langMalayRoman → smRoman
rpm-build 6a2e4c
    84: 4,  # langMalayArabic → smArabic
rpm-build 6a2e4c
    85: 28,  # langAmharic → smEthiopic
rpm-build 6a2e4c
    86: 28,  # langTigrinya → smEthiopic
rpm-build 6a2e4c
    87: 28,  # langOromo → smEthiopic
rpm-build 6a2e4c
    88: 0,  # langSomali → smRoman
rpm-build 6a2e4c
    89: 0,  # langSwahili → smRoman
rpm-build 6a2e4c
    90: 0,  # langKinyarwanda → smRoman
rpm-build 6a2e4c
    91: 0,  # langRundi → smRoman
rpm-build 6a2e4c
    92: 0,  # langNyanja → smRoman
rpm-build 6a2e4c
    93: 0,  # langMalagasy → smRoman
rpm-build 6a2e4c
    94: 0,  # langEsperanto → smRoman
rpm-build 6a2e4c
    128: 0,  # langWelsh → smRoman (modified)
rpm-build 6a2e4c
    129: 0,  # langBasque → smRoman
rpm-build 6a2e4c
    130: 0,  # langCatalan → smRoman
rpm-build 6a2e4c
    131: 0,  # langLatin → smRoman
rpm-build 6a2e4c
    132: 0,  # langQuechua → smRoman
rpm-build 6a2e4c
    133: 0,  # langGuarani → smRoman
rpm-build 6a2e4c
    134: 0,  # langAymara → smRoman
rpm-build 6a2e4c
    135: 7,  # langTatar → smCyrillic
rpm-build 6a2e4c
    136: 4,  # langUighur → smArabic
rpm-build 6a2e4c
    137: 26,  # langDzongkha → smTibetan
rpm-build 6a2e4c
    138: 0,  # langJavaneseRom → smRoman
rpm-build 6a2e4c
    139: 0,  # langSundaneseRom → smRoman
rpm-build 6a2e4c
    140: 0,  # langGalician → smRoman
rpm-build 6a2e4c
    141: 0,  # langAfrikaans → smRoman
rpm-build 6a2e4c
    142: 0,  # langBreton → smRoman (modified)
rpm-build 6a2e4c
    143: 28,  # langInuktitut → smEthiopic (modified)
rpm-build 6a2e4c
    144: 0,  # langScottishGaelic → smRoman (modified)
rpm-build 6a2e4c
    145: 0,  # langManxGaelic → smRoman (modified)
rpm-build 6a2e4c
    146: 0,  # langIrishGaelicScript → smRoman (modified)
rpm-build 6a2e4c
    147: 0,  # langTongan → smRoman
rpm-build 6a2e4c
    148: 6,  # langGreekAncient → smRoman
rpm-build 6a2e4c
    149: 0,  # langGreenlandic → smRoman
rpm-build 6a2e4c
    150: 0,  # langAzerbaijanRoman → smRoman
rpm-build 6a2e4c
    151: 0,   # langNynorsk → smRoman
rpm-build 6a2e4c
}