Merge pull request #1091 from readroberts/master
[CFF2] Fixes for writing PrivateDict BlueValues and Subrs to XML.
This commit is contained in:
commit
d91faeaf1a
@ -614,6 +614,11 @@ class GlobalSubrsIndex(Index):
|
||||
self.fdSelect = fdSelect
|
||||
if fdArray:
|
||||
self.fdArray = fdArray
|
||||
if isCFF2:
|
||||
# CFF2Subr's can have numeric arguments on the stack after the last operator.
|
||||
self.subrClass = psCharStrings.CFF2Subr
|
||||
self.charStringClass = psCharStrings.CFF2Subr
|
||||
|
||||
|
||||
def produceItem(self, index, data, file, offset):
|
||||
if self.private is not None:
|
||||
@ -1972,12 +1977,7 @@ class DictCompiler(object):
|
||||
|
||||
def arg_number(self, num):
|
||||
if isinstance(num, list):
|
||||
blendList = num
|
||||
firstNum = blendList[0]
|
||||
data = [firstNum]
|
||||
for blendNum in blendList[1:]:
|
||||
data.append(blendNum - firstNum)
|
||||
data = [encodeNumber(val) for val in data]
|
||||
data = [encodeNumber(val) for val in num]
|
||||
data.append(encodeNumber(1))
|
||||
data.append(bytechr(blendOp))
|
||||
datum = bytesjoin(data)
|
||||
@ -2011,15 +2011,33 @@ class DictCompiler(object):
|
||||
data.append(encodeNumber(num))
|
||||
return bytesjoin(data)
|
||||
|
||||
|
||||
def arg_delta_blend(self, value):
|
||||
# A delta list with blend lists has to be *all* blend lists.
|
||||
# We have a list of master value lists, where the nth master value list
|
||||
# contains the absolute values from each master for the nth entry in the
|
||||
# current array.
|
||||
# We first convert these to relative values from the previous entry.
|
||||
""" A delta list with blend lists has to be *all* blend lists.
|
||||
The value is a list is arranged as follows.
|
||||
[
|
||||
[V0, d0..dn]
|
||||
[V1, d0..dn]
|
||||
...
|
||||
[Vm, d0..dn]
|
||||
]
|
||||
V is the absolute coordinate value from the default font, and d0-dn are
|
||||
the delta values from the n regions. Each V is an absolute coordinate
|
||||
from the default font.
|
||||
We want to return a list:
|
||||
[
|
||||
[v0, v1..vm]
|
||||
[d0..dn]
|
||||
...
|
||||
[d0..dn]
|
||||
numBlends
|
||||
blendOp
|
||||
]
|
||||
where each v is relative to the previous default font value.
|
||||
"""
|
||||
numMasters = len(value[0])
|
||||
numValues = len(value)
|
||||
numStack = (numValues * numMasters) + 1
|
||||
numBlends = len(value)
|
||||
numStack = (numBlends * numMasters) + 1
|
||||
if numStack > self.maxBlendStack:
|
||||
# Figure out the max number of value we can blend
|
||||
# and divide this list up into chunks of that size.
|
||||
@ -2035,28 +2053,26 @@ class DictCompiler(object):
|
||||
out.extend(out1)
|
||||
value = value[numVal:]
|
||||
else:
|
||||
firstList = [0] * numValues
|
||||
deltaList = [None] * (numValues)
|
||||
firstList = [0] * numBlends
|
||||
deltaList = [None] * numBlends
|
||||
i = 0
|
||||
prevValList = numMasters * [0]
|
||||
while i < numValues:
|
||||
masterValList = value[i]
|
||||
firstVal = firstList[i] = masterValList[0] - prevValList[0]
|
||||
j = 1
|
||||
deltaEntry = (numMasters - 1) * [0]
|
||||
while j < numMasters:
|
||||
masterValDelta = masterValList[j] - prevValList[j]
|
||||
deltaEntry[j - 1] = masterValDelta - firstVal
|
||||
j += 1
|
||||
deltaList[i] = deltaEntry
|
||||
prevVal = 0
|
||||
while i < numBlends:
|
||||
# For PrivateDict BlueValues, the default font
|
||||
# values are absolute, not relative.
|
||||
# Must convert these back to relative coordinates
|
||||
# befor writing to CFF2.
|
||||
defaultValue = value[i][0]
|
||||
firstList[i] = defaultValue - prevVal
|
||||
prevVal = defaultValue
|
||||
deltaList[i] = value[i][1:]
|
||||
i += 1
|
||||
prevValList = masterValList
|
||||
|
||||
relValueList = firstList
|
||||
for blendList in deltaList:
|
||||
relValueList.extend(blendList)
|
||||
out = [encodeNumber(val) for val in relValueList]
|
||||
out.append(encodeNumber(numValues))
|
||||
out.append(encodeNumber(numBlends))
|
||||
out.append(bytechr(blendOp))
|
||||
return out
|
||||
|
||||
|
@ -943,7 +943,8 @@ class T2CharString(object):
|
||||
operators, opcodes = buildOperatorDict(t2Operators)
|
||||
decompilerClass = SimpleT2Decompiler
|
||||
outlineExtractor = T2OutlineExtractor
|
||||
|
||||
isCFF2 = False
|
||||
|
||||
def __init__(self, bytecode=None, program=None, private=None, globalSubrs=None):
|
||||
if program is None:
|
||||
program = []
|
||||
@ -1102,6 +1103,14 @@ class T2CharString(object):
|
||||
args = []
|
||||
else:
|
||||
args.append(token)
|
||||
if args:
|
||||
if self.isCFF2:
|
||||
# CFF2Subr's can have numeric arguments on the stack after the last operator.
|
||||
args = [str(arg) for arg in args]
|
||||
line = ' '.join(args)
|
||||
xmlWriter.write(line)
|
||||
else:
|
||||
assert 0, "T2Charstring or Subr has items on the stack after last operator."
|
||||
|
||||
def fromXML(self, name, attrs, content):
|
||||
from fontTools.misc.textTools import binary2num, readHex
|
||||
@ -1136,6 +1145,8 @@ class T2CharString(object):
|
||||
program.append(token)
|
||||
self.setProgram(program)
|
||||
|
||||
class CFF2Subr(T2CharString):
|
||||
isCFF2 = True
|
||||
|
||||
class T1CharString(T2CharString):
|
||||
|
||||
@ -1173,7 +1184,6 @@ class T1CharString(T2CharString):
|
||||
extractor.execute(self)
|
||||
self.width = extractor.width
|
||||
|
||||
|
||||
class DictDecompiler(object):
|
||||
|
||||
operandEncoding = cffDictOperandEncoding
|
||||
@ -1246,36 +1256,34 @@ class DictDecompiler(object):
|
||||
def arg_array(self, name):
|
||||
return self.popall()
|
||||
def arg_blendList(self, name):
|
||||
# The last item on the stack is the number of return values, aka numValues.
|
||||
# before that we have [numValues: args from first master]
|
||||
# then numValues blend lists, where each blend list is numMasters -1
|
||||
# Total number of values is numValues + (numValues * (numMasters -1)), == numValues * numMasters.
|
||||
# reformat list to be numReturnValues tuples, each tuple with nMaster values
|
||||
"""
|
||||
There may be non-blend args at the top of the stack. We first calculate
|
||||
where the blend args start in the stack. These are the last
|
||||
numMasters*numBlends) +1 args.
|
||||
The blend args starts with numMasters relative coordinate values, the BlueValues in the list from the default master font. This is followed by
|
||||
numBlends list of values. Each of value in one of these lists is the
|
||||
Variable Font delta for the matching region.
|
||||
|
||||
We re-arrange this to be a list of numMaster entries. Each entry starts with the corresponding default font relative value, and is followed by
|
||||
the delta values. We then convert the default values, the first item in each entry, to an absolute value.
|
||||
"""
|
||||
vsindex = self.dict.get('vsindex', 0)
|
||||
numMasters = self.parent.getNumRegions(vsindex) + 1 # only a PrivateDict has blended ops.
|
||||
numReturnValues = self.pop()
|
||||
stackIndex = -numMasters * numReturnValues
|
||||
args = self.stack[stackIndex:]
|
||||
del self.stack[stackIndex:]
|
||||
numBlends = self.pop()
|
||||
args = self.popall()
|
||||
numArgs = len(args)
|
||||
value = [None]*numReturnValues
|
||||
# The spec says that there should be no non-blended Blue Values,.
|
||||
assert(numArgs == numMasters * numBlends)
|
||||
value = [None]*numBlends
|
||||
numDeltas = numMasters-1
|
||||
i = 0
|
||||
prevVal = 0
|
||||
prevValueList = [0]*numMasters
|
||||
while i < numReturnValues:
|
||||
while i < numBlends:
|
||||
newVal = args[i] + prevVal
|
||||
blendList = [newVal]*numMasters
|
||||
prevVal = newVal
|
||||
masterOffset = numBlends + (i* numDeltas)
|
||||
blendList = [newVal] + args[masterOffset:masterOffset+numDeltas]
|
||||
value[i] = blendList
|
||||
j = 1
|
||||
while j < numMasters:
|
||||
masterOffset = numReturnValues + (i* numDeltas)
|
||||
mi = masterOffset +(j-1)
|
||||
delta = args[i] + args[mi]
|
||||
blendList[j]= delta + prevValueList[j]
|
||||
j += 1
|
||||
prevValueList = blendList
|
||||
i += 1
|
||||
return value
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont sfntVersion="OTTO" ttLibVersion="3.5">
|
||||
<ttFont sfntVersion="OTTO" ttLibVersion="3.18">
|
||||
|
||||
<GlyphOrder>
|
||||
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||
@ -12,12 +12,12 @@
|
||||
<!-- Most of this table will be recalculated by the compiler -->
|
||||
<tableVersion value="1.0"/>
|
||||
<fontRevision value="1.00099"/>
|
||||
<checkSumAdjustment value="0x5f8802c6"/>
|
||||
<checkSumAdjustment value="0x3e077bd3"/>
|
||||
<magicNumber value="0x5f0f3cf5"/>
|
||||
<flags value="00000000 00000011"/>
|
||||
<unitsPerEm value="1000"/>
|
||||
<created value="Fri Jan 6 11:41:20 2017"/>
|
||||
<modified value="Fri Jan 6 09:34:43 2017"/>
|
||||
<modified value="Thu Jan 12 22:37:13 2017"/>
|
||||
<xMin value="51"/>
|
||||
<yMin value="-115"/>
|
||||
<xMax value="560"/>
|
||||
@ -68,24 +68,24 @@
|
||||
<FontDict index="0">
|
||||
<Private>
|
||||
<BlueValues>
|
||||
<blend value="-20 -15 -13 -20 -15 -13"/>
|
||||
<blend value="0 0 0 0 0 0"/>
|
||||
<blend value="487 474 470 487 474 470"/>
|
||||
<blend value="503 487 483 503 487 483"/>
|
||||
<blend value="515 527 534 515 527 534"/>
|
||||
<blend value="531 540 547 531 540 547"/>
|
||||
<blend value="536 550 556 536 550 556"/>
|
||||
<blend value="552 563 569 552 563 569"/>
|
||||
<blend value="624 647 654 624 647 654"/>
|
||||
<blend value="640 660 667 640 660 667"/>
|
||||
<blend value="652 670 677 652 670 677"/>
|
||||
<blend value="672 685 690 672 685 690"/>
|
||||
<blend value="711 730 738 711 730 738"/>
|
||||
<blend value="731 750 758 731 750 758"/>
|
||||
<blend value="-20 5 7 0 5 7"/>
|
||||
<blend value="0 -5 -7 0 -5 -7"/>
|
||||
<blend value="487 -13 -17 0 -13 -17"/>
|
||||
<blend value="503 -3 -3 0 -3 -3"/>
|
||||
<blend value="515 28 39 0 28 39"/>
|
||||
<blend value="531 -3 -3 0 -3 -3"/>
|
||||
<blend value="536 5 4 0 5 4"/>
|
||||
<blend value="552 -3 -3 0 -3 -3"/>
|
||||
<blend value="624 12 13 0 12 13"/>
|
||||
<blend value="640 -3 -3 0 -3 -3"/>
|
||||
<blend value="652 -2 -2 0 -2 -2"/>
|
||||
<blend value="672 -5 -7 0 -5 -7"/>
|
||||
<blend value="711 6 9 0 6 9"/>
|
||||
<blend value="731 0 0 0 0 0"/>
|
||||
</BlueValues>
|
||||
<OtherBlues>
|
||||
<blend value="-232 -250 -255 -232 -250 -255"/>
|
||||
<blend value="-222 -240 -245 -222 -240 -245"/>
|
||||
<blend value="-232 -18 -23 0 -18 -23"/>
|
||||
<blend value="-222 0 0 0 0 0"/>
|
||||
</OtherBlues>
|
||||
<FamilyBlues value="-20 0 473 491 525 540 549 562 644 659 669 689 729 749"/>
|
||||
<FamilyOtherBlues value="-249 -239"/>
|
||||
@ -93,18 +93,18 @@
|
||||
<BlueShift value="7"/>
|
||||
<BlueFuzz value="0"/>
|
||||
<StdHW>
|
||||
<blend value="74 55 26 50 46 26"/>
|
||||
<blend value="74 -19 -48 -24 -28 -48"/>
|
||||
</StdHW>
|
||||
<StdVW>
|
||||
<blend value="190 80 28 190 80 28"/>
|
||||
<blend value="190 -110 -162 0 -110 -162"/>
|
||||
</StdVW>
|
||||
<StemSnapH>
|
||||
<blend value="60 40 20 38 32 20"/>
|
||||
<blend value="74 55 26 50 46 26"/>
|
||||
<blend value="60 -20 -40 -22 -28 -40"/>
|
||||
<blend value="74 1 -8 -2 0 -8"/>
|
||||
</StemSnapH>
|
||||
<StemSnapV>
|
||||
<blend value="190 80 28 190 80 28"/>
|
||||
<blend value="200 90 32 200 90 32"/>
|
||||
<blend value="190 -110 -162 0 -110 -162"/>
|
||||
<blend value="200 0 -6 0 0 -6"/>
|
||||
</StemSnapV>
|
||||
</Private>
|
||||
</FontDict>
|
||||
|
Loading…
x
Reference in New Issue
Block a user