[AAT] Support cidg
table with CID-to-glyph mapping
This commit is contained in:
parent
0f05f824d2
commit
db0d193db6
20
Lib/fontTools/ttLib/tables/_c_i_d_g.py
Normal file
20
Lib/fontTools/ttLib/tables/_c_i_d_g.py
Normal file
@ -0,0 +1,20 @@
|
||||
# coding: utf-8
|
||||
from __future__ import print_function, division, absolute_import
|
||||
from fontTools.misc.py23 import *
|
||||
from .otBase import BaseTTXConverter
|
||||
|
||||
|
||||
# The AAT ‘cidg’ table has almost the same structure as ‘gidc’,
|
||||
# just mapping CIDs to GlyphIDs instead of the reverse direction.
|
||||
#
|
||||
# It is useful for fonts that may be used by a PDF renderer in lieu of
|
||||
# a font reference with a known glyph collection but no subsetted
|
||||
# glyphs. For instance, a PDF can say “please use a font conforming
|
||||
# to Adobe-Japan-1”; the ‘cidg’ mapping is necessary if the font is,
|
||||
# say, a TrueType font. ‘gidc’ is lossy for this purpose and is
|
||||
# obsoleted by ‘cidg’.
|
||||
#
|
||||
# For example, the first font in /System/Library/Fonts/PingFang.ttc
|
||||
# (which Apple ships pre-installed on MacOS 10.12.6) has a ‘cidg’ table.
|
||||
class table__c_i_d_g(BaseTTXConverter):
|
||||
pass
|
@ -43,7 +43,7 @@ def buildConverters(tableSpec, tableNamespace):
|
||||
converterClass = SubStruct
|
||||
elif name == "FeatureParams":
|
||||
converterClass = FeatureParams
|
||||
elif name == "GlyphCIDMapping":
|
||||
elif name in ("CIDGlyphMapping", "GlyphCIDMapping"):
|
||||
converterClass = StructWithLength
|
||||
else:
|
||||
if not tp in converterMapping and '(' not in tp:
|
||||
@ -1082,6 +1082,43 @@ class STXHeader(BaseConverter):
|
||||
return state
|
||||
|
||||
|
||||
class CIDGlyphMap(BaseConverter):
|
||||
def read(self, reader, font, tableDict):
|
||||
numCIDs = reader.readUShort()
|
||||
result = {}
|
||||
for cid, glyphID in enumerate(reader.readUShortArray(numCIDs)):
|
||||
if glyphID != 0xFFFF:
|
||||
result[cid] = font.getGlyphName(glyphID)
|
||||
return result
|
||||
|
||||
def write(self, writer, font, tableDict, value, repeatIndex=None):
|
||||
items = {cid: font.getGlyphID(glyph)
|
||||
for cid, glyph in value.items()}
|
||||
count = max(items) + 1 if items else 0
|
||||
writer.writeUShort(count)
|
||||
for cid in range(count):
|
||||
writer.writeUShort(items.get(cid, 0xFFFF))
|
||||
|
||||
def xmlRead(self, attrs, content, font):
|
||||
result = {}
|
||||
for eName, eAttrs, _eContent in filter(istuple, content):
|
||||
if eName == "CID":
|
||||
result[safeEval(eAttrs["cid"])] = \
|
||||
eAttrs["glyph"].strip()
|
||||
return result
|
||||
|
||||
def xmlWrite(self, xmlWriter, font, value, name, attrs):
|
||||
xmlWriter.begintag(name, attrs)
|
||||
xmlWriter.newline()
|
||||
for cid, glyph in sorted(value.items()):
|
||||
if glyph is not None and glyph != 0xFFFF:
|
||||
xmlWriter.simpletag(
|
||||
"CID", cid=cid, glyph=glyph)
|
||||
xmlWriter.newline()
|
||||
xmlWriter.endtag(name)
|
||||
xmlWriter.newline()
|
||||
|
||||
|
||||
class GlyphCIDMap(BaseConverter):
|
||||
def read(self, reader, font, tableDict):
|
||||
glyphOrder = font.getGlyphOrder()
|
||||
@ -1096,7 +1133,7 @@ class GlyphCIDMap(BaseConverter):
|
||||
for glyphID in range(min(len(cids), len(glyphOrder))):
|
||||
cid = cids[glyphID]
|
||||
if cid != 0xFFFF:
|
||||
result[glyphOrder[glyphID]] = cids[glyphID]
|
||||
result[glyphOrder[glyphID]] = cid
|
||||
return result
|
||||
|
||||
def write(self, writer, font, tableDict, value, repeatIndex=None):
|
||||
@ -1294,6 +1331,7 @@ converterMapping = {
|
||||
"VarDataValue": VarDataValue,
|
||||
|
||||
# AAT
|
||||
"CIDGlyphMap": CIDGlyphMap,
|
||||
"GlyphCIDMap": GlyphCIDMap,
|
||||
"MortChain": StructWithLength,
|
||||
"MortSubtable": StructWithLength,
|
||||
|
@ -1249,6 +1249,27 @@ otData = [
|
||||
]),
|
||||
|
||||
|
||||
#
|
||||
# cidg
|
||||
#
|
||||
|
||||
('cidg', [
|
||||
('struct', 'CIDGlyphMapping', None, None, 'CID-to-glyph mapping table.'),
|
||||
]),
|
||||
|
||||
('CIDGlyphMappingFormat0', [
|
||||
('uint16', 'Format', None, None, 'Format of the CID-to-glyph mapping table, = 0.'),
|
||||
('uint16', 'DataFormat', None, None, 'Currenty unused, set to zero.'),
|
||||
('uint32', 'StructLength', None, None, 'Size of the table in bytes.'),
|
||||
('uint16', 'Registry', None, None, 'The registry ID.'),
|
||||
('char64', 'RegistryName', None, None, 'The registry name in ASCII; unused bytes should be set to 0.'),
|
||||
('uint16', 'Order', None, None, 'The order ID.'),
|
||||
('char64', 'OrderName', None, None, 'The order name in ASCII; unused bytes should be set to 0.'),
|
||||
('uint16', 'SupplementVersion', None, None, 'The supplement version.'),
|
||||
('CIDGlyphMap', 'Mapping', None, None, 'A mapping from CIDs to the glyphs in the font, starting with CID 0. If a CID from the identified collection has no glyph in the font, 0xFFFF is used'),
|
||||
]),
|
||||
|
||||
|
||||
#
|
||||
# feat
|
||||
#
|
||||
@ -1300,7 +1321,7 @@ otData = [
|
||||
('uint16', 'Order', None, None, 'The order ID.'),
|
||||
('char64', 'OrderName', None, None, 'The order name in ASCII; unused bytes should be set to 0.'),
|
||||
('uint16', 'SupplementVersion', None, None, 'The supplement version.'),
|
||||
('GlyphCIDMap', 'CIDs', None, None, 'The CIDs for the glyphs in the font, starting with glyph 0. If a glyph does not correspond to a CID in the identified collection, 0xFFFF is used'),
|
||||
('GlyphCIDMap', 'Mapping', None, None, 'The CIDs for the glyphs in the font, starting with glyph 0. If a glyph does not correspond to a CID in the identified collection, 0xFFFF is used'),
|
||||
]),
|
||||
|
||||
|
||||
|
70
Tests/ttLib/tables/_c_i_d_g_test.py
Normal file
70
Tests/ttLib/tables/_c_i_d_g_test.py
Normal file
@ -0,0 +1,70 @@
|
||||
# coding: utf-8
|
||||
from __future__ import print_function, division, absolute_import, unicode_literals
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.misc.testTools import FakeFont, getXML, parseXML
|
||||
from fontTools.misc.textTools import deHexStr, hexStr
|
||||
from fontTools.ttLib import newTable
|
||||
import unittest
|
||||
|
||||
|
||||
# On macOS X 10.12.6, the first font in /System/Library/Fonts/PingFang.ttc
|
||||
# has a ‘cidg’ table with a similar structure as this test data, just larger.
|
||||
CIDG_DATA = deHexStr(
|
||||
"0000 0000 " # 0: Format=0, Flags=0
|
||||
"0000 0098 " # 4: StructLength=152
|
||||
"0000 " # 8: Registry=0
|
||||
"41 64 6F 62 65 " # 10: RegistryName="Adobe"
|
||||
+ ("00" * 59) + # 15: <padding>
|
||||
"0002 " # 74: Order=2
|
||||
"43 4E 53 31 " # 76: Order="CNS1"
|
||||
+ ("00" * 60) + # 80: <padding>
|
||||
"0000 " # 140: SupplementVersion=0
|
||||
"0004 " # 142: Count
|
||||
"0000 " # 144: GlyphID[0]=.notdef
|
||||
"FFFF " # 146: CIDs[1]=<None>
|
||||
"0003 " # 148: CIDs[2]=C
|
||||
"0001 " # 150: CIDs[3]=A
|
||||
) # 152: <end>
|
||||
assert len(CIDG_DATA) == 152, len(CIDG_DATA)
|
||||
|
||||
|
||||
CIDG_XML = [
|
||||
'<CIDGlyphMapping Format="0">',
|
||||
' <DataFormat value="0"/>',
|
||||
' <!-- StructLength=152 -->',
|
||||
' <Registry value="0"/>',
|
||||
' <RegistryName value="Adobe"/>',
|
||||
' <Order value="2"/>',
|
||||
' <OrderName value="CNS1"/>',
|
||||
' <SupplementVersion value="0"/>',
|
||||
' <Mapping>',
|
||||
' <CID cid="0" glyph=".notdef"/>',
|
||||
' <CID cid="2" glyph="C"/>',
|
||||
' <CID cid="3" glyph="A"/>',
|
||||
' </Mapping>',
|
||||
'</CIDGlyphMapping>',
|
||||
]
|
||||
|
||||
|
||||
class GCIDTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.maxDiff = None
|
||||
cls.font = FakeFont(['.notdef', 'A', 'B', 'C', 'D'])
|
||||
|
||||
def testDecompileToXML(self):
|
||||
table = newTable('cidg')
|
||||
table.decompile(CIDG_DATA, self.font)
|
||||
self.assertEqual(getXML(table.toXML, self.font), CIDG_XML)
|
||||
|
||||
def testCompileFromXML(self):
|
||||
table = newTable('cidg')
|
||||
for name, attrs, content in parseXML(CIDG_XML):
|
||||
table.fromXML(name, attrs, content, font=self.font)
|
||||
self.assertEqual(hexStr(table.compile(self.font)),
|
||||
hexStr(CIDG_DATA))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(unittest.main())
|
@ -37,11 +37,11 @@ GCID_XML = [
|
||||
' <Order value="3"/>',
|
||||
' <OrderName value="Korea1"/>',
|
||||
' <SupplementVersion value="1"/>',
|
||||
' <CIDs>',
|
||||
' <Mapping>',
|
||||
' <CID glyph=".notdef" value="4660"/>',
|
||||
' <CID glyph="B" value="7"/>',
|
||||
' <CID glyph="C" value="57072"/>',
|
||||
' </CIDs>',
|
||||
' </Mapping>',
|
||||
'</GlyphCIDMapping>',
|
||||
]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user